From 297b297bc7fc4c7cd263fcbacbd27abb99c87a6f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 14 Nov 2020 10:00:01 -0500 Subject: [PATCH 01/91] devel release --- Changes | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 98a47d3a3..a531066d0 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,10 @@ Revision history for Verilator The contributors that suggested a given feature are shown in []. Thanks! + +* Verilator 4.105 devel + + * Verilator 4.104 2020-11-14 *** Support queue and associative array 'with' statements. (#2616) diff --git a/configure.ac b/configure.ac index 6b165fcc0..dada8de1e 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### devel]) -AC_INIT([Verilator],[4.104 2020-11-14], +AC_INIT([Verilator],[4.105 devel], [https://verilator.org], [verilator],[https://verilator.org]) # When releasing, also update header of Changes file From f94fcaa8e4ccf88da6d43f7afe7908d72c8a48c6 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 14 Nov 2020 10:20:27 -0500 Subject: [PATCH 02/91] Move YYDEBUG into header. No functional change intended. --- src/Makefile_obj.in | 1 - src/V3ParseGrammar.cpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 8b058c7b0..b686d5775 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -94,7 +94,6 @@ LIBS = $(CFG_LIBS) -lm CPPFLAGS += -MMD CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) -I../../include -CPPFLAGS += -DYYDEBUG # Required to get nice error messages #CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool CPPFLAGS += $(COPT) CPPFLAGS += -MP # Only works on recent GCC versions diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 329631792..e49b8f5d8 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -14,6 +14,8 @@ // //************************************************************************* +#define YYDEBUG 1 // Nicer errors + #include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict //====================================================================== From c64cc989f06dcf981d528ce96cdc211aec3a88b3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 14 Nov 2020 12:22:15 -0500 Subject: [PATCH 03/91] verilator_gantt: Show CPU physical info. --- bin/verilator_gantt | 76 ++++++++++++++++++++++++++++++++++++--- test_regress/t/t_gantt.pl | 2 +- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/bin/verilator_gantt b/bin/verilator_gantt index cc7f0fbba..1de46b104 100755 --- a/bin/verilator_gantt +++ b/bin/verilator_gantt @@ -60,6 +60,7 @@ sub process { my $filename = shift; read_data($filename); + read_cpuinfo(); report(); } @@ -70,7 +71,7 @@ sub read_data { %Global = (rdtsc_cycle_time => 0); - my $fh = IO::File->new ($filename) or die "%Error: $! $filename,"; + my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,"; while (my $line = $fh->getline) { if ($line =~ m/VLPROF mtask\s(\d+)\sstart\s(\d+)\send\s(\d+)\selapsed\s(\d+)\spredict_time\s(\d+)\scpu\s(\d+)\son thread (\d+)/) { my $mtask = $1; @@ -113,6 +114,27 @@ sub read_data { } } +sub read_cpuinfo { + my $filename = "/proc/cpuinfo"; + my $fh = IO::File->new("<$filename") or return; + my $cpu; + while (my $line = $fh->getline) { + chomp $line; + if ($line =~ m/^processor\s*:\s*(\d+)\s*$/) { + $cpu = $1; + } + if ($cpu && $line =~ m/^([a-z_ ]+)\s*:\s*(.*)$/) { + my ($term, $value) = ($1, $2); + $term =~ s/\s+$//; + $term =~ s/\s+/_/; + $value =~ s/\s+$//; + $Global{cpuinfo}{$cpu}{$term} = $value; + } + } +} + +####################################################################### + sub report { print "Verilator Gantt report\n"; @@ -162,9 +184,9 @@ sub report { printf " Total eval time = %d rdtsc ticks\n", $Global{last_end}; printf " Longest mtask time = %d rdtsc ticks\n", $long_mtask_time; printf " All-thread mtask time = %d rdtsc ticks\n", $mt_mtask_time; - my $long_efficiency = $long_mtask_time/($Global{last_end}); + my $long_efficiency = $long_mtask_time/($Global{last_end} || 1); printf " Longest-thread efficiency = %0.1f%%\n", $long_efficiency*100; - my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads); + my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads || 1); printf " All-thread efficiency = %0.1f%%\n", $mt_efficiency*100; printf " All-thread speedup = %0.1f\n", $mt_efficiency*$nthreads; if ($Global{rdtsc_cycle_time} > 0) { @@ -210,13 +232,58 @@ sub report { printf " mean = %0.3f\n", $mean; printf " stddev = %0.3f\n", $stddev; printf " e ^ stddev = %0.3f\n", exp($stddev); - print "\n"; + + report_cpus(); if ($nthreads > $ncpus) { + print "\n"; print "%Warning: There were fewer CPUs ($ncpus) then threads ($nthreads).\n"; print " : See docs on use of numactl.\n"; + } else { + if ($Global{cpu_socket_cores_warning}) { + print "\n"; + print "%Warning: Multiple threads scheduled on same hyperthreaded core.\n"; + print " : See docs on use of numactl.\n"; + } + if ($Global{cpu_sockets_warning}) { + print "\n"; + print "%Warning: Threads scheduled on multiple sockets.\n"; + print " : See docs on use of numactl.\n"; + } + } + print "\n"; +} + +sub report_cpus { + print "\nCPUs:\n"; + # Test - show all cores + # for (my $i=0; $i<73; ++$i) { $Global{cpus}{$i} ||= {cpu_time => 0}; } + + $Global{cpu_sockets} ||= {}; + $Global{cpu_socket_cores} ||= {}; + + foreach my $cpu (sort {$a <=> $b} keys %{$Global{cpus}}) { + printf " cpu %d: ", $cpu; + printf "cpu_time=%d", $Global{cpus}{$cpu}{cpu_time}; + + my $socket = $Global{cpuinfo}{$cpu}{physical_id}; + $Global{cpu_sockets}{$socket}++ if defined $socket; + printf " socket=%d", $socket if defined $socket; + + my $core = $Global{cpuinfo}{$cpu}{core_id}; + $Global{cpu_socket_cores}{$socket."__".$core}++ if defined $socket && defined $core; + printf " core=%d", $core if defined $core; + + my $model = $Global{cpuinfo}{$cpu}{model_name}; + printf " %s", $model if defined $model; print "\n"; } + + $Global{cpu_sockets_warning} = 1 + if (scalar keys %{$Global{cpu_sockets}} > 1); + foreach my $scn (values %{$Global{cpu_socket_cores}}) { + $Global{cpu_socket_cores_warning} = 1 if $scn > 1; + } } sub report_graph { @@ -230,6 +297,7 @@ sub report_graph { } # One more step so we can fit more labels $time_per = int($time_per/2); + $time_per ||= 1; } my ($graph, $conflicts) = _make_graph($time_per); diff --git a/test_regress/t/t_gantt.pl b/test_regress/t/t_gantt.pl index e38cd63b7..77b8714a4 100755 --- a/test_regress/t/t_gantt.pl +++ b/test_regress/t/t_gantt.pl @@ -40,7 +40,7 @@ execute( run(cmd => ["$ENV{VERILATOR_ROOT}/bin/verilator_gantt", "$Self->{obj_dir}/profile_threads.dat", "--vcd $Self->{obj_dir}/profile_threads.vcd", - "> $Self->{obj_dir}/gantt.log"], + "| tee $Self->{obj_dir}/gantt.log"], verilator_run => 1, ); From e74cc32f2d372b551055f94c8b0ca54a1361811d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 14 Nov 2020 16:13:06 -0500 Subject: [PATCH 04/91] Add internal assertion that VarScopes properly formed. --- src/V3Broken.cpp | 18 ++++++++++++++++++ src/V3Descope.cpp | 1 + src/V3Global.h | 3 +++ src/V3LinkDot.cpp | 1 + 4 files changed, 23 insertions(+) diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index f017c7fe5..de3a674b8 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -238,6 +238,8 @@ public: // Broken state, as a visitor of each AstNode class BrokenCheckVisitor : public AstNVisitor { + bool m_inScope = false; // Under AstScope + private: static void checkWidthMin(const AstNode* nodep) { UASSERT_OBJ(nodep->width() == nodep->widthMin() @@ -278,6 +280,22 @@ private: && !VN_CAST(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()), nodep, "Assignment LHS is not an lvalue"); } + virtual void visit(AstScope* nodep) override { + VL_RESTORER(m_inScope); + { + m_inScope = true; + processAndIterate(nodep); + } + } + virtual void visit(AstNodeVarRef* nodep) override { + processAndIterate(nodep); + // m_inScope because some Vars have initial variable references without scopes + // This might false fire with some debug flags, as not certain we don't have temporary + // clear varScopep's during some an infrequent dump just before we re-LinkDot. + UASSERT_OBJ( + !(v3Global.assertScoped() && m_inScope && nodep->varp() && !nodep->varScopep()), nodep, + "VarRef missing VarScope pointer"); + } virtual void visit(AstNode* nodep) override { // Process not just iterate processAndIterate(nodep); diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 9cf15822b..dcaddcae5 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -304,6 +304,7 @@ public: void V3Descope::descopeAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); + v3Global.assertScoped(false); { DescopeVisitor visitor(nodep); } // Destruct before checking V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } diff --git a/src/V3Global.h b/src/V3Global.h index ec4b6d0f1..41afa569d 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -95,6 +95,7 @@ class V3Global { int m_debugFileNumber = 0; // Number to append to debug files created bool m_assertDTypesResolved = false; // Tree should have dtypep()'s + bool m_assertScoped = false; // Tree is scoped bool m_constRemoveXs = false; // Const needs to strip any Xs bool m_needHeavy = false; // Need verilated_heavy.h include bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols @@ -125,6 +126,7 @@ public: AstNetlist* rootp() const { return m_rootp; } VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; } bool assertDTypesResolved() const { return m_assertDTypesResolved; } + bool assertScoped() const { return m_assertScoped; } // METHODS void readFiles(); @@ -132,6 +134,7 @@ public: static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0, bool doDump = true); void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; } + void assertScoped(bool flag) { m_assertScoped = flag; } void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; } bool constRemoveXs() const { return m_constRemoveXs; } void constRemoveXs(bool flag) { m_constRemoveXs = flag; } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 7877f7b17..a7dac78db 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2947,6 +2947,7 @@ void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) { // Well after the initial link when we're ready to operate on the flat design, // process AstScope's. This needs to be separate pass after whole hierarchy graph created. LinkDotScopeVisitor visitors(rootp, &state); + v3Global.assertScoped(true); if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree")); } From f6f7684ccd7338be4c1c7f9ffdc639f78a92aa97 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 15 Nov 2020 15:40:35 -0500 Subject: [PATCH 05/91] Internal member initialization. No functional change intended. --- include/verilated_imp.h | 4 ++-- include/verilated_sym_props.h | 8 +++----- include/verilated_vpi.cpp | 8 +++----- src/V3Ast.h | 16 +++++----------- src/V3AstNodes.h | 5 ++--- src/V3File.cpp | 3 +-- src/V3FileLine.cpp | 9 +-------- src/V3FileLine.h | 28 ++++++++++------------------ src/V3GraphPathChecker.cpp | 3 +-- src/V3GraphPathChecker.h | 2 +- src/V3OrderGraph.h | 13 +++++-------- src/V3Stats.h | 12 +++++------- 12 files changed, 39 insertions(+), 72 deletions(-) diff --git a/include/verilated_imp.h b/include/verilated_imp.h index a84aa13ba..afbcc76b0 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -268,8 +268,8 @@ protected: // MEMBERS union VerilatedImpU { ///< Enclose in an union to call ctor/dtor manually VerilatedImpData v; - VerilatedImpU() {} - ~VerilatedImpU() {} + VerilatedImpU() {} // Can't be = default; + ~VerilatedImpU() {} // Can't be = default; }; static VerilatedImpU s_s; ///< Static Singleton; One and only static this diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h index ca2689108..9d3b13732 100644 --- a/include/verilated_sym_props.h +++ b/include/verilated_sym_props.h @@ -37,15 +37,13 @@ // See also V3Ast::VNumRange class VerilatedRange { - int m_left; - int m_right; + int m_left = 0; + int m_right = 0; protected: friend class VerilatedVarProps; friend class VerilatedScope; - VerilatedRange() - : m_left{0} - , m_right{0} {} + VerilatedRange() {} VerilatedRange(int left, int right) : m_left{left} , m_right{right} {} diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index e1a2977a3..58e17aa87 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -211,7 +211,7 @@ public: class VerilatedVpioVar : public VerilatedVpio { const VerilatedVar* m_varp; const VerilatedScope* m_scopep; - vluint8_t* m_prevDatap; // Previous value of data, for cbValueChange + vluint8_t* m_prevDatap = nullptr; // Previous value of data, for cbValueChange union { vluint8_t u8[4]; vluint32_t u32; @@ -219,7 +219,7 @@ class VerilatedVpioVar : public VerilatedVpio { vluint32_t m_entSize; // memoized variable size protected: void* m_varDatap; // varp()->datap() adjusted for array entries - vlsint32_t m_index; + vlsint32_t m_index = 0; const VerilatedRange& get_range() const { // Determine number of dimensions and return outermost return (m_varp->dims() > 1) ? m_varp->unpacked() : m_varp->packed(); @@ -228,9 +228,7 @@ protected: public: VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep) : m_varp{varp} - , m_scopep{scopep} - , m_index{0} { - m_prevDatap = nullptr; + , m_scopep{scopep} { m_mask.u32 = VL_MASK_I(varp->packed().elements()); m_entSize = varp->entSize(); m_varDatap = varp->datap(); diff --git a/src/V3Ast.h b/src/V3Ast.h index 0c37dde78..ff2b5a8bc 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -977,8 +977,8 @@ inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) { class VNumRange { public: - int m_hi; // HI part, HI always >= LO - int m_lo; // LO + int m_hi = 0; // HI part, HI always >= LO + int m_lo = 0; // LO union { int mu_flags; struct { @@ -1001,19 +1001,13 @@ public: // class LeftRight {}; VNumRange() - : m_hi{0} - , m_lo{0} - , mu_flags{0} {} + : mu_flags{0} {} VNumRange(int hi, int lo, bool littleEndian) - : m_hi{0} - , m_lo{0} - , mu_flags{0} { + : mu_flags{0} { init(hi, lo, littleEndian); } VNumRange(LeftRight, int left, int right) - : m_hi{0} - , m_lo{0} - , mu_flags{0} { + : mu_flags{0} { init((right > left) ? right : left, (right > left) ? left : right, (right > left)); } ~VNumRange() {} diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 94cbc43e2..165f60dec 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -5348,7 +5348,7 @@ public: class AstRand : public AstNodeTermop { // Return a random number, based upon width() private: - bool m_reset; // Random reset, versus always random + bool m_reset = false; // Random reset, versus always random public: AstRand(FileLine* fl, AstNodeDType* dtp, bool reset) : ASTGEN_SUPER(fl) @@ -5356,8 +5356,7 @@ public: dtypep(dtp); } explicit AstRand(FileLine* fl) - : ASTGEN_SUPER(fl) - , m_reset{false} {} + : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(Rand) virtual string emitVerilog() override { return "%f$random"; } virtual string emitC() override { diff --git a/src/V3File.cpp b/src/V3File.cpp index ed7749481..f2cc0f6a9 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -67,13 +67,12 @@ class V3FileDependImp { class DependFile { // A single file bool m_target; // True if write, else read - bool m_exists; + bool m_exists = true; string m_filename; // Filename struct stat m_stat; // Stat information public: DependFile(const string& filename, bool target) : m_target{target} - , m_exists{true} , m_filename{filename} { m_stat.st_ctime = 0; m_stat.st_mtime = 0; diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 5d048f101..a68d2348d 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -143,14 +143,7 @@ std::ostream& operator<<(std::ostream& os, VFileContent* contentp) { // FileLine class functions // Sort of a singleton -FileLine::FileLine(FileLine::EmptySecret) - : m_firstLineno{0} - , m_firstColumn{0} - , m_lastLineno{0} - , m_lastColumn{0} - , m_contentLineno{0} - , m_contentp{nullptr} - , m_parent{nullptr} { +FileLine::FileLine(FileLine::EmptySecret) { m_filenameno = singleton().nameToNumber(FileLine::builtInFilename()); m_warnOn = 0; diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 757a4275c..e6c1941ff 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -93,16 +93,16 @@ class FileLine { // MEMBERS // Columns here means number of chars from beginning (i.e. tabs count as one) - int m_firstLineno; // `line corrected token's first line number - int m_firstColumn; // `line corrected token's first column number - int m_lastLineno; // `line corrected token's last line number - int m_lastColumn; // `line corrected token's last column number + int m_firstLineno = 0; // `line corrected token's first line number + int m_firstColumn = 0; // `line corrected token's first column number + int m_lastLineno = 0; // `line corrected token's last line number + int m_lastColumn = 0; // `line corrected token's last column number int m_filenameno; // `line corrected filename number - int m_contentLineno; // Line number within source stream - VFileContent* m_contentp; // Source text contents line is within - FileLine* m_parent; // Parent line that included this line + int m_contentLineno = 0; // Line number within source stream + VFileContent* m_contentp = nullptr; // Source text contents line is within + FileLine* m_parent = nullptr; // Parent line that included this line std::bitset m_warnOn; - bool m_waive; // Waive warning + bool m_waive = false; // Waive warning protected: // User routines should never need to change line numbers @@ -126,16 +126,8 @@ private: public: explicit FileLine(const string& filename) - : m_firstLineno{0} - , m_firstColumn{0} - , m_lastLineno{0} - , m_lastColumn{0} - , m_filenameno{singleton().nameToNumber(filename)} - , m_contentLineno{0} - , m_contentp{nullptr} - , m_parent{nullptr} - , m_warnOn{defaultFileLine().m_warnOn} - , m_waive{false} {} + : m_filenameno{singleton().nameToNumber(filename)} + , m_warnOn{defaultFileLine().m_warnOn} {} explicit FileLine(FileLine* fromp) : m_firstLineno{fromp->m_firstLineno} , m_firstColumn{fromp->m_firstColumn} diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp index 2497f35ca..bc8401c90 100644 --- a/src/V3GraphPathChecker.cpp +++ b/src/V3GraphPathChecker.cpp @@ -51,8 +51,7 @@ struct GraphPCNode { // GraphPathChecker implementation GraphPathChecker::GraphPathChecker(const V3Graph* graphp, V3EdgeFuncP edgeFuncp) - : GraphAlg{graphp, edgeFuncp} - , m_generation{0} { + : GraphAlg{graphp, edgeFuncp} { for (V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { // Setup tracking structure for each node. If delete a vertex // there would be a leak, but ok as accept only const V3Graph*'s. diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h index e50daf064..b32e360c1 100644 --- a/src/V3GraphPathChecker.h +++ b/src/V3GraphPathChecker.h @@ -34,7 +34,7 @@ class GraphPathChecker : GraphAlg { // the graph. Each node is marked with the last generation that scanned // it, to enable asserting there are no cycles, and to avoid recursing // through the same node twice while searching for a path. - vluint64_t m_generation; + vluint64_t m_generation = 0; public: // CONSTRUCTORS diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index a0cc562ef..e24db578a 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -124,7 +124,7 @@ public: class OrderEitherVertex : public V3GraphVertex { AstScope* m_scopep; // Scope the vertex is in AstSenTree* m_domainp; // Clock domain (nullptr = to be computed as we iterate) - bool m_isFromInput; // From input, or derived therefrom (conservatively false) + bool m_isFromInput = false; // From input, or derived therefrom (conservatively false) protected: OrderEitherVertex(V3Graph* graphp, const OrderEitherVertex& old) : V3GraphVertex{graphp, old} @@ -136,8 +136,7 @@ public: OrderEitherVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp) : V3GraphVertex{graphp} , m_scopep{scopep} - , m_domainp{domainp} - , m_isFromInput{false} {} + , m_domainp{domainp} {} virtual ~OrderEitherVertex() override {} virtual OrderEitherVertex* clone(V3Graph* graphp) const override = 0; // Methods @@ -200,8 +199,8 @@ public: class OrderVarVertex : public OrderEitherVertex { AstVarScope* m_varScp; - bool m_isClock; // Used as clock - bool m_isDelayed; // Set in a delayed assignment + bool m_isClock = false; // Used as clock + bool m_isDelayed = false; // Set in a delayed assignment protected: OrderVarVertex(V3Graph* graphp, const OrderVarVertex& old) : OrderEitherVertex{graphp, old} @@ -212,9 +211,7 @@ protected: public: OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderEitherVertex{graphp, scopep, nullptr} - , m_varScp{varScp} - , m_isClock{false} - , m_isDelayed{false} {} + , m_varScp{varScp} {} virtual ~OrderVarVertex() override {} virtual OrderVarVertex* clone(V3Graph* graphp) const override = 0; virtual OrderVEdgeType type() const override = 0; diff --git a/src/V3Stats.h b/src/V3Stats.h index ad5985110..5b6129e63 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -28,12 +28,11 @@ class AstNetlist; class VDouble0 { // Double counter, initializes to zero for easy use - double m_d; ///< Count of occurrences/ value + double m_d = 0.0; ///< Count of occurrences/ value public: // METHODS - VDouble0() - : m_d{0.0} {} - ~VDouble0() {} + VDouble0() = default; + ~VDouble0() = default; // Implicit conversion operators: explicit VDouble0(const vluint64_t v) @@ -73,7 +72,7 @@ class V3Statistic { string m_stage; ///< Runtime stage bool m_sumit; ///< Do summation of similar stats bool m_perf; ///< Performance section - bool m_printit; ///< Print the results + bool m_printit = true; ///< Print the results public: // METHODS string stage() const { return m_stage; } @@ -94,8 +93,7 @@ public: , m_count{count} , m_stage{stage} , m_sumit{sumit} - , m_perf{perf} - , m_printit{true} {} + , m_perf{perf} {} virtual ~V3Statistic() {} }; From f4ef4ad9f3056e3a30dff37e9239e7f0413ec6a9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 15 Nov 2020 16:21:26 -0500 Subject: [PATCH 06/91] Internals: Favor std::array where easy. No functional change intended. --- src/V3Case.cpp | 2 +- src/V3Error.cpp | 4 ++-- src/V3Error.h | 7 ++++--- src/V3GraphPathChecker.cpp | 2 +- src/V3LinkDot.cpp | 2 +- src/V3Order.cpp | 4 ++-- src/V3Os.cpp | 10 +++++----- src/V3Os.h | 2 +- src/V3Partition.cpp | 10 +++++----- src/V3SplitVar.cpp | 3 ++- src/V3Stats.cpp | 2 +- src/V3String.cpp | 11 +++++------ src/V3Task.cpp | 2 +- src/V3Undriven.cpp | 2 +- 14 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/V3Case.cpp b/src/V3Case.cpp index a9a0a3511..99f9ba8c6 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -133,7 +133,7 @@ private: int m_caseItems = 0; // Number of caseItem unique values bool m_caseNoOverlapsAllCovered = false; // Proven to be synopsys parallel_case compliant // For each possible value, the case branch we need - AstNode* m_valueItem[1 << CASE_OVERLAP_WIDTH]; + std::array m_valueItem; // METHODS VL_DEBUG_FUNC; // Declare debug() diff --git a/src/V3Error.cpp b/src/V3Error.cpp index e60ce5667..84df9285f 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -36,9 +36,9 @@ std::ostringstream V3Error::s_errorStr; // Error string being formed V3ErrorCode V3Error::s_errorCode = V3ErrorCode::EC_FATAL; bool V3Error::s_errorContexted = false; bool V3Error::s_errorSuppressed = false; -bool V3Error::s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; +std::array V3Error::s_describedEachWarn; +std::array V3Error::s_pretendError; bool V3Error::s_describedWarnings = false; -bool V3Error::s_pretendError[V3ErrorCode::_ENUM_MAX]; V3Error::MessagesSet V3Error::s_messages; V3Error::ErrorExitCb V3Error::s_errorExitCb = nullptr; diff --git a/src/V3Error.h b/src/V3Error.h index a1846e8e4..dc74e55ad 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -224,9 +224,10 @@ class V3Error { private: static bool s_describedWarnings; // Told user how to disable warns - static bool - s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; // Told user specifics about this warning - static bool s_pretendError[V3ErrorCode::_ENUM_MAX]; // Pretend this warning is an error + static std::array + s_describedEachWarn; // Told user specifics about this warning + static std::array + s_pretendError; // Pretend this warning is an error static int s_debugDefault; // Option: --debugi Default debugging level static int s_errorLimit; // Option: --error-limit Number of errors before exit static bool s_warnFatal; // Option: --warnFatal Warnings are fatal diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp index bc8401c90..05d14a167 100644 --- a/src/V3GraphPathChecker.cpp +++ b/src/V3GraphPathChecker.cpp @@ -32,7 +32,7 @@ struct GraphPCNode { // // Unlike the LogicMTasks's, we have no cost info for the generic graph // accepted by GraphPathChecker, so assume each node has unit cost. - vluint32_t m_cp[GraphWay::NUM_WAYS]; + std::array m_cp; // Detect if we've seen this node before in a given recursive // operation. We'll use this in pathExistsInternal() to avoid checking diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index a7dac78db..850ea63e2 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -153,7 +153,7 @@ private: VSymEnt* m_dunitEntp; // $unit entry NameScopeSymMap m_nameScopeSymMap; // Map of scope referenced by non-pretty textual name ImplicitNameSet m_implicitNameSet; // For [module][signalname] if we can implicitly create it - ScopeAliasMap m_scopeAliasMap[SAMN__MAX]; // Map of aliases + std::array m_scopeAliasMap; // Map of aliases IfaceVarSyms m_ifaceVarSyms; // List of AstIfaceRefDType's to be imported IfaceModSyms m_ifaceModSyms; // List of AstIface+Symbols to be processed bool m_forPrimary; // First link diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 7c555cd7f..862e7d366 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -190,7 +190,7 @@ class OrderUser { // Stored in AstVarScope::user1p, a list of all the various vertices // that can exist for one given variable private: - OrderVarVertex* m_vertexp[WV_MAX]; // Vertex of each type (if non nullptr) + std::array m_vertexp; // Vertex of each type (if non nullptr) public: // METHODS OrderVarVertex* newVarUserVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varscp, @@ -686,7 +686,7 @@ protected: private: // STATS - VDouble0 m_statCut[OrderVEdgeType::_ENUM_END]; // Count of each edge type cut + std::array m_statCut; // Count of each edge type cut // TYPES enum VarUsage : uint8_t { VU_NONE = 0, VU_CON = 1, VU_GEN = 2 }; diff --git a/src/V3Os.cpp b/src/V3Os.cpp index 299d5c104..b6d7375e5 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -252,12 +252,12 @@ void V3Os::unlinkRegexp(const string& dir, const string& regexp) { //###################################################################### // METHODS (random) -vluint64_t V3Os::rand64(vluint64_t* statep) { +vluint64_t V3Os::rand64(std::array& stater) { // Xoroshiro128+ algorithm - vluint64_t result = statep[0] + statep[1]; - statep[1] ^= statep[0]; - statep[0] = (((statep[0] << 55) | (statep[0] >> 9)) ^ statep[1] ^ (statep[1] << 14)); - statep[1] = (statep[1] << 36) | (statep[1] >> 28); + vluint64_t result = stater[0] + stater[1]; + stater[1] ^= stater[0]; + stater[0] = (((stater[0] << 55) | (stater[0] >> 9)) ^ stater[1] ^ (stater[1] << 14)); + stater[1] = (stater[1] << 36) | (stater[1] >> 28); return result; } diff --git a/src/V3Os.h b/src/V3Os.h index a107f36dc..8c328c89b 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -55,7 +55,7 @@ public: static void unlinkRegexp(const string& dir, const string& regexp); // METHODS (random) - static vluint64_t rand64(vluint64_t* statep); + static vluint64_t rand64(std::array& stater); static string trueRandom(size_t size); // METHODS (time & performance) diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index abfb6ce0d..978587be2 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -306,7 +306,7 @@ private: } void go() { // Generate a pseudo-random graph - vluint64_t rngState[2] = {0x12345678ULL, 0x9abcdef0ULL}; + std::array rngState = {0x12345678ULL, 0x9abcdef0ULL}; // Create 50 vertices for (auto& i : m_vx) i = new V3GraphVertex(&m_graph); // Create 250 edges at random. Edges must go from @@ -425,7 +425,7 @@ private: // Cost of critical paths going FORWARD from graph-start to the start // of this vertex, and also going REVERSE from the end of the graph to // the end of the vertex. Same units as m_cost. - uint32_t m_critPathCost[GraphWay::NUM_WAYS]; + std::array m_critPathCost; uint32_t m_serialId; // Unique MTask ID number @@ -443,7 +443,7 @@ private: // relatives in longest-to-shortest CP order. We rely on this ordering // in more than one place. typedef SortByValueMap EdgeSet; - EdgeSet m_edges[GraphWay::NUM_WAYS]; + std::array m_edges; public: // CONSTRUCTORS @@ -2252,8 +2252,8 @@ void V3Partition::debugMTaskGraphStats(const V3Graph* graphp, const string& stag UINFO(4, " Stats for " << stage << endl); uint32_t mtaskCount = 0; uint32_t totalCost = 0; - uint32_t mtaskCostHist[32]; - memset(mtaskCostHist, 0, sizeof(mtaskCostHist)); + std::array mtaskCostHist; + mtaskCostHist.fill(0); for (const V3GraphVertex* mtaskp = graphp->verticesBeginp(); mtaskp; mtaskp = mtaskp->verticesNextp()) { diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 38ea0da47..9abdbe246 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -1005,7 +1005,8 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { } UASSERT_OBJ(varp->attrSplitVar(), varp, "split_var attribute must be attached"); - AstConst* consts[2] = {VN_CAST(nodep->lsbp(), Const), VN_CAST(nodep->widthp(), Const)}; + std::array consts + = {VN_CAST(nodep->lsbp(), Const), VN_CAST(nodep->widthp(), Const)}; if (consts[0] && consts[1]) { // OK refit->second.append( PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lsb(), diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 9562aa8a0..a73df13e4 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -49,7 +49,7 @@ private: std::vector m_statTypeCount; // Nodes of given type VDouble0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type - VDouble0 m_statPred[VBranchPred::_ENUM_END]; // Nodes of given type + std::array m_statPred; // Nodes of given type VDouble0 m_statInstr; // Instruction count VDouble0 m_statInstrFast; // Instruction count, non-slow() eval functions only std::vector m_statVarWidths; // Variables of given width diff --git a/src/V3String.cpp b/src/V3String.cpp index 12db74f7c..5bf79a99a 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -306,7 +306,7 @@ uint64_t VHashSha256::digestUInt64() { } string VHashSha256::digestHex() { - static const char digits[16 + 1] = "0123456789abcdef"; + static const char* digits = "0123456789abcdef"; const string& binhash = digestBinary(); string out; out.reserve(70); @@ -322,8 +322,7 @@ string VHashSha256::digestSymbol() { // has + and / for last two digits, but need C symbol, and we also // avoid conflicts with use of _, so use "AB" at the end. // Thus this function is non-reversible. - static const char digits[64 + 1] - = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"; + static const char* digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"; const string& binhash = digestBinary(); string out; out.reserve(28); @@ -408,9 +407,9 @@ VSpellCheck::EditDistance VSpellCheck::editDistance(const string& s, const strin if (sLen >= LENGTH_LIMIT) return sLen; if (tLen >= LENGTH_LIMIT) return tLen; - static EditDistance s_v_two_ago[LENGTH_LIMIT + 1]; - static EditDistance s_v_one_ago[LENGTH_LIMIT + 1]; - static EditDistance s_v_next[LENGTH_LIMIT + 1]; + static std::array s_v_two_ago; + static std::array s_v_one_ago; + static std::array s_v_next; for (size_t i = 0; i < sLen + 1; i++) s_v_one_ago[i] = i; diff --git a/src/V3Task.cpp b/src/V3Task.cpp index f6a0c4a3c..9d210679e 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1580,7 +1580,7 @@ bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& fr } const char* V3Task::dpiTemporaryVarSuffix() { - static const char suffix[] = "__Vcvt"; + static const char* suffix = "__Vcvt"; return suffix; } diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 2e5dc239d..fdf90654c 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -237,7 +237,7 @@ private: AstUser2InUse m_inuser2; // STATE - std::vector m_entryps[3]; // Nodes to delete when we are finished + std::array, 3> m_entryps; // Nodes to delete when finished bool m_inBBox = false; // In black box; mark as driven+used bool m_inContAssign = false; // In continuous assignment bool m_inProcAssign = false; // In procedural assignment From b68038a73f4cc2a2b75ca69dcbdde4b4b680c745 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 15 Nov 2020 17:23:02 -0500 Subject: [PATCH 07/91] clang-tidy fix. No functional change. --- src/V3String.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/V3String.cpp b/src/V3String.cpp index 5bf79a99a..fcb3ebd38 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -487,10 +487,10 @@ void VSpellCheck::selfTestSuggestOne(bool matches, const string& c, const string speller.pushCandidate(c); string got = speller.bestCandidateInfo(goal, gdist /*ref*/); if (matches) { - UASSERT_SELFTEST(string, got, c); + UASSERT_SELFTEST(const string&, got, c); UASSERT_SELFTEST(EditDistance, gdist, dist); } else { - UASSERT_SELFTEST(string, got, ""); + UASSERT_SELFTEST(const string&, got, ""); } } From efc6fb7fc3c9de0605ec62cc788d0daccd6ca225 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 15 Nov 2020 22:03:06 -0500 Subject: [PATCH 08/91] Internals: Better pack AstNode. No functional change. --- src/V3Ast.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index ff2b5a8bc..b32e504f7 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1395,7 +1395,7 @@ public: do { \ if (nodep) { \ VL_PREFETCH_RD(&((nodep)->m_nextp)); \ - VL_PREFETCH_RD(&((nodep)->m_iterpp)); \ + VL_PREFETCH_RD(&((nodep)->m_type)); \ } \ } while (false) @@ -1408,22 +1408,21 @@ class AstNode { AstNode* m_op3p; // Generic pointer 3 AstNode* m_op4p; // Generic pointer 4 AstNode** m_iterpp; // Pointer to node iterating on, change it if we replace this node. + const AstType m_type; // Node sub-type identifier // ^ ASTNODE_PREFETCH depends on above ordering of members + // padding - 2 extra bytes here after m_type + int m_cloneCnt; // Mark of when userp was set + + AstNodeDType* m_dtypep; // Data type of output or assignment (etc) AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list - - const AstType m_type; // Node sub-type identifier - FileLine* m_fileline; // Where it was declared vluint64_t m_editCount; // When it was last edited static vluint64_t s_editCntGbl; // Global edit counter // Global edit counter, last value for printing * near node #s static vluint64_t s_editCntLast; - AstNodeDType* m_dtypep; // Data type of output or assignment (etc) - AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY) - int m_cloneCnt; // Mark of when userp was set static int s_cloneCntGbl; // Count of which userp is set // Attributes From 26c0e6ba00e2064a4e58795a993f0ccff5f3a5ff Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 16 Nov 2020 07:31:12 -0500 Subject: [PATCH 09/91] Fix missing array include. --- src/V3Error.h | 1 + src/V3Os.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/V3Error.h b/src/V3Error.h index dc74e55ad..a895a9cdb 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -23,6 +23,7 @@ // Limited V3 headers here - this is a base class for Vlc etc #include "V3String.h" +#include #include #include #include diff --git a/src/V3Os.h b/src/V3Os.h index 8c328c89b..21fa583b9 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -20,6 +20,8 @@ #include "config_build.h" #include "verilatedos.h" +#include + // Limited V3 headers here - this is a base class for Vlc etc #include "V3Error.h" From 70b3a599cee4a1fad732bf4c153abb097786c20f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 16 Nov 2020 18:11:27 -0500 Subject: [PATCH 10/91] Fix trace signal names getting hashed (#2643). --- Changes | 4 +- src/V3Ast.cpp | 8 +- src/V3String.cpp | 12 + src/V3String.h | 4 + test_regress/t/t_trace_complex.out | 390 ++++++------ test_regress/t/t_trace_complex.v | 54 +- test_regress/t/t_trace_complex_fst.out | 292 ++++----- test_regress/t/t_trace_complex_params.out | 390 ++++++------ test_regress/t/t_trace_complex_params_fst.out | 292 ++++----- test_regress/t/t_trace_complex_structs.out | 588 +++++++++--------- .../t/t_trace_complex_structs_fst.out | 464 +++++++------- 11 files changed, 1269 insertions(+), 1229 deletions(-) diff --git a/Changes b/Changes index a531066d0..5fed7394f 100644 --- a/Changes +++ b/Changes @@ -5,10 +5,12 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.105 devel +**** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] + * Verilator 4.104 2020-11-14 -*** Support queue and associative array 'with' statements. (#2616) +*** Support queue and associative array 'with' statements (#2616). *** Support queue slicing (#2326). diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index f7bf4eccd..819c0badf 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -127,8 +127,9 @@ string AstNode::encodeName(const string& namein) { } // Shorten names // TODO long term use VName in place of "string name" - VName vname(out); - out = vname.hashedName(); + // Then we also won't need to save the table of hased values + VName vname{out}; + return vname.hashedName(); return out; } @@ -161,7 +162,8 @@ string AstNode::dedotName(const string& namein) { string AstNode::vcdName(const string& namein) { // VCD tracing expects space to separate hierarchy // Dots are reserved for dots the user put in the name - string pretty = namein; + // We earlier hashed all symbols, dehash them so user sees real name + string pretty{VName::dehash(namein)}; string::size_type pos; while ((pos = pretty.find("__DOT__")) != string::npos) pretty.replace(pos, 7, " "); while ((pos = pretty.find('.')) != string::npos) pretty.replace(pos, 1, " "); diff --git a/src/V3String.cpp b/src/V3String.cpp index fcb3ebd38..d8d2c32cd 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -25,6 +25,7 @@ size_t VName::s_minLength = 32; size_t VName::s_maxLength = 0; // Disabled +std::map VName::s_dehashMap; //###################################################################### // Wildcard @@ -377,6 +378,15 @@ void VHashSha256::selfTest() { //###################################################################### // VName +string VName::dehash(const string& in) { + const string::size_type pos = in.find("__Vhsh"); + if (VL_LIKELY(pos == string::npos)) return in; + const string vhsh = in.substr(pos); + const auto& it = s_dehashMap.find(vhsh); + UASSERT(it != s_dehashMap.end(), "String not in reverse hash map '" << vhsh << "'"); + return in.substr(0, pos) + it->second; +} + string VName::hashedName() { if (m_name == "") return ""; if (m_hashed != "") return m_hashed; // Memoized @@ -387,8 +397,10 @@ string VName::hashedName() { VHashSha256 hash(m_name); string suffix = "__Vhsh" + hash.digestSymbol(); if (s_minLength < s_maxLength) { + s_dehashMap[suffix] = m_name.substr(s_minLength); m_hashed = m_name.substr(0, s_minLength) + suffix; } else { + s_dehashMap[suffix] = m_name; m_hashed = suffix; } return m_hashed; diff --git a/src/V3String.h b/src/V3String.h index b02ee587f..a8f8361ad 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -22,6 +22,7 @@ // No V3 headers here - this is a base class for Vlc etc +#include #include #include #include @@ -159,9 +160,11 @@ private: class VName { string m_name; string m_hashed; + static std::map s_dehashMap; // hashed -> original decoder static size_t s_maxLength; // Length at which to start hashing static size_t s_minLength; // Length to preserve if over maxLength + public: // CONSTRUCTORS explicit VName(const string& name) @@ -178,6 +181,7 @@ public: // Length at which to start hashing, 0=disable static void maxLength(size_t flag) { s_maxLength = flag; } static size_t maxLength() { return s_maxLength; } + static string dehash(const string& in); }; //###################################################################### diff --git a/test_regress/t/t_trace_complex.out b/test_regress/t/t_trace_complex.out index 1372dbc2c..e57a057af 100644 --- a/test_regress/t/t_trace_complex.out +++ b/test_regress/t/t_trace_complex.out @@ -1,53 +1,54 @@ $version Generated by VerilatedVcd $end -$date Tue Jan 21 18:15:27 2020 +$date Mon Nov 16 17:48:27 2020 $end $timescale 1ps $end $scope module top $end - $var wire 1 7" clk $end + $var wire 1 = clk $end $scope module $unit $end $var wire 1 # global_bit $end $upscope $end $scope module t $end - $var wire 1 7" clk $end - $var wire 32 + cyc [31:0] $end - $var wire 8 p" unpacked_array(-1) [7:0] $end - $var wire 8 o" unpacked_array(-2) [7:0] $end - $var wire 8 q" unpacked_array(0) [7:0] $end - $var real 64 E! v_arr_real(0) $end - $var real 64 G! v_arr_real(1) $end - $var wire 2 [ v_arrp [2:1] $end - $var wire 4 c v_arrp_arrp [3:0] $end - $var wire 4 k v_arrp_strp [3:0] $end - $var wire 1 ?" v_arru(1) $end - $var wire 1 @" v_arru(2) $end - $var wire 2 s v_arru_arrp(3) [2:1] $end - $var wire 2 t v_arru_arrp(4) [2:1] $end - $var wire 1 O" v_arru_arru(3)(1) $end - $var wire 1 W" v_arru_arru(3)(2) $end - $var wire 1 _" v_arru_arru(4)(1) $end - $var wire 1 g" v_arru_arru(4)(2) $end - $var wire 2 %! v_arru_strp(3) [1:0] $end - $var wire 2 -! v_arru_strp(4) [1:0] $end - $var wire 3 u! v_enumb [2:0] $end - $var wire 6 }! v_enumb2_str [5:0] $end - $var wire 32 e! v_enumed [31:0] $end - $var wire 32 m! v_enumed2 [31:0] $end - $var real 64 5! v_real $end - $var wire 64 3 v_str32x2 [63:0] $end - $var wire 2 C v_strp [1:0] $end - $var wire 4 K v_strp_strp [3:0] $end - $var wire 2 S v_unip_strp [1:0] $end + $var wire 1 G LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND $end + $var wire 1 = clk $end + $var wire 32 $ cyc [31:0] $end + $var wire 8 E unpacked_array(-1) [7:0] $end + $var wire 8 D unpacked_array(-2) [7:0] $end + $var wire 8 F unpacked_array(0) [7:0] $end + $var real 64 1 v_arr_real(0) $end + $var real 64 3 v_arr_real(1) $end + $var wire 2 ( v_arrp [2:1] $end + $var wire 4 ) v_arrp_arrp [3:0] $end + $var wire 4 * v_arrp_strp [3:0] $end + $var wire 1 > v_arru(1) $end + $var wire 1 ? v_arru(2) $end + $var wire 2 + v_arru_arrp(3) [2:1] $end + $var wire 2 , v_arru_arrp(4) [2:1] $end + $var wire 1 @ v_arru_arru(3)(1) $end + $var wire 1 A v_arru_arru(3)(2) $end + $var wire 1 B v_arru_arru(4)(1) $end + $var wire 1 C v_arru_arru(4)(2) $end + $var wire 2 - v_arru_strp(3) [1:0] $end + $var wire 2 . v_arru_strp(4) [1:0] $end + $var wire 3 9 v_enumb [2:0] $end + $var wire 6 : v_enumb2_str [5:0] $end + $var wire 32 7 v_enumed [31:0] $end + $var wire 32 8 v_enumed2 [31:0] $end + $var real 64 / v_real $end + $var wire 64 5 v_str32x2 [63:0] $end + $var wire 2 % v_strp [1:0] $end + $var wire 4 & v_strp_strp [3:0] $end + $var wire 2 ' v_unip_strp [1:0] $end $scope module p2 $end - $var wire 32 )# PARAM [31:0] $end + $var wire 32 H PARAM [31:0] $end $upscope $end $scope module p3 $end - $var wire 32 1# PARAM [31:0] $end + $var wire 32 I PARAM [31:0] $end $upscope $end $scope module unnamedblk1 $end - $var wire 32 '" b [31:0] $end + $var wire 32 ; b [31:0] $end $scope module unnamedblk2 $end - $var wire 32 /" a [31:0] $end + $var wire 32 < a [31:0] $end $upscope $end $upscope $end $upscope $end @@ -57,173 +58,174 @@ $enddefinitions $end #0 1# -b00000000000000000000000000000000 + -b0000000000000000000000000000000000000000000000000000000011111111 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0 5! -r0 E! -r0 G! -b00000000000000000000000000000000 e! -b00000000000000000000000000000000 m! -b000 u! -b000000 }! -b00000000000000000000000000000000 '" -b00000000000000000000000000000000 /" -07" -0?" -0@" -0O" -0W" -0_" -0g" -b00000000 o" -b00000000 p" -b00000000 q" -b00000000000000000000000000000010 )# -b00000000000000000000000000000011 1# +b00000000000000000000000000000000 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0 / +r0 1 +r0 3 +b0000000000000000000000000000000000000000000000000000000011111111 5 +b00000000000000000000000000000000 7 +b00000000000000000000000000000000 8 +b000 9 +b000000 : +b00000000000000000000000000000000 ; +b00000000000000000000000000000000 < +0= +0> +0? +0@ +0A +0B +0C +b00000000 D +b00000000 E +b00000000 F +0G +b00000000000000000000000000000010 H +b00000000000000000000000000000011 I #10 -b00000000000000000000000000000001 + -b0000000000000000000000000000000100000000000000000000000011111110 3 -b11 C -b1111 K -b11 S -b11 [ -b1111 c -b1111 k -b11 s -b11 t -b11 %! -b11 -! -r0.1 5! -r0.2 E! -r0.3 G! -b00000000000000000000000000000001 e! -b00000000000000000000000000000010 m! -b111 u! -b00000000000000000000000000000101 '" -b00000000000000000000000000000101 /" -17" +b00000000000000000000000000000001 $ +b11 % +b1111 & +b11 ' +b11 ( +b1111 ) +b1111 * +b11 + +b11 , +b11 - +b11 . +r0.1 / +r0.2 1 +r0.3 3 +b0000000000000000000000000000000100000000000000000000000011111110 5 +b00000000000000000000000000000001 7 +b00000000000000000000000000000010 8 +b111 9 +b00000000000000000000000000000101 ; +b00000000000000000000000000000101 < +1= #15 -07" +0= #20 -b00000000000000000000000000000010 + -b0000000000000000000000000000001000000000000000000000000011111101 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0.2 5! -r0.4 E! -r0.6 G! -b00000000000000000000000000000010 e! -b00000000000000000000000000000100 m! -b110 u! -b111111 }! -17" +b00000000000000000000000000000010 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0.2 / +r0.4 1 +r0.6 3 +b0000000000000000000000000000001000000000000000000000000011111101 5 +b00000000000000000000000000000010 7 +b00000000000000000000000000000100 8 +b110 9 +b111111 : +1= #25 -07" +0= #30 -b00000000000000000000000000000011 + -b0000000000000000000000000000001100000000000000000000000011111100 3 -b11 C -b1111 K -b11 S -b11 [ -b1111 c -b1111 k -b11 s -b11 t -b11 %! -b11 -! -r0.3 5! -r0.6000000000000001 E! -r0.8999999999999999 G! -b00000000000000000000000000000011 e! -b00000000000000000000000000000110 m! -b101 u! -b110110 }! -17" +b00000000000000000000000000000011 $ +b11 % +b1111 & +b11 ' +b11 ( +b1111 ) +b1111 * +b11 + +b11 , +b11 - +b11 . +r0.3 / +r0.6000000000000001 1 +r0.8999999999999999 3 +b0000000000000000000000000000001100000000000000000000000011111100 5 +b00000000000000000000000000000011 7 +b00000000000000000000000000000110 8 +b101 9 +b110110 : +1= #35 -07" +0= #40 -b00000000000000000000000000000100 + -b0000000000000000000000000000010000000000000000000000000011111011 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0.4 5! -r0.8 E! -r1.2 G! -b00000000000000000000000000000100 e! -b00000000000000000000000000001000 m! -b100 u! -b101101 }! -17" +b00000000000000000000000000000100 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0.4 / +r0.8 1 +r1.2 3 +b0000000000000000000000000000010000000000000000000000000011111011 5 +b00000000000000000000000000000100 7 +b00000000000000000000000000001000 8 +b100 9 +b101101 : +1= #45 -07" +0= #50 -b00000000000000000000000000000101 + -b0000000000000000000000000000010100000000000000000000000011111010 3 -b11 C -b1111 K -b11 S -b11 [ -b1111 c -b1111 k -b11 s -b11 t -b11 %! -b11 -! -r0.5 5! -r1 E! -r1.5 G! -b00000000000000000000000000000101 e! -b00000000000000000000000000001010 m! -b011 u! -b100100 }! -17" +b00000000000000000000000000000101 $ +b11 % +b1111 & +b11 ' +b11 ( +b1111 ) +b1111 * +b11 + +b11 , +b11 - +b11 . +r0.5 / +r1 1 +r1.5 3 +b0000000000000000000000000000010100000000000000000000000011111010 5 +b00000000000000000000000000000101 7 +b00000000000000000000000000001010 8 +b011 9 +b100100 : +1= #55 -07" +0= #60 -b00000000000000000000000000000110 + -b0000000000000000000000000000011000000000000000000000000011111001 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0.6 5! -r1.2 E! -r1.8 G! -b00000000000000000000000000000110 e! -b00000000000000000000000000001100 m! -b010 u! -b011011 }! -17" +b00000000000000000000000000000110 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0.6 / +r1.2 1 +r1.8 3 +b0000000000000000000000000000011000000000000000000000000011111001 5 +b00000000000000000000000000000110 7 +b00000000000000000000000000001100 8 +b010 9 +b011011 : +1= diff --git a/test_regress/t/t_trace_complex.v b/test_regress/t/t_trace_complex.v index 8f283e2e8..14489e9c5 100644 --- a/test_regress/t/t_trace_complex.v +++ b/test_regress/t/t_trace_complex.v @@ -8,21 +8,21 @@ bit global_bit; module t (clk); input clk; - integer cyc=0; + integer cyc=0; typedef struct packed { - bit b1; - bit b0; + bit b1; + bit b0; } strp_t; typedef struct packed { - strp_t x1; - strp_t x0; + strp_t x1; + strp_t x0; } strp_strp_t; typedef union packed { - strp_t x1; - strp_t x0; + strp_t x1; + strp_t x0; } unip_strp_t; typedef bit [2:1] arrp_t; @@ -35,20 +35,20 @@ module t (clk); typedef arrp_t arru_arrp_t [4:3]; typedef strp_t arru_strp_t [4:3]; - strp_t v_strp; - strp_strp_t v_strp_strp; - unip_strp_t v_unip_strp; - arrp_t v_arrp; - arrp_arrp_t v_arrp_arrp; - arrp_strp_t v_arrp_strp; - arru_t v_arru; - arru_arru_t v_arru_arru; - arru_arrp_t v_arru_arrp; - arru_strp_t v_arru_strp; + strp_t v_strp; + strp_strp_t v_strp_strp; + unip_strp_t v_unip_strp; + arrp_t v_arrp; + arrp_arrp_t v_arrp_arrp; + arrp_strp_t v_arrp_strp; + arru_t v_arru; + arru_arru_t v_arru_arru; + arru_arrp_t v_arru_arrp; + arru_strp_t v_arru_strp; real v_real; real v_arr_real [2]; - string v_string; + string v_string; string v_assoc[string]; initial v_assoc["key"] = "value"; @@ -73,6 +73,8 @@ module t (clk); logic [7:0] unpacked_array[-2:0]; + bit LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND; + p #(.PARAM(2)) p2 (); p #(.PARAM(3)) p3 (); @@ -93,18 +95,18 @@ module t (clk); v_enumb <= v_enumb - 1; v_enumb2_str <= {v_enumb, v_enumb}; for (integer b=3; b<=4; b++) begin - v_arru[b] <= ~v_arru[b]; - v_arru_strp[b] <= ~v_arru_strp[b]; - v_arru_arrp[b] <= ~v_arru_arrp[b]; - for (integer a=3; a<=4; a++) begin - v_arru_arru[a][b] = ~v_arru_arru[a][b]; - end + v_arru[b] <= ~v_arru[b]; + v_arru_strp[b] <= ~v_arru_strp[b]; + v_arru_arrp[b] <= ~v_arru_arrp[b]; + for (integer a=3; a<=4; a++) begin + v_arru_arru[a][b] = ~v_arru_arru[a][b]; + end end v_str32x2[0] <= v_str32x2[0] - 1; v_str32x2[1] <= v_str32x2[1] + 1; if (cyc == 5) begin - $write("*-* All Finished *-*\n"); - $finish; + $write("*-* All Finished *-*\n"); + $finish; end end endmodule diff --git a/test_regress/t/t_trace_complex_fst.out b/test_regress/t/t_trace_complex_fst.out index 8b05384c7..e4f264a8e 100644 --- a/test_regress/t/t_trace_complex_fst.out +++ b/test_regress/t/t_trace_complex_fst.out @@ -1,5 +1,5 @@ $date - Sun Apr 19 04:15:26 2020 + Mon Nov 16 17:51:08 2020 $end $version @@ -45,193 +45,197 @@ $var logic 6 : v_enumb2_str $end $var logic 8 ; unpacked_array(-2) $end $var logic 8 < unpacked_array(-1) $end $var logic 8 = unpacked_array(0) $end +$var bit 1 > LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND $end $scope module unnamedblk1 $end -$var integer 32 > b $end +$var integer 32 ? b $end $scope module unnamedblk2 $end -$var integer 32 ? a $end +$var integer 32 @ a $end $upscope $end $upscope $end $scope module p2 $end -$var parameter 32 @ PARAM $end +$var parameter 32 A PARAM $end $upscope $end $scope module p3 $end -$var parameter 32 A PARAM $end +$var parameter 32 B PARAM $end $upscope $end $upscope $end $scope module $unit $end -$var bit 1 B global_bit $end +$var bit 1 C global_bit $end $upscope $end $upscope $end $enddefinitions $end +#0 $dumpvars -0! -b00000000000000000000000000000000 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -0) -0* -0+ -0, -0- -0. -b00 / -b00 0 -b00 1 -b00 2 -r0 3 -r0 4 -r0 5 -b0000000000000000000000000000000000000000000000000000000011111111 6 -b00000000000000000000000000000000 7 -b00000000000000000000000000000000 8 -b000 9 -b000000 : -b00000000 ; -b00000000 < -b00000000 = -b00000000000000000000000000000000 > +1C +b00000000000000000000000000000011 B +b00000000000000000000000000000010 A +b00000000000000000000000000000000 @ b00000000000000000000000000000000 ? -b00000000000000000000000000000010 @ -b00000000000000000000000000000011 A -1B +0> +b00000000 = +b00000000 < +b00000000 ; +b000000 : +b000 9 +b00000000000000000000000000000000 8 +b00000000000000000000000000000000 7 +b0000000000000000000000000000000000000000000000000000000011111111 6 +r0 5 +r0 4 +r0 3 +b00 2 +b00 1 +b00 0 +b00 / +0. +0- +0, +0+ +0* +0) +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000000 " +0! +$end #10 -b00000000000000000000000000000101 ? -b00000000000000000000000000000101 > -b111 9 -b00000000000000000000000000000010 8 -b00000000000000000000000000000001 7 -b0000000000000000000000000000000100000000000000000000000011111110 6 -r0.3 5 -r0.2 4 -r0.1 3 -b11 2 -b11 1 -b11 0 -b11 / -b1111 ( -b1111 ' -b11 & -b11 % -b1111 $ -b11 # -b00000000000000000000000000000001 " 1! +b00000000000000000000000000000001 " +b11 # +b1111 $ +b11 % +b11 & +b1111 ' +b1111 ( +b11 / +b11 0 +b11 1 +b11 2 +r0.1 3 +r0.2 4 +r0.3 5 +b0000000000000000000000000000000100000000000000000000000011111110 6 +b00000000000000000000000000000001 7 +b00000000000000000000000000000010 8 +b111 9 +b00000000000000000000000000000101 ? +b00000000000000000000000000000101 @ #15 0! #20 1! -b00000000000000000000000000000010 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -b00 / -b00 0 -b00 1 -b00 2 -r0.2 3 -r0.4 4 -r0.6 5 -b0000000000000000000000000000001000000000000000000000000011111101 6 -b00000000000000000000000000000010 7 -b00000000000000000000000000000100 8 b110 9 +b00000000000000000000000000000100 8 +b00000000000000000000000000000010 7 +b0000000000000000000000000000001000000000000000000000000011111101 6 +r0.6 5 +r0.4 4 +r0.2 3 +b00 2 +b00 1 +b00 0 +b00 / +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000010 " b111111 : #25 0! #30 1! b110110 : -b101 9 -b00000000000000000000000000000110 8 -b00000000000000000000000000000011 7 -b0000000000000000000000000000001100000000000000000000000011111100 6 -r0.8999999999999999 5 -r0.6000000000000001 4 -r0.3 3 -b11 2 -b11 1 -b11 0 -b11 / -b1111 ( -b1111 ' -b11 & -b11 % -b1111 $ -b11 # b00000000000000000000000000000011 " +b11 # +b1111 $ +b11 % +b11 & +b1111 ' +b1111 ( +b11 / +b11 0 +b11 1 +b11 2 +r0.3 3 +r0.6000000000000001 4 +r0.8999999999999999 5 +b0000000000000000000000000000001100000000000000000000000011111100 6 +b00000000000000000000000000000011 7 +b00000000000000000000000000000110 8 +b101 9 #35 0! #40 1! -b00000000000000000000000000000100 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -b00 / -b00 0 -b00 1 -b00 2 -r0.4 3 -r0.8 4 -r1.2 5 -b0000000000000000000000000000010000000000000000000000000011111011 6 -b00000000000000000000000000000100 7 -b00000000000000000000000000001000 8 b100 9 +b00000000000000000000000000001000 8 +b00000000000000000000000000000100 7 +b0000000000000000000000000000010000000000000000000000000011111011 6 +r1.2 5 +r0.8 4 +r0.4 3 +b00 2 +b00 1 +b00 0 +b00 / +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000100 " b101101 : #45 0! #50 1! b100100 : -b011 9 -b00000000000000000000000000001010 8 -b00000000000000000000000000000101 7 -b0000000000000000000000000000010100000000000000000000000011111010 6 -r1.5 5 -r1 4 -r0.5 3 -b11 2 -b11 1 -b11 0 -b11 / -b1111 ( -b1111 ' -b11 & -b11 % -b1111 $ -b11 # b00000000000000000000000000000101 " +b11 # +b1111 $ +b11 % +b11 & +b1111 ' +b1111 ( +b11 / +b11 0 +b11 1 +b11 2 +r0.5 3 +r1 4 +r1.5 5 +b0000000000000000000000000000010100000000000000000000000011111010 6 +b00000000000000000000000000000101 7 +b00000000000000000000000000001010 8 +b011 9 #55 0! #60 1! -b00000000000000000000000000000110 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -b00 / -b00 0 -b00 1 -b00 2 -r0.6 3 -r1.2 4 -r1.8 5 -b0000000000000000000000000000011000000000000000000000000011111001 6 -b00000000000000000000000000000110 7 -b00000000000000000000000000001100 8 b010 9 +b00000000000000000000000000001100 8 +b00000000000000000000000000000110 7 +b0000000000000000000000000000011000000000000000000000000011111001 6 +r1.8 5 +r1.2 4 +r0.6 3 +b00 2 +b00 1 +b00 0 +b00 / +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000110 " b011011 : diff --git a/test_regress/t/t_trace_complex_params.out b/test_regress/t/t_trace_complex_params.out index b328bd887..88690fd62 100644 --- a/test_regress/t/t_trace_complex_params.out +++ b/test_regress/t/t_trace_complex_params.out @@ -1,53 +1,54 @@ $version Generated by VerilatedVcd $end -$date Tue Jan 21 18:15:28 2020 +$date Mon Nov 16 17:51:08 2020 $end $timescale 1ps $end $scope module top $end - $var wire 1 7" clk $end + $var wire 1 = clk $end $scope module $unit $end $var wire 1 # global_bit $end $upscope $end $scope module t $end - $var wire 1 7" clk $end - $var wire 32 + cyc [31:0] $end - $var wire 8 p" unpacked_array(-1) [7:0] $end - $var wire 8 o" unpacked_array(-2) [7:0] $end - $var wire 8 q" unpacked_array(0) [7:0] $end - $var real 64 E! v_arr_real(0) $end - $var real 64 G! v_arr_real(1) $end - $var wire 2 [ v_arrp [2:1] $end - $var wire 4 c v_arrp_arrp [3:0] $end - $var wire 4 k v_arrp_strp [3:0] $end - $var wire 1 ?" v_arru(1) $end - $var wire 1 @" v_arru(2) $end - $var wire 2 s v_arru_arrp(3) [2:1] $end - $var wire 2 t v_arru_arrp(4) [2:1] $end - $var wire 1 O" v_arru_arru(3)(1) $end - $var wire 1 W" v_arru_arru(3)(2) $end - $var wire 1 _" v_arru_arru(4)(1) $end - $var wire 1 g" v_arru_arru(4)(2) $end - $var wire 2 %! v_arru_strp(3) [1:0] $end - $var wire 2 -! v_arru_strp(4) [1:0] $end - $var wire 3 u! v_enumb [2:0] $end - $var wire 6 }! v_enumb2_str [5:0] $end - $var wire 32 e! v_enumed [31:0] $end - $var wire 32 m! v_enumed2 [31:0] $end - $var real 64 5! v_real $end - $var wire 64 3 v_str32x2 [63:0] $end - $var wire 2 C v_strp [1:0] $end - $var wire 4 K v_strp_strp [3:0] $end - $var wire 2 S v_unip_strp [1:0] $end + $var wire 1 G LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND $end + $var wire 1 = clk $end + $var wire 32 $ cyc [31:0] $end + $var wire 8 E unpacked_array(-1) [7:0] $end + $var wire 8 D unpacked_array(-2) [7:0] $end + $var wire 8 F unpacked_array(0) [7:0] $end + $var real 64 1 v_arr_real(0) $end + $var real 64 3 v_arr_real(1) $end + $var wire 2 ( v_arrp [2:1] $end + $var wire 4 ) v_arrp_arrp [3:0] $end + $var wire 4 * v_arrp_strp [3:0] $end + $var wire 1 > v_arru(1) $end + $var wire 1 ? v_arru(2) $end + $var wire 2 + v_arru_arrp(3) [2:1] $end + $var wire 2 , v_arru_arrp(4) [2:1] $end + $var wire 1 @ v_arru_arru(3)(1) $end + $var wire 1 A v_arru_arru(3)(2) $end + $var wire 1 B v_arru_arru(4)(1) $end + $var wire 1 C v_arru_arru(4)(2) $end + $var wire 2 - v_arru_strp(3) [1:0] $end + $var wire 2 . v_arru_strp(4) [1:0] $end + $var wire 3 9 v_enumb [2:0] $end + $var wire 6 : v_enumb2_str [5:0] $end + $var wire 32 7 v_enumed [31:0] $end + $var wire 32 8 v_enumed2 [31:0] $end + $var real 64 / v_real $end + $var wire 64 5 v_str32x2 [63:0] $end + $var wire 2 % v_strp [1:0] $end + $var wire 4 & v_strp_strp [3:0] $end + $var wire 2 ' v_unip_strp [1:0] $end $scope module p2 $end - $var wire 32 )# PARAM [31:0] $end + $var wire 32 H PARAM [31:0] $end $upscope $end $scope module p3 $end - $var wire 32 1# PARAM [31:0] $end + $var wire 32 I PARAM [31:0] $end $upscope $end $scope module unnamedblk1 $end - $var wire 32 '" b [31:0] $end + $var wire 32 ; b [31:0] $end $scope module unnamedblk2 $end - $var wire 32 /" a [31:0] $end + $var wire 32 < a [31:0] $end $upscope $end $upscope $end $upscope $end @@ -57,173 +58,174 @@ $enddefinitions $end #0 1# -b00000000000000000000000000000000 + -b0000000000000000000000000000000000000000000000000000000011111111 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0 5! -r0 E! -r0 G! -b00000000000000000000000000000000 e! -b00000000000000000000000000000000 m! -b000 u! -b000000 }! -b00000000000000000000000000000000 '" -b00000000000000000000000000000000 /" -07" -0?" -0@" -0O" -0W" -0_" -0g" -b00000000 o" -b00000000 p" -b00000000 q" -b00000000000000000000000000000010 )# -b00000000000000000000000000000011 1# +b00000000000000000000000000000000 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0 / +r0 1 +r0 3 +b0000000000000000000000000000000000000000000000000000000011111111 5 +b00000000000000000000000000000000 7 +b00000000000000000000000000000000 8 +b000 9 +b000000 : +b00000000000000000000000000000000 ; +b00000000000000000000000000000000 < +0= +0> +0? +0@ +0A +0B +0C +b00000000 D +b00000000 E +b00000000 F +0G +b00000000000000000000000000000010 H +b00000000000000000000000000000011 I #10 -b00000000000000000000000000000001 + -b0000000000000000000000000000000100000000000000000000000011111110 3 -b11 C -b1111 K -b11 S -b11 [ -b1111 c -b1111 k -b11 s -b11 t -b11 %! -b11 -! -r0.1 5! -r0.2 E! -r0.3 G! -b00000000000000000000000000000001 e! -b00000000000000000000000000000010 m! -b111 u! -b00000000000000000000000000000101 '" -b00000000000000000000000000000101 /" -17" +b00000000000000000000000000000001 $ +b11 % +b1111 & +b11 ' +b11 ( +b1111 ) +b1111 * +b11 + +b11 , +b11 - +b11 . +r0.1 / +r0.2 1 +r0.3 3 +b0000000000000000000000000000000100000000000000000000000011111110 5 +b00000000000000000000000000000001 7 +b00000000000000000000000000000010 8 +b111 9 +b00000000000000000000000000000101 ; +b00000000000000000000000000000101 < +1= #15 -07" +0= #20 -b00000000000000000000000000000010 + -b0000000000000000000000000000001000000000000000000000000011111101 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0.2 5! -r0.4 E! -r0.6 G! -b00000000000000000000000000000010 e! -b00000000000000000000000000000100 m! -b110 u! -b111111 }! -17" +b00000000000000000000000000000010 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0.2 / +r0.4 1 +r0.6 3 +b0000000000000000000000000000001000000000000000000000000011111101 5 +b00000000000000000000000000000010 7 +b00000000000000000000000000000100 8 +b110 9 +b111111 : +1= #25 -07" +0= #30 -b00000000000000000000000000000011 + -b0000000000000000000000000000001100000000000000000000000011111100 3 -b11 C -b1111 K -b11 S -b11 [ -b1111 c -b1111 k -b11 s -b11 t -b11 %! -b11 -! -r0.3 5! -r0.6000000000000001 E! -r0.8999999999999999 G! -b00000000000000000000000000000011 e! -b00000000000000000000000000000110 m! -b101 u! -b110110 }! -17" +b00000000000000000000000000000011 $ +b11 % +b1111 & +b11 ' +b11 ( +b1111 ) +b1111 * +b11 + +b11 , +b11 - +b11 . +r0.3 / +r0.6000000000000001 1 +r0.8999999999999999 3 +b0000000000000000000000000000001100000000000000000000000011111100 5 +b00000000000000000000000000000011 7 +b00000000000000000000000000000110 8 +b101 9 +b110110 : +1= #35 -07" +0= #40 -b00000000000000000000000000000100 + -b0000000000000000000000000000010000000000000000000000000011111011 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0.4 5! -r0.8 E! -r1.2 G! -b00000000000000000000000000000100 e! -b00000000000000000000000000001000 m! -b100 u! -b101101 }! -17" +b00000000000000000000000000000100 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0.4 / +r0.8 1 +r1.2 3 +b0000000000000000000000000000010000000000000000000000000011111011 5 +b00000000000000000000000000000100 7 +b00000000000000000000000000001000 8 +b100 9 +b101101 : +1= #45 -07" +0= #50 -b00000000000000000000000000000101 + -b0000000000000000000000000000010100000000000000000000000011111010 3 -b11 C -b1111 K -b11 S -b11 [ -b1111 c -b1111 k -b11 s -b11 t -b11 %! -b11 -! -r0.5 5! -r1 E! -r1.5 G! -b00000000000000000000000000000101 e! -b00000000000000000000000000001010 m! -b011 u! -b100100 }! -17" +b00000000000000000000000000000101 $ +b11 % +b1111 & +b11 ' +b11 ( +b1111 ) +b1111 * +b11 + +b11 , +b11 - +b11 . +r0.5 / +r1 1 +r1.5 3 +b0000000000000000000000000000010100000000000000000000000011111010 5 +b00000000000000000000000000000101 7 +b00000000000000000000000000001010 8 +b011 9 +b100100 : +1= #55 -07" +0= #60 -b00000000000000000000000000000110 + -b0000000000000000000000000000011000000000000000000000000011111001 3 -b00 C -b0000 K -b00 S -b00 [ -b0000 c -b0000 k -b00 s -b00 t -b00 %! -b00 -! -r0.6 5! -r1.2 E! -r1.8 G! -b00000000000000000000000000000110 e! -b00000000000000000000000000001100 m! -b010 u! -b011011 }! -17" +b00000000000000000000000000000110 $ +b00 % +b0000 & +b00 ' +b00 ( +b0000 ) +b0000 * +b00 + +b00 , +b00 - +b00 . +r0.6 / +r1.2 1 +r1.8 3 +b0000000000000000000000000000011000000000000000000000000011111001 5 +b00000000000000000000000000000110 7 +b00000000000000000000000000001100 8 +b010 9 +b011011 : +1= diff --git a/test_regress/t/t_trace_complex_params_fst.out b/test_regress/t/t_trace_complex_params_fst.out index c94200384..e4f264a8e 100644 --- a/test_regress/t/t_trace_complex_params_fst.out +++ b/test_regress/t/t_trace_complex_params_fst.out @@ -1,5 +1,5 @@ $date - Sun Apr 19 04:15:31 2020 + Mon Nov 16 17:51:08 2020 $end $version @@ -45,193 +45,197 @@ $var logic 6 : v_enumb2_str $end $var logic 8 ; unpacked_array(-2) $end $var logic 8 < unpacked_array(-1) $end $var logic 8 = unpacked_array(0) $end +$var bit 1 > LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND $end $scope module unnamedblk1 $end -$var integer 32 > b $end +$var integer 32 ? b $end $scope module unnamedblk2 $end -$var integer 32 ? a $end +$var integer 32 @ a $end $upscope $end $upscope $end $scope module p2 $end -$var parameter 32 @ PARAM $end +$var parameter 32 A PARAM $end $upscope $end $scope module p3 $end -$var parameter 32 A PARAM $end +$var parameter 32 B PARAM $end $upscope $end $upscope $end $scope module $unit $end -$var bit 1 B global_bit $end +$var bit 1 C global_bit $end $upscope $end $upscope $end $enddefinitions $end +#0 $dumpvars -0! -b00000000000000000000000000000000 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -0) -0* -0+ -0, -0- -0. -b00 / -b00 0 -b00 1 -b00 2 -r0 3 -r0 4 -r0 5 -b0000000000000000000000000000000000000000000000000000000011111111 6 -b00000000000000000000000000000000 7 -b00000000000000000000000000000000 8 -b000 9 -b000000 : -b00000000 ; -b00000000 < -b00000000 = -b00000000000000000000000000000000 > +1C +b00000000000000000000000000000011 B +b00000000000000000000000000000010 A +b00000000000000000000000000000000 @ b00000000000000000000000000000000 ? -b00000000000000000000000000000010 @ -b00000000000000000000000000000011 A -1B +0> +b00000000 = +b00000000 < +b00000000 ; +b000000 : +b000 9 +b00000000000000000000000000000000 8 +b00000000000000000000000000000000 7 +b0000000000000000000000000000000000000000000000000000000011111111 6 +r0 5 +r0 4 +r0 3 +b00 2 +b00 1 +b00 0 +b00 / +0. +0- +0, +0+ +0* +0) +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000000 " +0! +$end #10 -b00000000000000000000000000000101 ? -b00000000000000000000000000000101 > -b111 9 -b00000000000000000000000000000010 8 -b00000000000000000000000000000001 7 -b0000000000000000000000000000000100000000000000000000000011111110 6 -r0.3 5 -r0.2 4 -r0.1 3 -b11 2 -b11 1 -b11 0 -b11 / -b1111 ( -b1111 ' -b11 & -b11 % -b1111 $ -b11 # -b00000000000000000000000000000001 " 1! +b00000000000000000000000000000001 " +b11 # +b1111 $ +b11 % +b11 & +b1111 ' +b1111 ( +b11 / +b11 0 +b11 1 +b11 2 +r0.1 3 +r0.2 4 +r0.3 5 +b0000000000000000000000000000000100000000000000000000000011111110 6 +b00000000000000000000000000000001 7 +b00000000000000000000000000000010 8 +b111 9 +b00000000000000000000000000000101 ? +b00000000000000000000000000000101 @ #15 0! #20 1! -b00000000000000000000000000000010 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -b00 / -b00 0 -b00 1 -b00 2 -r0.2 3 -r0.4 4 -r0.6 5 -b0000000000000000000000000000001000000000000000000000000011111101 6 -b00000000000000000000000000000010 7 -b00000000000000000000000000000100 8 b110 9 +b00000000000000000000000000000100 8 +b00000000000000000000000000000010 7 +b0000000000000000000000000000001000000000000000000000000011111101 6 +r0.6 5 +r0.4 4 +r0.2 3 +b00 2 +b00 1 +b00 0 +b00 / +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000010 " b111111 : #25 0! #30 1! b110110 : -b101 9 -b00000000000000000000000000000110 8 -b00000000000000000000000000000011 7 -b0000000000000000000000000000001100000000000000000000000011111100 6 -r0.8999999999999999 5 -r0.6000000000000001 4 -r0.3 3 -b11 2 -b11 1 -b11 0 -b11 / -b1111 ( -b1111 ' -b11 & -b11 % -b1111 $ -b11 # b00000000000000000000000000000011 " +b11 # +b1111 $ +b11 % +b11 & +b1111 ' +b1111 ( +b11 / +b11 0 +b11 1 +b11 2 +r0.3 3 +r0.6000000000000001 4 +r0.8999999999999999 5 +b0000000000000000000000000000001100000000000000000000000011111100 6 +b00000000000000000000000000000011 7 +b00000000000000000000000000000110 8 +b101 9 #35 0! #40 1! -b00000000000000000000000000000100 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -b00 / -b00 0 -b00 1 -b00 2 -r0.4 3 -r0.8 4 -r1.2 5 -b0000000000000000000000000000010000000000000000000000000011111011 6 -b00000000000000000000000000000100 7 -b00000000000000000000000000001000 8 b100 9 +b00000000000000000000000000001000 8 +b00000000000000000000000000000100 7 +b0000000000000000000000000000010000000000000000000000000011111011 6 +r1.2 5 +r0.8 4 +r0.4 3 +b00 2 +b00 1 +b00 0 +b00 / +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000100 " b101101 : #45 0! #50 1! b100100 : -b011 9 -b00000000000000000000000000001010 8 -b00000000000000000000000000000101 7 -b0000000000000000000000000000010100000000000000000000000011111010 6 -r1.5 5 -r1 4 -r0.5 3 -b11 2 -b11 1 -b11 0 -b11 / -b1111 ( -b1111 ' -b11 & -b11 % -b1111 $ -b11 # b00000000000000000000000000000101 " +b11 # +b1111 $ +b11 % +b11 & +b1111 ' +b1111 ( +b11 / +b11 0 +b11 1 +b11 2 +r0.5 3 +r1 4 +r1.5 5 +b0000000000000000000000000000010100000000000000000000000011111010 6 +b00000000000000000000000000000101 7 +b00000000000000000000000000001010 8 +b011 9 #55 0! #60 1! -b00000000000000000000000000000110 " -b00 # -b0000 $ -b00 % -b00 & -b0000 ' -b0000 ( -b00 / -b00 0 -b00 1 -b00 2 -r0.6 3 -r1.2 4 -r1.8 5 -b0000000000000000000000000000011000000000000000000000000011111001 6 -b00000000000000000000000000000110 7 -b00000000000000000000000000001100 8 b010 9 +b00000000000000000000000000001100 8 +b00000000000000000000000000000110 7 +b0000000000000000000000000000011000000000000000000000000011111001 6 +r1.8 5 +r1.2 4 +r0.6 3 +b00 2 +b00 1 +b00 0 +b00 / +b0000 ( +b0000 ' +b00 & +b00 % +b0000 $ +b00 # +b00000000000000000000000000000110 " b011011 : diff --git a/test_regress/t/t_trace_complex_structs.out b/test_regress/t/t_trace_complex_structs.out index f22f6d3be..dad2d3736 100644 --- a/test_regress/t/t_trace_complex_structs.out +++ b/test_regress/t/t_trace_complex_structs.out @@ -1,90 +1,91 @@ $version Generated by VerilatedVcd $end -$date Tue Jan 21 18:55:13 2020 +$date Mon Nov 16 17:51:09 2020 $end $timescale 1ps $end $scope module top $end - $var wire 1 9# clk $end + $var wire 1 I clk $end $scope module $unit $end $var wire 1 # global_bit $end $upscope $end $scope module t $end - $var wire 1 9# clk $end - $var wire 32 + cyc [31:0] $end - $var wire 8 r# unpacked_array(-1) [7:0] $end - $var wire 8 q# unpacked_array(-2) [7:0] $end - $var wire 8 s# unpacked_array(0) [7:0] $end - $var real 64 ?" v_arr_real(0) $end - $var real 64 A" v_arr_real(1) $end - $var wire 2 %! v_arrp [2:1] $end - $var wire 2 -! v_arrp_arrp(3) [2:1] $end - $var wire 2 5! v_arrp_arrp(4) [2:1] $end - $var wire 1 A# v_arru(1) $end - $var wire 1 B# v_arru(2) $end - $var wire 2 ]! v_arru_arrp(3) [2:1] $end - $var wire 2 ^! v_arru_arrp(4) [2:1] $end - $var wire 1 Q# v_arru_arru(3)(1) $end - $var wire 1 Y# v_arru_arru(3)(2) $end - $var wire 1 a# v_arru_arru(4)(1) $end - $var wire 1 i# v_arru_arru(4)(2) $end - $var wire 3 o" v_enumb [2:0] $end - $var wire 32 _" v_enumed [31:0] $end - $var wire 32 g" v_enumed2 [31:0] $end - $var real 64 /" v_real $end + $var wire 1 S LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND $end + $var wire 1 I clk $end + $var wire 32 $ cyc [31:0] $end + $var wire 8 Q unpacked_array(-1) [7:0] $end + $var wire 8 P unpacked_array(-2) [7:0] $end + $var wire 8 R unpacked_array(0) [7:0] $end + $var real 64 < v_arr_real(0) $end + $var real 64 > v_arr_real(1) $end + $var wire 2 - v_arrp [2:1] $end + $var wire 2 . v_arrp_arrp(3) [2:1] $end + $var wire 2 / v_arrp_arrp(4) [2:1] $end + $var wire 1 J v_arru(1) $end + $var wire 1 K v_arru(2) $end + $var wire 2 4 v_arru_arrp(3) [2:1] $end + $var wire 2 5 v_arru_arrp(4) [2:1] $end + $var wire 1 L v_arru_arru(3)(1) $end + $var wire 1 M v_arru_arru(3)(2) $end + $var wire 1 N v_arru_arru(4)(1) $end + $var wire 1 O v_arru_arru(4)(2) $end + $var wire 3 D v_enumb [2:0] $end + $var wire 32 B v_enumed [31:0] $end + $var wire 32 C v_enumed2 [31:0] $end + $var real 64 : v_real $end $scope module unnamedblk1 $end - $var wire 32 )# b [31:0] $end + $var wire 32 G b [31:0] $end $scope module unnamedblk2 $end - $var wire 32 1# a [31:0] $end + $var wire 32 H a [31:0] $end $upscope $end $upscope $end $scope module v_arrp_strp(3) $end - $var wire 1 E! b0 $end - $var wire 1 =! b1 $end + $var wire 1 1 b0 $end + $var wire 1 0 b1 $end $upscope $end $scope module v_arrp_strp(4) $end - $var wire 1 U! b0 $end - $var wire 1 M! b1 $end + $var wire 1 3 b0 $end + $var wire 1 2 b1 $end $upscope $end $scope module v_arru_strp(3) $end - $var wire 1 u! b0 $end - $var wire 1 m! b1 $end + $var wire 1 7 b0 $end + $var wire 1 6 b1 $end $upscope $end $scope module v_arru_strp(4) $end - $var wire 1 '" b0 $end - $var wire 1 }! b1 $end + $var wire 1 9 b0 $end + $var wire 1 8 b1 $end $upscope $end $scope module v_enumb2_str $end - $var wire 3 w" a [2:0] $end - $var wire 3 !# b [2:0] $end + $var wire 3 E a [2:0] $end + $var wire 3 F b [2:0] $end $upscope $end $scope module v_str32x2(0) $end - $var wire 32 3 data [31:0] $end + $var wire 32 @ data [31:0] $end $upscope $end $scope module v_str32x2(1) $end - $var wire 32 ; data [31:0] $end + $var wire 32 A data [31:0] $end $upscope $end $scope module v_strp $end - $var wire 1 K b0 $end - $var wire 1 C b1 $end + $var wire 1 & b0 $end + $var wire 1 % b1 $end $upscope $end $scope module v_strp_strp $end $scope module x0 $end - $var wire 1 k b0 $end - $var wire 1 c b1 $end + $var wire 1 * b0 $end + $var wire 1 ) b1 $end $upscope $end $scope module x1 $end - $var wire 1 [ b0 $end - $var wire 1 S b1 $end + $var wire 1 ( b0 $end + $var wire 1 ' b1 $end $upscope $end $upscope $end $scope module v_unip_strp $end $scope module x0 $end - $var wire 1 { b0 $end - $var wire 1 s b1 $end + $var wire 1 , b0 $end + $var wire 1 + b1 $end $upscope $end $scope module x1 $end - $var wire 1 { b0 $end - $var wire 1 s b1 $end + $var wire 1 , b0 $end + $var wire 1 + b1 $end $upscope $end $upscope $end $upscope $end @@ -94,261 +95,262 @@ $enddefinitions $end #0 1# -b00000000000000000000000000000000 + -b00000000000000000000000011111111 3 -b00000000000000000000000000000000 ; -0C +b00000000000000000000000000000000 $ +0% +0& +0' +0( +0) +0* +0+ +0, +b00 - +b00 . +b00 / +00 +01 +02 +03 +b00 4 +b00 5 +06 +07 +08 +09 +r0 : +r0 < +r0 > +b00000000000000000000000011111111 @ +b00000000000000000000000000000000 A +b00000000000000000000000000000000 B +b00000000000000000000000000000000 C +b000 D +b000 E +b000 F +b00000000000000000000000000000000 G +b00000000000000000000000000000000 H +0I +0J 0K +0L +0M +0N +0O +b00000000 P +b00000000 Q +b00000000 R 0S -0[ -0c -0k -0s -0{ -b00 %! -b00 -! -b00 5! -0=! -0E! -0M! -0U! -b00 ]! -b00 ^! -0m! -0u! -0}! -0'" -r0 /" -r0 ?" -r0 A" -b00000000000000000000000000000000 _" -b00000000000000000000000000000000 g" -b000 o" -b000 w" -b000 !# -b00000000000000000000000000000000 )# -b00000000000000000000000000000000 1# -09# -0A# -0B# -0Q# -0Y# -0a# -0i# -b00000000 q# -b00000000 r# -b00000000 s# #10 -b00000000000000000000000000000001 + -b00000000000000000000000011111110 3 -b00000000000000000000000000000001 ; -1C -1K -1S -1[ -1c -1k -1s -1{ -b11 %! -b11 -! -b11 5! -1=! -1E! -1M! -1U! -b11 ]! -b11 ^! -1m! -1u! -1}! -1'" -r0.1 /" -r0.2 ?" -r0.3 A" -b00000000000000000000000000000001 _" -b00000000000000000000000000000010 g" -b111 o" -b00000000000000000000000000000101 )# -b00000000000000000000000000000101 1# -19# +b00000000000000000000000000000001 $ +1% +1& +1' +1( +1) +1* +1+ +1, +b11 - +b11 . +b11 / +10 +11 +12 +13 +b11 4 +b11 5 +16 +17 +18 +19 +r0.1 : +r0.2 < +r0.3 > +b00000000000000000000000011111110 @ +b00000000000000000000000000000001 A +b00000000000000000000000000000001 B +b00000000000000000000000000000010 C +b111 D +b00000000000000000000000000000101 G +b00000000000000000000000000000101 H +1I #15 -09# +0I #20 -b00000000000000000000000000000010 + -b00000000000000000000000011111101 3 -b00000000000000000000000000000010 ; -0C -0K -0S -0[ -0c -0k -0s -0{ -b00 %! -b00 -! -b00 5! -0=! -0E! -0M! -0U! -b00 ]! -b00 ^! -0m! -0u! -0}! -0'" -r0.2 /" -r0.4 ?" -r0.6 A" -b00000000000000000000000000000010 _" -b00000000000000000000000000000100 g" -b110 o" -b111 w" -b111 !# -19# +b00000000000000000000000000000010 $ +0% +0& +0' +0( +0) +0* +0+ +0, +b00 - +b00 . +b00 / +00 +01 +02 +03 +b00 4 +b00 5 +06 +07 +08 +09 +r0.2 : +r0.4 < +r0.6 > +b00000000000000000000000011111101 @ +b00000000000000000000000000000010 A +b00000000000000000000000000000010 B +b00000000000000000000000000000100 C +b110 D +b111 E +b111 F +1I #25 -09# +0I #30 -b00000000000000000000000000000011 + -b00000000000000000000000011111100 3 -b00000000000000000000000000000011 ; -1C -1K -1S -1[ -1c -1k -1s -1{ -b11 %! -b11 -! -b11 5! -1=! -1E! -1M! -1U! -b11 ]! -b11 ^! -1m! -1u! -1}! -1'" -r0.3 /" -r0.6000000000000001 ?" -r0.8999999999999999 A" -b00000000000000000000000000000011 _" -b00000000000000000000000000000110 g" -b101 o" -b110 w" -b110 !# -19# +b00000000000000000000000000000011 $ +1% +1& +1' +1( +1) +1* +1+ +1, +b11 - +b11 . +b11 / +10 +11 +12 +13 +b11 4 +b11 5 +16 +17 +18 +19 +r0.3 : +r0.6000000000000001 < +r0.8999999999999999 > +b00000000000000000000000011111100 @ +b00000000000000000000000000000011 A +b00000000000000000000000000000011 B +b00000000000000000000000000000110 C +b101 D +b110 E +b110 F +1I #35 -09# +0I #40 -b00000000000000000000000000000100 + -b00000000000000000000000011111011 3 -b00000000000000000000000000000100 ; -0C -0K -0S -0[ -0c -0k -0s -0{ -b00 %! -b00 -! -b00 5! -0=! -0E! -0M! -0U! -b00 ]! -b00 ^! -0m! -0u! -0}! -0'" -r0.4 /" -r0.8 ?" -r1.2 A" -b00000000000000000000000000000100 _" -b00000000000000000000000000001000 g" -b100 o" -b101 w" -b101 !# -19# +b00000000000000000000000000000100 $ +0% +0& +0' +0( +0) +0* +0+ +0, +b00 - +b00 . +b00 / +00 +01 +02 +03 +b00 4 +b00 5 +06 +07 +08 +09 +r0.4 : +r0.8 < +r1.2 > +b00000000000000000000000011111011 @ +b00000000000000000000000000000100 A +b00000000000000000000000000000100 B +b00000000000000000000000000001000 C +b100 D +b101 E +b101 F +1I #45 -09# +0I #50 -b00000000000000000000000000000101 + -b00000000000000000000000011111010 3 -b00000000000000000000000000000101 ; -1C -1K -1S -1[ -1c -1k -1s -1{ -b11 %! -b11 -! -b11 5! -1=! -1E! -1M! -1U! -b11 ]! -b11 ^! -1m! -1u! -1}! -1'" -r0.5 /" -r1 ?" -r1.5 A" -b00000000000000000000000000000101 _" -b00000000000000000000000000001010 g" -b011 o" -b100 w" -b100 !# -19# +b00000000000000000000000000000101 $ +1% +1& +1' +1( +1) +1* +1+ +1, +b11 - +b11 . +b11 / +10 +11 +12 +13 +b11 4 +b11 5 +16 +17 +18 +19 +r0.5 : +r1 < +r1.5 > +b00000000000000000000000011111010 @ +b00000000000000000000000000000101 A +b00000000000000000000000000000101 B +b00000000000000000000000000001010 C +b011 D +b100 E +b100 F +1I #55 -09# +0I #60 -b00000000000000000000000000000110 + -b00000000000000000000000011111001 3 -b00000000000000000000000000000110 ; -0C -0K -0S -0[ -0c -0k -0s -0{ -b00 %! -b00 -! -b00 5! -0=! -0E! -0M! -0U! -b00 ]! -b00 ^! -0m! -0u! -0}! -0'" -r0.6 /" -r1.2 ?" -r1.8 A" -b00000000000000000000000000000110 _" -b00000000000000000000000000001100 g" -b010 o" -b011 w" -b011 !# -19# +b00000000000000000000000000000110 $ +0% +0& +0' +0( +0) +0* +0+ +0, +b00 - +b00 . +b00 / +00 +01 +02 +03 +b00 4 +b00 5 +06 +07 +08 +09 +r0.6 : +r1.2 < +r1.8 > +b00000000000000000000000011111001 @ +b00000000000000000000000000000110 A +b00000000000000000000000000000110 B +b00000000000000000000000000001100 C +b010 D +b011 E +b011 F +1I diff --git a/test_regress/t/t_trace_complex_structs_fst.out b/test_regress/t/t_trace_complex_structs_fst.out index 1cde8a16c..3e0bcd6f8 100644 --- a/test_regress/t/t_trace_complex_structs_fst.out +++ b/test_regress/t/t_trace_complex_structs_fst.out @@ -1,5 +1,5 @@ $date - Sun Apr 19 04:15:33 2020 + Mon Nov 16 17:51:13 2020 $end $version @@ -90,275 +90,279 @@ $upscope $end $var logic 8 H unpacked_array(-2) $end $var logic 8 I unpacked_array(-1) $end $var logic 8 J unpacked_array(0) $end +$var bit 1 K LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND $end $scope module unnamedblk1 $end -$var integer 32 K b $end +$var integer 32 L b $end $scope module unnamedblk2 $end -$var integer 32 L a $end +$var integer 32 M a $end $upscope $end $upscope $end $upscope $end $scope module $unit $end -$var bit 1 M global_bit $end +$var bit 1 N global_bit $end $upscope $end $upscope $end $enddefinitions $end +#0 $dumpvars -0! -b00000000000000000000000000000000 " -0# -0$ -0% -0& -0' -0( -0) -0* -b00 + -b00 , -b00 - -0. -0/ -00 -01 -02 -03 -04 -05 -06 -07 -b00 8 -b00 9 -0: -0; -0< -0= -r0 > -r0 ? -r0 @ -b00000000000000000000000011111111 A -b00000000000000000000000000000000 B -b00000000000000000000000000000000 C -b00000000000000000000000000000000 D -b000 E -b000 F -b000 G -b00000000 H -b00000000 I -b00000000 J -b00000000000000000000000000000000 K +1N +b00000000000000000000000000000000 M b00000000000000000000000000000000 L -1M +0K +b00000000 J +b00000000 I +b00000000 H +b000 G +b000 F +b000 E +b00000000000000000000000000000000 D +b00000000000000000000000000000000 C +b00000000000000000000000000000000 B +b00000000000000000000000011111111 A +r0 @ +r0 ? +r0 > +0= +0< +0; +0: +b00 9 +b00 8 +07 +06 +05 +04 +03 +02 +01 +00 +0/ +0. +b00 - +b00 , +b00 + +0* +0) +0( +0' +0& +0% +0$ +0# +b00000000000000000000000000000000 " +0! +$end #10 -b00000000000000000000000000000101 L -b00000000000000000000000000000101 K -b111 E -b00000000000000000000000000000010 D -b00000000000000000000000000000001 C -b00000000000000000000000000000001 B -b00000000000000000000000011111110 A -r0.3 @ -r0.2 ? -r0.1 > -1= -1< -1; -1: -b11 9 -b11 8 -11 -10 -1/ -1. -b11 - -b11 , -b11 + -1* -1) -1( -1' -1& -1% -1$ -1# -b00000000000000000000000000000001 " 1! +b00000000000000000000000000000001 " +1# +1$ +1% +1& +1' +1( +1) +1* +b11 + +b11 , +b11 - +1. +1/ +10 +11 +b11 8 +b11 9 +1: +1; +1< +1= +r0.1 > +r0.2 ? +r0.3 @ +b00000000000000000000000011111110 A +b00000000000000000000000000000001 B +b00000000000000000000000000000001 C +b00000000000000000000000000000010 D +b111 E +b00000000000000000000000000000101 L +b00000000000000000000000000000101 M #15 0! #20 1! -b00000000000000000000000000000010 " -0# -0$ -0% -0& -0' -0( -0) -0* -b00 + -b00 , -b00 - -0. -0/ -00 -01 -b00 8 -b00 9 -0: -0; -0< -0= -r0.2 > -r0.4 ? -r0.6 @ -b00000000000000000000000011111101 A -b00000000000000000000000000000010 B -b00000000000000000000000000000010 C -b00000000000000000000000000000100 D b110 E -b111 G +b00000000000000000000000000000100 D +b00000000000000000000000000000010 C +b00000000000000000000000000000010 B +b00000000000000000000000011111101 A +r0.6 @ +r0.4 ? +r0.2 > +0= +0< +0; +0: +b00 9 +b00 8 +01 +00 +0/ +0. +b00 - +b00 , +b00 + +0* +0) +0( +0' +0& +0% +0$ +0# +b00000000000000000000000000000010 " b111 F +b111 G #25 0! #30 1! -b110 F b110 G -b101 E -b00000000000000000000000000000110 D -b00000000000000000000000000000011 C -b00000000000000000000000000000011 B -b00000000000000000000000011111100 A -r0.8999999999999999 @ -r0.6000000000000001 ? -r0.3 > -1= -1< -1; -1: -b11 9 -b11 8 -11 -10 -1/ -1. -b11 - -b11 , -b11 + -1* -1) -1( -1' -1& -1% -1$ -1# +b110 F b00000000000000000000000000000011 " +1# +1$ +1% +1& +1' +1( +1) +1* +b11 + +b11 , +b11 - +1. +1/ +10 +11 +b11 8 +b11 9 +1: +1; +1< +1= +r0.3 > +r0.6000000000000001 ? +r0.8999999999999999 @ +b00000000000000000000000011111100 A +b00000000000000000000000000000011 B +b00000000000000000000000000000011 C +b00000000000000000000000000000110 D +b101 E #35 0! #40 1! -b00000000000000000000000000000100 " -0# -0$ -0% -0& -0' -0( -0) -0* -b00 + -b00 , -b00 - -0. -0/ -00 -01 -b00 8 -b00 9 -0: -0; -0< -0= -r0.4 > -r0.8 ? -r1.2 @ -b00000000000000000000000011111011 A -b00000000000000000000000000000100 B -b00000000000000000000000000000100 C -b00000000000000000000000000001000 D b100 E -b101 G +b00000000000000000000000000001000 D +b00000000000000000000000000000100 C +b00000000000000000000000000000100 B +b00000000000000000000000011111011 A +r1.2 @ +r0.8 ? +r0.4 > +0= +0< +0; +0: +b00 9 +b00 8 +01 +00 +0/ +0. +b00 - +b00 , +b00 + +0* +0) +0( +0' +0& +0% +0$ +0# +b00000000000000000000000000000100 " b101 F +b101 G #45 0! #50 1! -b100 F b100 G -b011 E -b00000000000000000000000000001010 D -b00000000000000000000000000000101 C -b00000000000000000000000000000101 B -b00000000000000000000000011111010 A -r1.5 @ -r1 ? -r0.5 > -1= -1< -1; -1: -b11 9 -b11 8 -11 -10 -1/ -1. -b11 - -b11 , -b11 + -1* -1) -1( -1' -1& -1% -1$ -1# +b100 F b00000000000000000000000000000101 " +1# +1$ +1% +1& +1' +1( +1) +1* +b11 + +b11 , +b11 - +1. +1/ +10 +11 +b11 8 +b11 9 +1: +1; +1< +1= +r0.5 > +r1 ? +r1.5 @ +b00000000000000000000000011111010 A +b00000000000000000000000000000101 B +b00000000000000000000000000000101 C +b00000000000000000000000000001010 D +b011 E #55 0! #60 1! -b00000000000000000000000000000110 " -0# -0$ -0% -0& -0' -0( -0) -0* -b00 + -b00 , -b00 - -0. -0/ -00 -01 -b00 8 -b00 9 -0: -0; -0< -0= -r0.6 > -r1.2 ? -r1.8 @ -b00000000000000000000000011111001 A -b00000000000000000000000000000110 B -b00000000000000000000000000000110 C -b00000000000000000000000000001100 D b010 E -b011 G +b00000000000000000000000000001100 D +b00000000000000000000000000000110 C +b00000000000000000000000000000110 B +b00000000000000000000000011111001 A +r1.8 @ +r1.2 ? +r0.6 > +0= +0< +0; +0: +b00 9 +b00 8 +01 +00 +0/ +0. +b00 - +b00 , +b00 + +0* +0) +0( +0' +0& +0% +0$ +0# +b00000000000000000000000000000110 " b011 F +b011 G From 1b0a48ea02123a8f49c505ec2089fa2951e660e9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 16 Nov 2020 19:56:16 -0500 Subject: [PATCH 11/91] Internals: Use C++11 = default where obvious. No functional change intended. --- .clang-tidy | 2 +- Makefile.in | 5 +++-- include/verilated.cpp | 5 ----- include/verilated.h | 18 +++++++++--------- include/verilated_cov.cpp | 6 +++--- include/verilated_heavy.h | 32 +++++++++++++++++++++----------- include/verilated_imp.h | 16 ++++++++++------ include/verilated_save.h | 4 ++-- include/verilated_sym_props.h | 10 +++++----- include/verilated_syms.h | 12 ++++++------ include/verilated_threads.h | 4 ++-- include/verilated_vcd_c.h | 4 ++-- include/verilated_vpi.cpp | 28 ++++++++++++++-------------- src/V3Active.cpp | 8 ++++---- src/V3ActiveTop.cpp | 2 +- src/V3AssertPre.cpp | 2 +- src/V3Ast.h | 12 ++++++------ src/V3AstNodes.h | 2 +- src/V3Begin.cpp | 8 ++++---- src/V3Branch.cpp | 2 +- src/V3Broken.cpp | 8 ++++---- src/V3CCtors.cpp | 2 +- src/V3CUse.cpp | 6 +++--- src/V3Case.cpp | 2 +- src/V3Cast.cpp | 2 +- src/V3Cdc.cpp | 10 +++++----- src/V3Changed.cpp | 8 ++++---- src/V3Clean.cpp | 2 +- src/V3Clock.cpp | 2 +- src/V3Combine.cpp | 8 ++++---- src/V3Config.cpp | 14 +++++++------- src/V3Const.cpp | 6 +++--- src/V3Coverage.cpp | 6 +++--- src/V3Dead.cpp | 4 ++-- src/V3Depth.cpp | 2 +- src/V3DepthBlock.cpp | 2 +- src/V3Descope.cpp | 2 +- src/V3EmitC.cpp | 10 +++++----- src/V3EmitCBase.h | 6 +++--- src/V3EmitCMake.cpp | 2 +- src/V3EmitCSyms.cpp | 2 +- src/V3EmitMk.cpp | 2 +- src/V3EmitV.cpp | 8 ++++---- src/V3EmitXml.cpp | 6 +++--- src/V3Expand.cpp | 2 +- src/V3File.cpp | 4 ++-- src/V3File.h | 12 ++++++------ src/V3FileLine.h | 8 ++++---- src/V3Gate.cpp | 26 +++++++++++++------------- src/V3GenClk.cpp | 4 ++-- src/V3Graph.h | 4 ++-- src/V3GraphAcyc.cpp | 4 ++-- src/V3GraphAlg.cpp | 12 ++++++------ src/V3GraphAlg.h | 2 +- src/V3GraphDfa.cpp | 6 +++--- src/V3GraphDfa.h | 8 ++++---- src/V3GraphPathChecker.cpp | 2 +- src/V3GraphStream.h | 2 +- src/V3GraphTest.cpp | 10 +++++----- src/V3Hashed.cpp | 2 +- src/V3Hashed.h | 10 +++++----- src/V3HierBlock.cpp | 2 -- src/V3HierBlock.h | 2 +- src/V3Inline.cpp | 6 +++--- src/V3Inst.cpp | 10 +++++----- src/V3InstrCount.cpp | 4 ++-- src/V3Life.cpp | 8 ++++---- src/V3LifePost.cpp | 6 +++--- src/V3LinkCells.cpp | 10 +++++----- src/V3LinkDot.cpp | 12 ++++++------ src/V3LinkInc.cpp | 2 +- src/V3LinkJump.cpp | 2 +- src/V3LinkLValue.cpp | 2 +- src/V3LinkParse.cpp | 2 +- src/V3LinkResolve.cpp | 4 ++-- src/V3List.h | 6 +++--- src/V3Localize.cpp | 2 +- src/V3MergeCond.cpp | 2 +- src/V3Name.cpp | 2 +- src/V3Options.cpp | 4 ++-- src/V3Order.cpp | 14 +++++++------- src/V3OrderGraph.h | 34 +++++++++++++++++----------------- src/V3Param.cpp | 2 +- src/V3ParseLex.cpp | 2 +- src/V3ParseSym.h | 2 +- src/V3Partition.cpp | 18 +++++++++--------- src/V3Partition.h | 4 ++-- src/V3PartitionGraph.h | 4 ++-- src/V3PreProc.cpp | 4 ++-- src/V3PreProc.h | 2 +- src/V3PreShell.cpp | 4 ++-- src/V3Premit.cpp | 4 ++-- src/V3Scope.cpp | 4 ++-- src/V3Scoreboard.cpp | 2 +- src/V3Scoreboard.h | 4 ++-- src/V3SenTree.h | 4 ++-- src/V3Simulate.h | 2 +- src/V3Slice.cpp | 2 +- src/V3Split.cpp | 32 ++++++++++++++++---------------- src/V3SplitAs.cpp | 4 ++-- src/V3Stats.h | 2 +- src/V3StatsReport.cpp | 2 +- src/V3String.h | 8 ++++---- src/V3Subst.cpp | 4 ++-- src/V3TSP.cpp | 8 ++++---- src/V3Table.cpp | 2 +- src/V3Task.cpp | 14 +++++++------- src/V3Trace.cpp | 8 ++++---- src/V3Tristate.cpp | 4 ++-- src/V3Undriven.cpp | 2 +- src/V3Width.cpp | 4 ++-- src/V3WidthCommit.h | 6 +++--- src/V3WidthSel.cpp | 6 +++--- src/VlcOptions.h | 4 ++-- src/VlcPoint.h | 6 +++--- src/VlcSource.h | 8 ++++---- src/VlcTest.h | 4 ++-- src/VlcTop.h | 4 ++-- 118 files changed, 381 insertions(+), 373 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index f5079ed0e..f043d8cda 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,4 +1,4 @@ -Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-modernize*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-default-arguments,-fuchsia-overloaded-operator,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance' +Checks: '*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-*,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-modernize-use-auto,-modernize-use-trailing-return-type,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance' WarningsAsErrors: '' HeaderFilterRegex: '' FormatStyle: none diff --git a/Makefile.in b/Makefile.in index 6e2dc2ec7..7d2a929e2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -445,12 +445,13 @@ CLANGTIDY = clang-tidy CLANGTIDY_FLAGS = -config='' -checks='-fuchsia-*,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-init-variables' CLANGTIDY_DEP = $(subst .h,.h.tidy,$(CPPCHECK_H)) \ $(subst .cpp,.cpp.tidy,$(CPPCHECK_CPP)) +CLANGTIDY_DEFS = -DVL_DEBUG=1 -DVL_THREADED=1 -DVL_CPPCHECK=1 clang-tidy: $(CLANGTIDY_DEP) %.cpp.tidy: %.cpp - $(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@ + $(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@ %.h.tidy: %.h - $(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@ + $(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@ analyzer-src: -rm -rf src/obj_dbg diff --git a/include/verilated.cpp b/include/verilated.cpp index d976d45a5..396b0cd5b 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -2202,9 +2202,6 @@ void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix, //=========================================================================== // Verilated:: Methods -Verilated::ThreadLocal::ThreadLocal() {} -Verilated::ThreadLocal::~ThreadLocal() {} - void Verilated::debug(int level) VL_MT_SAFE { const VerilatedLockGuard lock(m_mutex); s_s.s_debug = level; @@ -2648,8 +2645,6 @@ void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const //====================================================================== // VerilatedScope:: Methods -VerilatedScope::VerilatedScope() {} - VerilatedScope::~VerilatedScope() { // Memory cleanup - not called during normal operation VerilatedImp::scopeErase(this); diff --git a/include/verilated.h b/include/verilated.h index 9d339d8db..c9a198e19 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -133,8 +133,8 @@ class VL_CAPABILITY("mutex") VerilatedMutex { private: std::mutex m_mutex; // Mutex public: - VerilatedMutex() {} - ~VerilatedMutex() {} + VerilatedMutex() = default; + ~VerilatedMutex() = default; const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety /// Acquire/lock mutex void lock() VL_ACQUIRE() { @@ -186,7 +186,7 @@ class VerilatedLockGuard { public: explicit VerilatedLockGuard(VerilatedMutex&) {} - ~VerilatedLockGuard() {} + ~VerilatedLockGuard() = default; void lock() {} void unlock() {} }; @@ -330,7 +330,7 @@ private: Type m_type = SCOPE_OTHER; ///< Type of the scope public: // But internals only - called from VerilatedModule's - VerilatedScope(); + VerilatedScope() = default; ~VerilatedScope(); void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp, const char* identifier, vlsint8_t timeunit, const Type& type) VL_MT_UNSAFE; @@ -387,7 +387,7 @@ class Verilated { int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random int s_randSeed; ///< Random seed: 0=random Serialized(); - ~Serialized() {} + ~Serialized() = default; } s_s; static struct NonSerialized { // Non-serialized information @@ -407,8 +407,8 @@ class Verilated { VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED int argc = 0; const char** argv = nullptr; - CommandArgValues() {} - ~CommandArgValues() {} + CommandArgValues() = default; + ~CommandArgValues() = default; } s_args; // Not covered by mutex, as per-thread @@ -422,8 +422,8 @@ class Verilated { const char* t_dpiFilename = nullptr; ///< DPI context filename int t_dpiLineno = 0; ///< DPI context line number - ThreadLocal(); - ~ThreadLocal(); + ThreadLocal() = default; + ~ThreadLocal() = default; } t_s; private: diff --git a/include/verilated_cov.cpp b/include/verilated_cov.cpp index 753e550cb..5eee2997a 100644 --- a/include/verilated_cov.cpp +++ b/include/verilated_cov.cpp @@ -52,7 +52,7 @@ public: // But only local to this file m_vals[i] = 0; } } - virtual ~VerilatedCovImpItem() {} + virtual ~VerilatedCovImpItem() = default; virtual vluint64_t count() const = 0; virtual void zero() const = 0; }; @@ -78,7 +78,7 @@ public: : m_countp{countp} { *m_countp = 0; } - virtual ~VerilatedCoverItemSpec() override {} + virtual ~VerilatedCoverItemSpec() override = default; }; //============================================================================= @@ -105,7 +105,7 @@ private: int m_insertLineno VL_GUARDED_BY(m_mutex) = 0; ///< Line number about to insert // CONSTRUCTORS - VerilatedCovImp() {} + VerilatedCovImp() = default; VL_UNCOPYABLE(VerilatedCovImp); public: diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 0c4d2eb83..5cf4530b0 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -108,10 +108,13 @@ private: public: // CONSTRUCTORS - VlQueue() { - // m_defaultValue isn't defaulted. Caller's constructor must do it. - } - ~VlQueue() {} + // m_defaultValue isn't defaulted. Caller's constructor must do it. + VlQueue() = default; + ~VlQueue() = default; + VlQueue(const VlQueue&) = default; + VlQueue(VlQueue&&) = default; + VlQueue& operator=(const VlQueue&) = default; + VlQueue& operator=(VlQueue&&) = default; // Standard copy constructor works. Verilog: assoca = assocb // Also must allow conversion from a different T_MaxSize queue @@ -426,8 +429,13 @@ template class VlWide { public: // cppcheck-suppress uninitVar - VlWide() {} - ~VlWide() {} + VlWide() = default; + ~VlWide() = default; + VlWide(const VlWide&) = default; + VlWide(VlWide&&) = default; + VlWide& operator=(const VlWide&) = default; + VlWide& operator=(VlWide&&) = default; + // METHODS const WData& at(size_t index) const { return m_storage[index]; } WData& at(size_t index) { return m_storage[index]; } WData* data() { return &m_storage[0]; } @@ -467,11 +475,13 @@ private: public: // CONSTRUCTORS - VlAssocArray() { - // m_defaultValue isn't defaulted. Caller's constructor must do it. - } - ~VlAssocArray() {} - // Standard copy constructor works. Verilog: assoca = assocb + // m_defaultValue isn't defaulted. Caller's constructor must do it. + VlAssocArray() = default; + ~VlAssocArray() = default; + VlAssocArray(const VlAssocArray&) = default; + VlAssocArray(VlAssocArray&&) = default; + VlAssocArray& operator=(const VlAssocArray&) = default; + VlAssocArray& operator=(VlAssocArray&&) = default; // METHODS T_Value& atDefault() { return m_defaultValue; } diff --git a/include/verilated_imp.h b/include/verilated_imp.h index afbcc76b0..1b92f4798 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -64,7 +64,11 @@ public: VerilatedMsg(const std::function& cb) : m_mtaskId{Verilated::mtaskId()} , m_cb{cb} {} - ~VerilatedMsg() {} + ~VerilatedMsg() = default; + VerilatedMsg(const VerilatedMsg&) = default; + VerilatedMsg(VerilatedMsg&&) = default; + VerilatedMsg& operator=(const VerilatedMsg&) = default; + VerilatedMsg& operator=(VerilatedMsg&&) = default; // METHODS vluint32_t mtaskId() const { return m_mtaskId; } /// Execute the lambda function @@ -87,7 +91,7 @@ public: : m_depth{0} { assert(atomic_is_lock_free(&m_depth)); } - ~VerilatedEvalMsgQueue() {} + ~VerilatedEvalMsgQueue() = default; private: VL_UNCOPYABLE(VerilatedEvalMsgQueue); @@ -207,8 +211,8 @@ protected: int m_timeFormatPrecision = 0; // $timeformat number of decimal places int m_timeFormatWidth = 20; // $timeformat character width enum { UNITS_NONE = 99 }; // Default based on precision - Serialized() {} - ~Serialized() {} + Serialized() = default; + ~Serialized() = default; } m_ser; VerilatedMutex m_sergMutex; ///< Protect m_ser @@ -275,8 +279,8 @@ protected: public: // But only for verilated*.cpp // CONSTRUCTORS - VerilatedImp() {} - ~VerilatedImp() {} + VerilatedImp() = default; + ~VerilatedImp() = default; static void setup(); static void teardown(); diff --git a/include/verilated_save.h b/include/verilated_save.h index adc65fa8d..5729591d9 100644 --- a/include/verilated_save.h +++ b/include/verilated_save.h @@ -160,7 +160,7 @@ private: public: // CONSTRUCTORS - VerilatedSave() {} + VerilatedSave() = default; virtual ~VerilatedSave() override { close(); } // METHODS /// Open the file; call isOpen() to see if errors @@ -180,7 +180,7 @@ private: public: // CONSTRUCTORS - VerilatedRestore() {} + VerilatedRestore() = default; virtual ~VerilatedRestore() override { close(); } // METHODS diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h index 9d3b13732..9419e3309 100644 --- a/include/verilated_sym_props.h +++ b/include/verilated_sym_props.h @@ -43,7 +43,7 @@ class VerilatedRange { protected: friend class VerilatedVarProps; friend class VerilatedScope; - VerilatedRange() {} + VerilatedRange() = default; VerilatedRange(int left, int right) : m_left{left} , m_right{right} {} @@ -53,7 +53,7 @@ protected: } public: - ~VerilatedRange() {} + ~VerilatedRange() = default; int left() const { return m_left; } int right() const { return m_right; } int low() const { return (m_left < m_right) ? m_left : m_right; } @@ -136,7 +136,7 @@ public: } public: - ~VerilatedVarProps() {} + ~VerilatedVarProps() = default; // METHODS bool magicOk() const { return m_magic == MAGIC; } VerilatedVarType vltype() const { return m_vltype; } @@ -199,7 +199,7 @@ public: VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap) : m_propsp{propsp} , m_datap{const_cast(datap)} {} - ~VerilatedDpiOpenVar() {} + ~VerilatedDpiOpenVar() = default; // METHODS void* datap() const { return m_datap; } // METHODS - from VerilatedVarProps @@ -241,7 +241,7 @@ protected: , m_isParam{isParam} {} public: - ~VerilatedVar() {} + ~VerilatedVar() = default; // ACCESSORS void* datap() const { return m_datap; } const VerilatedRange& range() const { return packed(); } // Deprecated diff --git a/include/verilated_syms.h b/include/verilated_syms.h index e364a18cf..2a643b341 100644 --- a/include/verilated_syms.h +++ b/include/verilated_syms.h @@ -45,23 +45,23 @@ struct VerilatedCStrCmp { class VerilatedScopeNameMap : public std::map { public: - VerilatedScopeNameMap() {} - ~VerilatedScopeNameMap() {} + VerilatedScopeNameMap() = default; + ~VerilatedScopeNameMap() = default; }; /// Map of sorted variable names to find associated variable class class VerilatedVarNameMap : public std::map { public: - VerilatedVarNameMap() {} - ~VerilatedVarNameMap() {} + VerilatedVarNameMap() = default; + ~VerilatedVarNameMap() = default; }; typedef std::vector VerilatedScopeVector; class VerilatedHierarchyMap : public std::map { public: - VerilatedHierarchyMap() {} - ~VerilatedHierarchyMap() {} + VerilatedHierarchyMap() = default; + ~VerilatedHierarchyMap() = default; }; #endif // Guard diff --git a/include/verilated_threads.h b/include/verilated_threads.h index 1ff8de64e..1592b2eaf 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -82,7 +82,7 @@ public: // that must notify this MTaskVertex before it will become ready // to run. explicit VlMTaskVertex(vluint32_t upstreamDepCount); - ~VlMTaskVertex() {} + ~VlMTaskVertex() = default; static vluint64_t yields() { return s_yields; } static void yieldThread() { @@ -136,7 +136,7 @@ protected: unsigned m_cpu; // Execution CPU number (at start anyways) public: class Barrier {}; - VlProfileRec() {} + VlProfileRec() = default; explicit VlProfileRec(Barrier) { m_cpu = getcpu(); } void startRecord(vluint64_t time, uint32_t mtask, uint32_t predict) { m_type = VlProfileRec::TYPE_MTASK_RUN; diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index e5e1b334a..1bc9080a3 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -39,8 +39,8 @@ private: int m_fd = 0; ///< File descriptor we're writing to public: // METHODS - VerilatedVcdFile() {} - virtual ~VerilatedVcdFile() {} + VerilatedVcdFile() = default; + virtual ~VerilatedVcdFile() = default; virtual bool open(const std::string& name) VL_MT_UNSAFE; virtual void close() VL_MT_UNSAFE; virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE; diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 58e17aa87..43e6feecd 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -61,8 +61,8 @@ class VerilatedVpio { public: // CONSTRUCTORS - VerilatedVpio() {} - virtual ~VerilatedVpio() {} + VerilatedVpio() = default; + virtual ~VerilatedVpio() = default; inline static void* operator new(size_t size) VL_MT_SAFE { // We new and delete tons of vpi structures, so keep them around // To simplify our free list, we use a size large enough for all derived types @@ -114,7 +114,7 @@ public: m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal; m_cbData.value = &m_value; } - virtual ~VerilatedVpioCb() override {} + virtual ~VerilatedVpioCb() override = default; static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -131,7 +131,7 @@ class VerilatedVpioConst : public VerilatedVpio { public: explicit VerilatedVpioConst(vlsint32_t num) : m_num{num} {} - virtual ~VerilatedVpioConst() override {} + virtual ~VerilatedVpioConst() override = default; static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -148,7 +148,7 @@ public: : m_varp{varp} , m_scopep{scopep} {} - virtual ~VerilatedVpioParam() override {} + virtual ~VerilatedVpioParam() override = default; static inline VerilatedVpioParam* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); @@ -172,7 +172,7 @@ class VerilatedVpioRange : public VerilatedVpio { public: explicit VerilatedVpioRange(const VerilatedRange* range) : m_range{range} {} - virtual ~VerilatedVpioRange() override {} + virtual ~VerilatedVpioRange() override = default; static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -198,7 +198,7 @@ protected: public: explicit VerilatedVpioScope(const VerilatedScope* scopep) : m_scopep{scopep} {} - virtual ~VerilatedVpioScope() override {} + virtual ~VerilatedVpioScope() override = default; static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -274,7 +274,7 @@ public: m_index = index; m_varDatap = (static_cast(varp->datap())) + entSize() * offset; } - virtual ~VerilatedVpioMemoryWord() override {} + virtual ~VerilatedVpioMemoryWord() override = default; static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -298,7 +298,7 @@ class VerilatedVpioVarIter : public VerilatedVpio { public: explicit VerilatedVpioVarIter(const VerilatedScope* scopep) : m_scopep{scopep} {} - virtual ~VerilatedVpioVarIter() override {} + virtual ~VerilatedVpioVarIter() override = default; static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -334,7 +334,7 @@ public: , m_varp{varp} , m_iteration{varp->unpacked().right()} , m_direction{VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) ? 1 : -1} {} - virtual ~VerilatedVpioMemoryWordIter() override {} + virtual ~VerilatedVpioMemoryWordIter() override = default; static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -379,7 +379,7 @@ public: : m_vec{&vec} { m_it = m_vec->begin(); } - virtual ~VerilatedVpioModuleIter() override {} + virtual ~VerilatedVpioModuleIter() override = default; static inline VerilatedVpioModuleIter* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } @@ -422,8 +422,8 @@ class VerilatedVpiImp { static VerilatedVpiImp s_s; // Singleton public: - VerilatedVpiImp() {} - ~VerilatedVpiImp() {} + VerilatedVpiImp() = default; + ~VerilatedVpiImp() = default; static void assertOneCheck() { s_s.m_assertOne.check(); } static void cbReasonAdd(VerilatedVpioCb* vop) { if (vop->reason() == cbValueChange) { @@ -553,7 +553,7 @@ public: m_buff[0] = '\0'; m_errorInfo.product = const_cast(Verilated::productName()); } - ~VerilatedVpiError() {} + ~VerilatedVpiError() = default; static void selfTest() VL_MT_UNSAFE_ONE; VerilatedVpiError* setMessage(PLI_INT32 level) { m_flag = true; diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 7b0124922..dae137c95 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -130,8 +130,8 @@ public: } // CONSTRUCTORS - ActiveNamer() {} - virtual ~ActiveNamer() override {} + ActiveNamer() = default; + virtual ~ActiveNamer() override = default; void main(AstScope* nodep) { iterate(nodep); } }; @@ -205,7 +205,7 @@ public: , m_alwaysp{nodep} { iterate(nodep); } - virtual ~ActiveDlyVisitor() override {} + virtual ~ActiveDlyVisitor() override = default; }; //###################################################################### @@ -406,7 +406,7 @@ private: public: // CONSTRUCTORS explicit ActiveVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ActiveVisitor() override {} + virtual ~ActiveVisitor() override = default; }; //###################################################################### diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index b944618cf..72d2f0580 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -128,7 +128,7 @@ private: public: // CONSTRUCTORS explicit ActiveTopVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ActiveTopVisitor() override {} + virtual ~ActiveTopVisitor() override = default; }; //###################################################################### diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 50a405b13..0c288ea8f 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -197,7 +197,7 @@ public: // Process iterate(nodep); } - virtual ~AssertPreVisitor() override {} + virtual ~AssertPreVisitor() override = default; }; //###################################################################### diff --git a/src/V3Ast.h b/src/V3Ast.h index b32e504f7..d086a4def 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1010,7 +1010,7 @@ public: : mu_flags{0} { init((right > left) ? right : left, (right > left) ? left : right, (right > left)); } - ~VNumRange() {} + ~VNumRange() = default; // MEMBERS void init(int hi, int lo, bool littleEndian) { m_hi = hi; @@ -1112,7 +1112,7 @@ public: , m_numeric{numeric} , m_keyword{kwd} , m_nrange{nrange} {} - ~VBasicTypeKey() {} + ~VBasicTypeKey() = default; }; //###################################################################### @@ -1138,7 +1138,7 @@ public: m_u.ui = i; } explicit VNUser(void* p) { m_u.up = p; } - ~VNUser() {} + ~VNUser() = default; // Casters WidthVP* c() const { return reinterpret_cast(m_u.up); } VSymEnt* toSymEnt() const { return reinterpret_cast(m_u.up); } @@ -1315,7 +1315,7 @@ protected: AstNode** m_iterpp = nullptr; public: - AstNRelinker() {} + AstNRelinker() = default; void relink(AstNode* newp); AstNode* oldp() const { return m_oldp; } void dump(std::ostream& str = std::cout) const; @@ -1538,7 +1538,7 @@ public: bool brokeExistsBelow() const; // CONSTRUCTORS - virtual ~AstNode() {} + virtual ~AstNode() = default; #ifdef VL_LEAK_CHECKS static void* operator new(size_t size); static void operator delete(void* obj, size_t size); @@ -1905,7 +1905,7 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); } //=== AstNode* : Derived generic node types #define ASTNODE_BASE_FUNCS(name) \ - virtual ~Ast##name() {} \ + virtual ~Ast##name() override = default; \ static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ } \ diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 165f60dec..f68c68120 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -36,7 +36,7 @@ Ast##name* clonep() const { return static_cast(AstNode::clonep()); } #define ASTNODE_NODE_FUNCS(name) \ - virtual ~Ast##name() override {} \ + virtual ~Ast##name() override = default; \ ASTNODE_NODE_FUNCS_NO_DTOR(name) //###################################################################### diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index cbe3871eb..31190eca8 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -45,8 +45,8 @@ private: bool m_anyFuncInBegin = false; public: - BeginState() {} - ~BeginState() {} + BeginState() = default; + ~BeginState() = default; void userMarkChanged(AstNode* nodep) { nodep->user1(true); m_anyFuncInBegin = true; @@ -242,7 +242,7 @@ public: : m_statep{statep} { iterate(nodep); } - virtual ~BeginVisitor() override {} + virtual ~BeginVisitor() override = default; }; //###################################################################### @@ -283,7 +283,7 @@ private: public: // CONSTRUCTORS BeginRelinkVisitor(AstNetlist* nodep, BeginState*) { iterate(nodep); } - virtual ~BeginRelinkVisitor() override {} + virtual ~BeginRelinkVisitor() override = default; }; //###################################################################### diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp index 2aa42a9b3..325ba2900 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -118,7 +118,7 @@ public: iterateChildren(nodep); calc_tasks(); } - virtual ~BranchVisitor() override {} + virtual ~BranchVisitor() override = default; }; //###################################################################### diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index de3a674b8..d76a9241c 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -190,8 +190,8 @@ public: } // CONSTRUCTORS - BrokenTable() {} - virtual ~BrokenTable() override {} + BrokenTable() = default; + virtual ~BrokenTable() override = default; }; BrokenTable::NodeMap BrokenTable::s_nodes; @@ -231,7 +231,7 @@ private: public: // CONSTRUCTORS explicit BrokenMarkVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~BrokenMarkVisitor() override {} + virtual ~BrokenMarkVisitor() override = default; }; //###################################################################### @@ -304,7 +304,7 @@ private: public: // CONSTRUCTORS explicit BrokenCheckVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~BrokenCheckVisitor() override {} + virtual ~BrokenCheckVisitor() override = default; }; //###################################################################### diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index 94a0b1306..eb3a88d5d 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -87,7 +87,7 @@ public: m_funcp = m_tlFuncp; m_modp->addStmtp(m_tlFuncp); } - ~V3CCtorsVisitor() {} + ~V3CCtorsVisitor() = default; private: VL_UNCOPYABLE(V3CCtorsVisitor); diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index 698378314..86f97dd74 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -68,7 +68,7 @@ public: // CONSTRUCTORS explicit CUseState(AstNodeModule* nodep) : m_modInsertp{nodep} {} - virtual ~CUseState() {} + virtual ~CUseState() = default; VL_UNCOPYABLE(CUseState); }; @@ -109,7 +109,7 @@ public: : m_stater(stater) { // Need () or GCC 4.8 false warning iterate(nodep); } - virtual ~CUseDTypeVisitor() override {} + virtual ~CUseDTypeVisitor() override = default; VL_UNCOPYABLE(CUseDTypeVisitor); }; @@ -219,7 +219,7 @@ public: : m_state{nodep} { iterate(nodep); } - virtual ~CUseVisitor() override {} + virtual ~CUseVisitor() override = default; VL_UNCOPYABLE(CUseVisitor); }; diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 99f9ba8c6..31c0bfeec 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -111,7 +111,7 @@ private: public: // CONSTRUCTORS explicit CaseLintVisitor(AstNodeCase* nodep) { iterate(nodep); } - virtual ~CaseLintVisitor() override {} + virtual ~CaseLintVisitor() override = default; }; //###################################################################### diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index faa0eedad..e2fe21ccb 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -193,7 +193,7 @@ private: public: // CONSTRUCTORS explicit CastVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~CastVisitor() override {} + virtual ~CastVisitor() override = default; }; //###################################################################### diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 60e85be33..891420e47 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -66,7 +66,7 @@ public: , m_srcDomainSet{false} , m_dstDomainSet{false} , m_asyncPath{false} {} - virtual ~CdcEitherVertex() override {} + virtual ~CdcEitherVertex() override = default; // ACCESSORS virtual FileLine* fileline() const override { return nodep()->fileline(); } AstScope* scopep() const { return m_scopep; } @@ -92,7 +92,7 @@ public: CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : CdcEitherVertex{graphp, scopep, varScp} , m_varScp{varScp} {} - virtual ~CdcVarVertex() override {} + virtual ~CdcVarVertex() override = default; // ACCESSORS AstVarScope* varScp() const { return m_varScp; } virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); } @@ -117,7 +117,7 @@ public: srcDomainp(sensenodep); dstDomainp(sensenodep); } - virtual ~CdcLogicVertex() override {} + virtual ~CdcLogicVertex() override = default; // ACCESSORS virtual string name() const override { return (cvtToHex(nodep()) + "@" + scopep()->prettyName()); @@ -170,7 +170,7 @@ public: , m_prefix{prefix} { iterate(nodep); } - virtual ~CdcDumpVisitor() override {} + virtual ~CdcDumpVisitor() override = default; }; //###################################################################### @@ -194,7 +194,7 @@ private: public: // CONSTRUCTORS explicit CdcWidthVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~CdcWidthVisitor() override {} + virtual ~CdcWidthVisitor() override = default; // ACCESSORS int maxWidth() const { size_t width = 1; diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 922d0686c..6d80a0a7b 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -48,8 +48,8 @@ public: int m_numStmts = 0; // Number of statements added to m_chgFuncp int m_funcNum = 0; // Number of change functions emitted - ChangedState() {} - ~ChangedState() {} + ChangedState() = default; + ~ChangedState() = default; void maybeCreateChgFuncp() { // Don't create an extra function call if splitting is disabled @@ -208,7 +208,7 @@ public: m_newLvEqnp->deleteTree(); m_newRvEqnp->deleteTree(); } - virtual ~ChangedInsertVisitor() override {} + virtual ~ChangedInsertVisitor() override = default; VL_UNCOPYABLE(ChangedInsertVisitor); }; @@ -280,7 +280,7 @@ public: : m_statep{statep} { iterate(nodep); } - virtual ~ChangedVisitor() override {} + virtual ~ChangedVisitor() override = default; }; //###################################################################### diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 3dcd7fc1e..e1ebe1fa0 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -305,7 +305,7 @@ private: public: // CONSTRUCTORS explicit CleanVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~CleanVisitor() override {} + virtual ~CleanVisitor() override = default; }; //###################################################################### diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 1c39a0c9b..77a7d6ff7 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -454,7 +454,7 @@ public: // easily without iterating through the tree. nodep->evalp(m_evalFuncp); } - virtual ~ClockVisitor() override {} + virtual ~ClockVisitor() override = default; }; //###################################################################### diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index ad2bcc690..70fcd589d 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -56,7 +56,7 @@ protected: // STATE // METHODS - virtual ~CombBaseVisitor() override {} + virtual ~CombBaseVisitor() override = default; VL_DEBUG_FUNC; // Declare debug() }; @@ -131,8 +131,8 @@ private: public: // CONSTRUCTORS - CombCallVisitor() {} - virtual ~CombCallVisitor() override {} + CombCallVisitor() = default; + virtual ~CombCallVisitor() override = default; void main(AstNetlist* nodep) { iterate(nodep); } }; @@ -153,7 +153,7 @@ private: public: // CONSTRUCTORS explicit CombMarkVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~CombMarkVisitor() override {} + virtual ~CombMarkVisitor() override = default; }; //###################################################################### diff --git a/src/V3Config.cpp b/src/V3Config.cpp index 7a29b21fd..d58608116 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -38,8 +38,8 @@ template class V3ConfigWildcardResolver { Map m_mapWildcard; // Wildcard strings to entities Map m_mapResolved; // Resolved strings to converged entities public: - V3ConfigWildcardResolver() {} - ~V3ConfigWildcardResolver() {} + V3ConfigWildcardResolver() = default; + ~V3ConfigWildcardResolver() = default; /// Update into maps from other void update(const V3ConfigWildcardResolver& other) { @@ -123,7 +123,7 @@ class V3ConfigFTask { bool m_public = false; // Public function/task public: - V3ConfigFTask() {} + V3ConfigFTask() = default; void update(const V3ConfigFTask& f) { // Don't overwrite true with false if (f.m_isolate) m_isolate = true; @@ -165,7 +165,7 @@ class V3ConfigModule { bool m_inlineValue = false; // The inline value (on/off) public: - V3ConfigModule() {} + V3ConfigModule() = default; void update(const V3ConfigModule& m) { m_tasks.update(m.m_tasks); @@ -233,7 +233,7 @@ public: : m_lineno{lineno} , m_code{code} , m_on{on} {} - ~V3ConfigIgnoresLine() {} + ~V3ConfigIgnoresLine() = default; inline bool operator<(const V3ConfigIgnoresLine& rh) const { if (m_lineno < rh.m_lineno) return true; if (m_lineno > rh.m_lineno) return false; @@ -352,8 +352,8 @@ class V3ConfigResolver { V3ConfigFileResolver m_files; // Access to file names (with wildcards) static V3ConfigResolver s_singleton; // Singleton (not via local static, as that's slow) - V3ConfigResolver() {} - ~V3ConfigResolver() {} + V3ConfigResolver() = default; + ~V3ConfigResolver() = default; public: inline static V3ConfigResolver& s() { return s_singleton; } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 8f71622b6..b2370d1ce 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -52,7 +52,7 @@ public: AstNode::user4ClearTree(); // Check marked InUse before we're called iterate(nodep); } - virtual ~ConstVarMarkVisitor() override {} + virtual ~ConstVarMarkVisitor() override = default; }; class ConstVarFindVisitor : public AstNVisitor { @@ -71,7 +71,7 @@ private: public: // CONSTRUCTORS explicit ConstVarFindVisitor(AstNode* nodep) { iterateAndNextNull(nodep); } - virtual ~ConstVarFindVisitor() override {} + virtual ~ConstVarFindVisitor() override = default; // METHODS bool found() const { return m_found; } }; @@ -2563,7 +2563,7 @@ public: } // clang-format on } - virtual ~ConstVisitor() override {} + virtual ~ConstVisitor() override = default; AstNode* mainAcceptEdit(AstNode* nodep) { // Operate starting at a random place return iterateSubtreeReturnEdits(nodep); diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index a216b385c..4019953e8 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -52,7 +52,7 @@ private: : m_comment{comment} , m_varRefp{vp} , m_chgRefp{cp} {} - ~ToggleEnt() {} + ~ToggleEnt() = default; void cleanup() { VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = nullptr); VL_DO_CLEAR(m_chgRefp->deleteTree(), m_chgRefp = nullptr); @@ -64,7 +64,7 @@ private: bool m_inModOff = false; // In module with no coverage int m_handle = 0; // Opaque handle for index into line tracking const AstNode* m_nodep = nullptr; // Node establishing this state - CheckState() {} + CheckState() = default; bool lineCoverageOn(const AstNode* nodep) const { return m_on && !m_inModOff && nodep->fileline()->coverageOn() && v3Global.opt.coverageLine(); @@ -534,7 +534,7 @@ private: public: // CONSTRUCTORS explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); } - virtual ~CoverageVisitor() override {} + virtual ~CoverageVisitor() override = default; }; //###################################################################### diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 7b75e4bdb..718131703 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -63,7 +63,7 @@ private: public: // CONSTRUCTORS explicit DeadModVisitor(AstNodeModule* nodep) { iterate(nodep); } - virtual ~DeadModVisitor() override {} + virtual ~DeadModVisitor() override = default; }; //###################################################################### @@ -461,7 +461,7 @@ public: // We may have removed some datatypes, cleanup nodep->typeTablep()->repairCache(); } - virtual ~DeadVisitor() override {} + virtual ~DeadVisitor() override = default; }; //###################################################################### diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index fce9b9cf4..158bf4f85 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -155,7 +155,7 @@ private: public: // CONSTRUCTORS explicit DepthVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~DepthVisitor() override {} + virtual ~DepthVisitor() override = default; }; //###################################################################### diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index b4346db8d..a95592ab8 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -117,7 +117,7 @@ private: public: // CONSTRUCTORS explicit DepthBlockVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~DepthBlockVisitor() override {} + virtual ~DepthBlockVisitor() override = default; }; //###################################################################### diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index dcaddcae5..fb864118d 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -296,7 +296,7 @@ private: public: // CONSTRUCTORS explicit DescopeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~DescopeVisitor() override {} + virtual ~DescopeVisitor() override = default; }; //###################################################################### diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 79a11f158..4dabe5e7c 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -1258,7 +1258,7 @@ public: m_trackText = trackText; iterate(nodep); } - virtual ~EmitCStmts() override {} + virtual ~EmitCStmts() override = default; }; //###################################################################### @@ -1276,7 +1276,7 @@ public: : m_mtaskIds(mtaskIds) { // Cannot be {} or GCC 4.8 false warning m_serial = ++m_serialNext; // Cannot be ()/{} or GCC 4.8 false warning } - virtual ~EmitVarTspSorter() {} + virtual ~EmitVarTspSorter() = default; // METHODS virtual bool operator<(const TspStateBase& other) const override { return operator<(dynamic_cast(other)); @@ -1840,8 +1840,8 @@ class EmitCImp : EmitCStmts { void maybeSplit(AstNodeModule* modp); public: - EmitCImp() {} - virtual ~EmitCImp() override {} + EmitCImp() = default; + virtual ~EmitCImp() override = default; void mainImp(AstNodeModule* modp, bool slow); void mainInt(AstNodeModule* modp); void mainDoFunc(AstCFunc* nodep) { iterate(nodep); } @@ -3840,7 +3840,7 @@ class EmitCTrace : EmitCStmts { public: explicit EmitCTrace(bool slow) : m_slow{slow} {} - virtual ~EmitCTrace() override {} + virtual ~EmitCTrace() override = default; void main() { // Put out the file newOutCFile(0); diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 75e4838ec..87bdb58bc 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -106,8 +106,8 @@ public: } // CONSTRUCTORS - EmitCBaseVisitor() {} - virtual ~EmitCBaseVisitor() override {} + EmitCBaseVisitor() = default; + virtual ~EmitCBaseVisitor() override = default; }; //###################################################################### @@ -126,7 +126,7 @@ private: public: // CONSTRUCTORS explicit EmitCBaseCounterVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~EmitCBaseCounterVisitor() override {} + virtual ~EmitCBaseCounterVisitor() override = default; int count() const { return m_count; } }; diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index 0b7e0f52e..ce830611e 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -256,7 +256,7 @@ class CMakeEmitter { public: explicit CMakeEmitter() { emitOverallCMake(); } - virtual ~CMakeEmitter() {} + virtual ~CMakeEmitter() = default; }; void V3EmitCMake::emit() { diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index f0e63fa1d..eb88e4cdb 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -467,7 +467,7 @@ void EmitCSyms::emitSymHdr() { puts("\n// CREATORS\n"); puts(symClassName() + "(" + topClassName() + "* topp, const char* namep);\n"); - puts(string("~") + symClassName() + "() {}\n"); + puts(string("~") + symClassName() + "() = default;\n"); for (const auto& i : m_usesVfinal) { puts("void " + symClassName() + "_" + cvtToStr(i.first) + "("); diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 0a55a2ef9..1c9f11cba 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -285,7 +285,7 @@ public: emitClassMake(); emitOverallMake(); } - virtual ~EmitMk() {} + virtual ~EmitMk() = default; }; //###################################################################### diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index aa53317dd..fb3974f7f 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -667,7 +667,7 @@ public: explicit EmitVBaseVisitor(bool suppressUnknown, AstSenTree* domainp) : m_suppressUnknown{suppressUnknown} , m_sensesp{domainp} {} - virtual ~EmitVBaseVisitor() override {} + virtual ~EmitVBaseVisitor() override = default; }; //###################################################################### @@ -693,7 +693,7 @@ public: m_suppressVarSemi = suppressVarSemi; iterate(nodep); } - virtual ~EmitVFileVisitor() override {} + virtual ~EmitVFileVisitor() override = default; }; //###################################################################### @@ -715,7 +715,7 @@ public: , m_os(os) { // Need () or GCC 4.8 false warning iterate(nodep); } - virtual ~EmitVStreamVisitor() override {} + virtual ~EmitVStreamVisitor() override = default; }; //###################################################################### @@ -792,7 +792,7 @@ public: if (user3mark) { AstUser3InUse::check(); } iterate(nodep); } - virtual ~EmitVPrefixedVisitor() override {} + virtual ~EmitVPrefixedVisitor() override = default; }; //###################################################################### diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index da2d26720..e607a8db8 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -250,7 +250,7 @@ public: : m_ofp{ofp} { iterate(nodep); } - virtual ~EmitXmlFileVisitor() override {} + virtual ~EmitXmlFileVisitor() override = default; }; //###################################################################### @@ -298,7 +298,7 @@ public: } m_os << "\n"; } - virtual ~ModuleFilesXmlVisitor() override {} + virtual ~ModuleFilesXmlVisitor() override = default; }; //###################################################################### @@ -363,7 +363,7 @@ public: // Operate on whole netlist nodep->accept(*this); } - virtual ~HierCellsXmlVisitor() override {} + virtual ~HierCellsXmlVisitor() override = default; }; //###################################################################### diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index fb6bc7c43..3bb2d2451 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -879,7 +879,7 @@ private: public: // CONSTRUCTORS explicit ExpandVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ExpandVisitor() override {} + virtual ~ExpandVisitor() override = default; }; //---------------------------------------------------------------------- diff --git a/src/V3File.cpp b/src/V3File.cpp index f2cc0f6a9..59a2236c0 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -77,7 +77,7 @@ class V3FileDependImp { m_stat.st_ctime = 0; m_stat.st_mtime = 0; } - ~DependFile() {} + ~DependFile() = default; const string& filename() const { return m_filename; } bool target() const { return m_target; } bool exists() const { return m_exists; } @@ -971,7 +971,7 @@ public: passthru("vlTOPp"); passthru("vlSymsp"); } - ~VIdProtectImp() {} + ~VIdProtectImp() = default; // METHODS string passthru(const string& old) { if (!v3Global.opt.protectIds()) return old; diff --git a/src/V3File.h b/src/V3File.h index 98145475e..5b841fe59 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -130,7 +130,7 @@ private: public: V3OutFormatter(const string& filename, Language lang); - virtual ~V3OutFormatter() {} + virtual ~V3OutFormatter() = default; // ACCESSORS string filename() const { return m_filename; } int column() const { return m_column; } @@ -198,7 +198,7 @@ public: : V3OutFile{filename, V3OutFormatter::LA_C} { resetPrivate(); } - virtual ~V3OutCFile() override {} + virtual ~V3OutCFile() override = default; virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); } virtual void putsIntTopInclude() { putsForceIncs(); } virtual void putsGuard(); @@ -222,7 +222,7 @@ class V3OutScFile : public V3OutCFile { public: explicit V3OutScFile(const string& filename) : V3OutCFile{filename} {} - virtual ~V3OutScFile() override {} + virtual ~V3OutScFile() override = default; virtual void putsHeader() override { puts("// Verilated -*- SystemC -*-\n"); } virtual void putsIntTopInclude() override { putsForceIncs(); @@ -235,7 +235,7 @@ class V3OutVFile : public V3OutFile { public: explicit V3OutVFile(const string& filename) : V3OutFile{filename, V3OutFormatter::LA_VERILOG} {} - virtual ~V3OutVFile() override {} + virtual ~V3OutVFile() override = default; virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); } }; @@ -245,7 +245,7 @@ public: : V3OutFile{filename, V3OutFormatter::LA_XML} { blockIndent(2); } - virtual ~V3OutXmlFile() override {} + virtual ~V3OutXmlFile() override = default; virtual void putsHeader() { puts("\n"); } }; @@ -253,7 +253,7 @@ class V3OutMkFile : public V3OutFile { public: explicit V3OutMkFile(const string& filename) : V3OutFile{filename, V3OutFormatter::LA_MK} {} - virtual ~V3OutMkFile() override {} + virtual ~V3OutMkFile() override = default; virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); } // No automatic indentation yet. void puts(const char* strg) { putsNoTracking(strg); } diff --git a/src/V3FileLine.h b/src/V3FileLine.h index e6c1941ff..64adea8d4 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -45,8 +45,8 @@ class FileLineSingleton { std::deque m_names; // filename text for each filenameno std::deque m_languages; // language for each filenameno // CONSTRUCTORS - FileLineSingleton() {} - ~FileLineSingleton() {} + FileLineSingleton() = default; + ~FileLineSingleton() = default; protected: friend class FileLine; @@ -73,7 +73,7 @@ public: static int s_id = 0; m_id = ++s_id; } - ~VFileContent() {} + ~VFileContent() = default; // METHODS void pushText(const string& text); // Add arbitrary text (need not be line-by-line) string getLine(int lineno) const; @@ -143,7 +143,7 @@ public: explicit FileLine(EmptySecret); FileLine* copyOrSameFileLine(); static void deleteAllRemaining(); - ~FileLine() {} + ~FileLine() = default; #ifdef VL_LEAK_CHECKS static void* operator new(size_t size); static void operator delete(void* obj, size_t size); diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 3d53fb356..b0b7d0a20 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -57,7 +57,7 @@ public: V3Graph* m_graphp; // Graph this class is visiting explicit GateGraphBaseVisitor(V3Graph* graphp) : m_graphp{graphp} {} - virtual ~GateGraphBaseVisitor() {} + virtual ~GateGraphBaseVisitor() = default; virtual VNUser visit(GateLogicVertex* vertexp, VNUser vu = VNUser(0)) = 0; virtual VNUser visit(GateVarVertex* vertexp, VNUser vu = VNUser(0)) = 0; VL_DEBUG_FUNC; // Declare debug() @@ -75,7 +75,7 @@ public: GateEitherVertex(V3Graph* graphp, AstScope* scopep) : V3GraphVertex{graphp} , m_scopep{scopep} {} - virtual ~GateEitherVertex() override {} + virtual ~GateEitherVertex() override = default; // ACCESSORS virtual string dotStyle() const override { return m_consumed ? "" : "dotted"; } AstScope* scopep() const { return m_scopep; } @@ -133,7 +133,7 @@ public: GateVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : GateEitherVertex{graphp, scopep} , m_varScp{varScp} {} - virtual ~GateVarVertex() override {} + virtual ~GateVarVertex() override = default; // ACCESSORS AstVarScope* varScp() const { return m_varScp; } virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); } @@ -174,7 +174,7 @@ public: , m_nodep{nodep} , m_activep{activep} , m_slow{slow} {} - virtual ~GateLogicVertex() override {} + virtual ~GateLogicVertex() override = default; // ACCESSORS virtual string name() const override { return (cvtToHex(m_nodep) + "@" + scopep()->prettyName()); @@ -291,7 +291,7 @@ public: } if (debug() >= 9 && !m_isSimple) nodep->dumpTree(cout, " gate!Ok: "); } - virtual ~GateOkVisitor() override {} + virtual ~GateOkVisitor() override = default; // PUBLIC METHODS bool isSimple() const { return m_isSimple; } AstNode* substTree() const { return m_substTreep; } @@ -870,7 +870,7 @@ private: public: // CONSTRUCTORS - virtual ~GateElimVisitor() override {} + virtual ~GateElimVisitor() override = default; GateElimVisitor(AstNode* nodep, AstVarScope* varscp, AstNode* replaceTreep, GateDedupeVarVisitor* varVisp) { UINFO(9, " elimvisitor " << nodep << endl); @@ -939,7 +939,7 @@ private: } public: - GateDedupeHash() {} + GateDedupeHash() = default; virtual ~GateDedupeHash() override { if (v3Global.opt.debugCheck()) check(); } @@ -1086,8 +1086,8 @@ private: public: // CONSTRUCTORS - GateDedupeVarVisitor() {} - virtual ~GateDedupeVarVisitor() override {} + GateDedupeVarVisitor() = default; + virtual ~GateDedupeVarVisitor() override = default; // PUBLIC METHODS AstNodeVarRef* findDupe(AstNode* nodep, AstVarScope* consumerVarScopep, AstActive* activep) { m_assignp = nullptr; @@ -1409,8 +1409,8 @@ private: public: // CONSTRUCTORS - GateConcatVisitor() {} - virtual ~GateConcatVisitor() override {} + GateConcatVisitor() = default; + virtual ~GateConcatVisitor() override = default; // PUBLIC METHODS bool concatOffset(AstConcat* concatp, AstVarScope* vscp, int& offsetr) { m_vscp = vscp; @@ -1436,7 +1436,7 @@ public: GateClkDecompState(int offset, AstVarScope* vsp) : m_offset{offset} , m_last_vsp{vsp} {} - virtual ~GateClkDecompState() {} + virtual ~GateClkDecompState() = default; }; class GateClkDecompGraphVisitor : public GateGraphBaseVisitor { @@ -1591,7 +1591,7 @@ private: public: // CONSTRUCTORS explicit GateDeassignVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~GateDeassignVisitor() override {} + virtual ~GateDeassignVisitor() override = default; }; //###################################################################### diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index 0aa972080..60ebff081 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -121,7 +121,7 @@ public: : m_topModp{topModp} { iterate(nodep); } - virtual ~GenClkRenameVisitor() override {} + virtual ~GenClkRenameVisitor() override = default; }; //###################################################################### @@ -214,7 +214,7 @@ private: public: // CONSTRUCTORS explicit GenClkReadVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~GenClkReadVisitor() override {} + virtual ~GenClkReadVisitor() override = default; }; //###################################################################### diff --git a/src/V3Graph.h b/src/V3Graph.h index c8d0b2431..d4dbab874 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -218,7 +218,7 @@ public: virtual V3GraphVertex* clone(V3Graph* graphp) const { return new V3GraphVertex(graphp, *this); } - virtual ~V3GraphVertex() {} + virtual ~V3GraphVertex() = default; void unlinkEdges(V3Graph* graphp); void unlinkDelete(V3Graph* graphp); @@ -317,7 +317,7 @@ public: virtual V3GraphEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const { return new V3GraphEdge(graphp, fromp, top, *this); } - virtual ~V3GraphEdge() {} + virtual ~V3GraphEdge() = default; // METHODS virtual string name() const { return m_fromp->name() + "->" + m_top->name(); } virtual string dotLabel() const { return ""; } diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 57fc442e6..4eff24c30 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -42,7 +42,7 @@ public: GraphAcycVertex(V3Graph* graphp, V3GraphVertex* origVertexp) : V3GraphVertex{graphp} , m_origVertexp{origVertexp} {} - virtual ~GraphAcycVertex() override {} + virtual ~GraphAcycVertex() override = default; V3GraphVertex* origVertexp() const { return m_origVertexp; } void setDelete() { m_deleted = true; } bool isDelete() const { return m_deleted; } @@ -67,7 +67,7 @@ public: GraphAcycEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = false) : V3GraphEdge{graphp, fromp, top, weight, cutable} {} - virtual ~GraphAcycEdge() override {} + virtual ~GraphAcycEdge() override = default; // yellow=we might still cut it, else oldEdge: yellowGreen=made uncutable, red=uncutable virtual string dotColor() const override { return (cutable() ? "yellow" : origEdgep()->dotColor()); diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index 504c719cf..218d050a3 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -123,7 +123,7 @@ public: , m_sumWeights{sumWeights} { main(); } - ~GraphRemoveRedundant() {} + ~GraphRemoveRedundant() = default; }; void V3Graph::removeRedundantEdges(V3EdgeFuncP edgeFuncp) { @@ -200,7 +200,7 @@ public: : GraphAlg<>(graphp, edgeFuncp) { main(); } - ~GraphAlgWeakly() {} + ~GraphAlgWeakly() = default; }; void V3Graph::weaklyConnected(V3EdgeFuncP edgeFuncp) { GraphAlgWeakly(this, edgeFuncp); } @@ -288,7 +288,7 @@ public: m_currentDfs = 0; main(); } - ~GraphAlgStrongly() {} + ~GraphAlgStrongly() = default; }; void V3Graph::stronglyConnected(V3EdgeFuncP edgeFuncp) { GraphAlgStrongly(this, edgeFuncp); } @@ -339,7 +339,7 @@ public: : GraphAlg<>{graphp, edgeFuncp} { main(); } - ~GraphAlgRank() {} + ~GraphAlgRank() = default; }; void V3Graph::rank() { GraphAlgRank(this, &V3GraphEdge::followAlwaysTrue); } @@ -393,7 +393,7 @@ public: m_done = false; main(vertexp); } - ~GraphAlgRLoops() {} + ~GraphAlgRLoops() = default; }; void V3Graph::reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) { @@ -441,7 +441,7 @@ public: m_graphp->userClearEdges(); (void)vertexIterateAll(vertexp); } - ~GraphAlgSubtrees() {} + ~GraphAlgSubtrees() = default; }; //! Report the entire connected graph with a loop or loops diff --git a/src/V3GraphAlg.h b/src/V3GraphAlg.h index 3d7abaea5..408e99c46 100644 --- a/src/V3GraphAlg.h +++ b/src/V3GraphAlg.h @@ -36,7 +36,7 @@ protected: GraphAlg(T_Graph* graphp, V3EdgeFuncP edgeFuncp) : m_graphp{graphp} , m_edgeFuncp{edgeFuncp} {} - ~GraphAlg() {} + ~GraphAlg() = default; // METHODS inline bool followEdge(V3GraphEdge* edgep) { return (edgep->weight() && (m_edgeFuncp)(edgep)); diff --git a/src/V3GraphDfa.cpp b/src/V3GraphDfa.cpp index 2c8f0bb48..c114f8632 100644 --- a/src/V3GraphDfa.cpp +++ b/src/V3GraphDfa.cpp @@ -368,7 +368,7 @@ public: m_step = 0; main(); } - ~GraphNfaToDfa() {} + ~GraphNfaToDfa() = default; }; void DfaGraph::nfaToDfa() { GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue); } @@ -502,7 +502,7 @@ public: optimize_no_outbound(); if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_noout"); } - ~DfaGraphReduce() {} + ~DfaGraphReduce() = default; }; void DfaGraph::dfaReduce() { DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue); } @@ -598,7 +598,7 @@ public: VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = nullptr); if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_out"); } - ~DfaGraphComplement() {} + ~DfaGraphComplement() = default; VL_UNCOPYABLE(DfaGraphComplement); }; diff --git a/src/V3GraphDfa.h b/src/V3GraphDfa.h index a2ec64bd8..027724506 100644 --- a/src/V3GraphDfa.h +++ b/src/V3GraphDfa.h @@ -61,8 +61,8 @@ class DfaEdge; class DfaGraph : public V3Graph { public: // CONSTRUCTORS - DfaGraph() {} - virtual ~DfaGraph() override {} + DfaGraph() = default; + virtual ~DfaGraph() override = default; // METHODS /// Find start node DfaVertex* findStart(); @@ -93,7 +93,7 @@ public: virtual DfaVertex* clone(DfaGraph* graphp) { return new DfaVertex(graphp, start(), accepting()); } - virtual ~DfaVertex() override {} + virtual ~DfaVertex() override = default; // ACCESSORS virtual string dotShape() const override { return (accepting() ? "doublecircle" : ""); } virtual string dotColor() const override { @@ -128,7 +128,7 @@ public: : V3GraphEdge{graphp, fromp, top, copyfrom->weight()} , m_input{copyfrom->input()} , m_complement{copyfrom->complement()} {} - virtual ~DfaEdge() override {} + virtual ~DfaEdge() override = default; // METHODS virtual string dotColor() const override { return (na() ? "yellow" : epsilon() ? "green" : "black"); diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp index 05d14a167..8867d2cfa 100644 --- a/src/V3GraphPathChecker.cpp +++ b/src/V3GraphPathChecker.cpp @@ -44,7 +44,7 @@ struct GraphPCNode { GraphPCNode() { for (unsigned int& w : m_cp) w = 0; } - ~GraphPCNode() {} + ~GraphPCNode() = default; }; //###################################################################### diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index 233184397..d8a44a472 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -132,7 +132,7 @@ public: } } } - ~GraphStream() {} + ~GraphStream() = default; // METHODS diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index ac2f66f48..ba12e0284 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -40,8 +40,8 @@ protected: } public: - V3GraphTest() {} - virtual ~V3GraphTest() {} + V3GraphTest() = default; + virtual ~V3GraphTest() = default; VL_DEBUG_FUNC; // Declare debug() void run() { runTest(); } }; @@ -57,7 +57,7 @@ public: V3GraphTestVertex(V3Graph* graphp, const string& name) : V3GraphVertex{graphp} , m_name{name} {} - virtual ~V3GraphTestVertex() override {} + virtual ~V3GraphTestVertex() override = default; // ACCESSORS virtual string name() const override { return m_name; } }; @@ -66,7 +66,7 @@ class V3GraphTestVarVertex : public V3GraphTestVertex { public: V3GraphTestVarVertex(V3Graph* graphp, const string& name) : V3GraphTestVertex{graphp, name} {} - virtual ~V3GraphTestVarVertex() override {} + virtual ~V3GraphTestVarVertex() override = default; // ACCESSORS virtual string dotColor() const override { return "blue"; } }; @@ -267,7 +267,7 @@ public: DfaTestVertex(DfaGraph* graphp, const string& name) : DfaVertex{graphp} , m_name{name} {} - virtual ~DfaTestVertex() override {} + virtual ~DfaTestVertex() override = default; // ACCESSORS virtual string name() const override { return m_name; } }; diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index 14579bc87..e830f0ab7 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -102,7 +102,7 @@ public: nodeHashIterate(const_cast(nodep)); } V3Hash finalHash() const { return m_lowerHash; } - virtual ~HashedVisitor() override {} + virtual ~HashedVisitor() override = default; }; //###################################################################### diff --git a/src/V3Hashed.h b/src/V3Hashed.h index 0fc0ace5a..0f8afbac1 100644 --- a/src/V3Hashed.h +++ b/src/V3Hashed.h @@ -27,8 +27,8 @@ class VHashedBase { public: // CONSTRUCTORS - VHashedBase() {} - ~VHashedBase() {} + VHashedBase() = default; + ~VHashedBase() = default; // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -39,8 +39,8 @@ public: struct V3HashedUserSame { // Functor for V3Hashed::findDuplicate virtual bool isSame(AstNode*, AstNode*) = 0; - V3HashedUserSame() {} - virtual ~V3HashedUserSame() {} + V3HashedUserSame() = default; + virtual ~V3HashedUserSame() = default; }; class V3Hashed : public VHashedBase { @@ -60,7 +60,7 @@ private: public: // CONSTRUCTORS V3Hashed() { clear(); } - ~V3Hashed() {} + ~V3Hashed() = default; // ACCESSORS HashMmap& mmap() { return m_hashMmap; } // Return map for iteration diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index f605723fc..198877007 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -304,8 +304,6 @@ public: //###################################################################### -V3HierBlockPlan::V3HierBlockPlan() {} - bool V3HierBlockPlan::isHierBlock(const AstNodeModule* modp) const { return m_blocks.find(modp) != m_blocks.end(); } diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h index d5898dc34..81e0603ae 100644 --- a/src/V3HierBlock.h +++ b/src/V3HierBlock.h @@ -99,7 +99,7 @@ class V3HierBlockPlan { typedef std::map HierMap; HierMap m_blocks; - V3HierBlockPlan(); + V3HierBlockPlan() = default; VL_UNCOPYABLE(V3HierBlockPlan); public: diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 01ef648fd..f66f2a0f8 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -254,7 +254,7 @@ public: explicit InlineCollectVisitor(AstNodeModule* nodep) { // passed OLD module, not new one iterate(nodep); } - virtual ~InlineCollectVisitor() override {} + virtual ~InlineCollectVisitor() override = default; }; //###################################################################### @@ -474,7 +474,7 @@ public: , m_cellp{cellp} { iterate(cloneModp); } - virtual ~InlineRelinkVisitor() override {} + virtual ~InlineRelinkVisitor() override = default; }; //###################################################################### @@ -702,7 +702,7 @@ private: public: // CONSTRUCTORS explicit InlineIntfRefVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~InlineIntfRefVisitor() override {} + virtual ~InlineIntfRefVisitor() override = default; }; //###################################################################### diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index adc210e24..022388977 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -132,7 +132,7 @@ private: public: // CONSTRUCTORS explicit InstVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~InstVisitor() override {} + virtual ~InstVisitor() override = default; }; //###################################################################### @@ -178,13 +178,13 @@ public: } // CONSTRUCTORS - explicit InstDeModVarVisitor() {} + InstDeModVarVisitor() = default; + virtual ~InstDeModVarVisitor() override = default; void main(AstNodeModule* nodep) { UINFO(8, " dmMODULE " << nodep << endl); m_modVarNameMap.clear(); iterate(nodep); } - virtual ~InstDeModVarVisitor() override {} }; //###################################################################### @@ -466,7 +466,7 @@ private: public: // CONSTRUCTORS explicit InstDeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~InstDeVisitor() override {} + virtual ~InstDeVisitor() override = default; }; //###################################################################### @@ -475,7 +475,7 @@ public: class InstStatic { private: VL_DEBUG_FUNC; // Declare debug() - InstStatic() {} // Static class + InstStatic() = default; // Static class static AstNode* extendOrSel(FileLine* fl, AstNode* rhsp, AstNode* cmpWidthp) { if (cmpWidthp->width() > rhsp->width()) { diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 85ca8f3c9..5eb23fae9 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -74,7 +74,7 @@ public: , m_osp{osp} { if (nodep) iterate(nodep); } - virtual ~InstrCountVisitor() override {} + virtual ~InstrCountVisitor() override = default; // METHODS uint32_t instrCount() const { return m_instrCount; } @@ -275,7 +275,7 @@ public: UASSERT_OBJ(osp, nodep, "Don't call if not dumping"); if (nodep) iterate(nodep); } - virtual ~InstrCountDumpVisitor() override {} + virtual ~InstrCountDumpVisitor() override = default; private: // METHODS diff --git a/src/V3Life.cpp b/src/V3Life.cpp index a2ea3efd8..7663ca404 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -50,7 +50,7 @@ public: std::vector m_unlinkps; // CONSTRUCTORS - LifeState() {} + LifeState() = default; ~LifeState() { V3Stats::addStatSum("Optimizations, Lifetime assign deletions", m_statAssnDel); V3Stats::addStatSum("Optimizations, Lifetime constant prop", m_statAssnCon); @@ -92,7 +92,7 @@ public: : m_setBeforeUse{false} { consumed(); } - ~LifeVarEntry() {} + ~LifeVarEntry() = default; inline void simpleAssign(AstNodeAssign* assp) { // New simple A=.... assignment m_assignp = assp; m_constp = nullptr; @@ -135,7 +135,7 @@ public: m_aboveLifep = aboveLifep; // Null if top m_statep = statep; } - ~LifeBlock() {} + ~LifeBlock() = default; // METHODS void checkRemoveAssign(const LifeMap::iterator& it) { AstVar* varp = it->first->varp(); @@ -479,7 +479,7 @@ public: : m_statep{statep} { iterate(nodep); } - virtual ~LifeTopVisitor() override {} + virtual ~LifeTopVisitor() override = default; }; //###################################################################### diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index 4e254a991..a633af7ce 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -91,7 +91,7 @@ private: public: // CONSTRUCTORS explicit LifePostElimVisitor(AstTopScope* nodep) { iterate(nodep); } - virtual ~LifePostElimVisitor() override {} + virtual ~LifePostElimVisitor() override = default; }; //###################################################################### @@ -103,7 +103,7 @@ struct LifeLocation { uint32_t sequence = 0; public: - LifeLocation() {} + LifeLocation() = default; LifeLocation(const ExecMTask* mtaskp_, uint32_t sequence_) : mtaskp{mtaskp_} , sequence{sequence_} {} @@ -119,7 +119,7 @@ public: struct LifePostLocation { LifeLocation loc; AstAssignPost* nodep = nullptr; - LifePostLocation() {} + LifePostLocation() = default; LifePostLocation(LifeLocation loc_, AstAssignPost* nodep_) : loc{loc_} , nodep{nodep_} {} diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index b97e1261b..73e688c3e 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -43,8 +43,8 @@ class LinkCellsGraph : public V3Graph { public: - LinkCellsGraph() {} - virtual ~LinkCellsGraph() override {} + LinkCellsGraph() = default; + virtual ~LinkCellsGraph() override = default; virtual void loopsMessageCb(V3GraphVertex* vertexp) override; }; @@ -55,7 +55,7 @@ public: LinkCellsVertex(V3Graph* graphp, AstNodeModule* modp) : V3GraphVertex{graphp} , m_modp{modp} {} - virtual ~LinkCellsVertex() override {} + virtual ~LinkCellsVertex() override = default; AstNodeModule* modp() const { return m_modp; } virtual string name() const override { return modp()->name(); } virtual FileLine* fileline() const override { return modp()->fileline(); } @@ -69,7 +69,7 @@ class LibraryVertex : public V3GraphVertex { public: explicit LibraryVertex(V3Graph* graphp) : V3GraphVertex{graphp} {} - virtual ~LibraryVertex() override {} + virtual ~LibraryVertex() override = default; virtual string name() const override { return "*LIBRARY*"; } }; @@ -517,7 +517,7 @@ public: } iterate(nodep); } - virtual ~LinkCellsVisitor() override {} + virtual ~LinkCellsVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 850ea63e2..5d07c5457 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1314,7 +1314,7 @@ public: iterate(rootp); } - virtual ~LinkDotFindVisitor() override {} + virtual ~LinkDotFindVisitor() override = default; }; //====================================================================== @@ -1479,7 +1479,7 @@ public: UINFO(4, __FUNCTION__ << ": " << endl); iterate(rootp); } - virtual ~LinkDotParamVisitor() override {} + virtual ~LinkDotParamVisitor() override = default; }; //====================================================================== @@ -1637,7 +1637,7 @@ public: UINFO(4, __FUNCTION__ << ": " << endl); iterate(rootp); } - virtual ~LinkDotScopeVisitor() override {} + virtual ~LinkDotScopeVisitor() override = default; }; //====================================================================== @@ -1722,7 +1722,7 @@ public: m_statep = statep; iterate(nodep); } - virtual ~LinkDotIfaceVisitor() override {} + virtual ~LinkDotIfaceVisitor() override = default; }; void LinkDotState::computeIfaceModSyms() { @@ -1777,7 +1777,7 @@ private: bool m_dotErr; // Error found in dotted resolution, ignore upwards string m_dotText; // String of dotted names found in below parseref DotStates() { init(nullptr); } - ~DotStates() {} + ~DotStates() = default; void init(VSymEnt* curSymp) { m_dotPos = DP_NONE; m_dotSymp = curSymp; @@ -2919,7 +2919,7 @@ public: UINFO(4, __FUNCTION__ << ": " << endl); iterate(rootp); } - virtual ~LinkDotResolveVisitor() override {} + virtual ~LinkDotResolveVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index c7cf6298a..db1f00fa1 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -238,7 +238,7 @@ private: public: // CONSTRUCTORS explicit LinkIncVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LinkIncVisitor() override {} + virtual ~LinkIncVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 0bccce54a..a83387885 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -282,7 +282,7 @@ private: public: // CONSTRUCTORS explicit LinkJumpVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LinkJumpVisitor() override {} + virtual ~LinkJumpVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index d5a26d0f5..999950d8e 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -290,7 +290,7 @@ public: : m_setRefLvalue{start} { iterate(nodep); } - virtual ~LinkLValueVisitor() override {} + virtual ~LinkLValueVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 14cc8d494..19c065d24 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -606,7 +606,7 @@ private: public: // CONSTRUCTORS explicit LinkParseVisitor(AstNetlist* rootp) { iterate(rootp); } - virtual ~LinkParseVisitor() override {} + virtual ~LinkParseVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 190c4c4a8..eccb7318a 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -517,7 +517,7 @@ private: public: // CONSTRUCTORS explicit LinkResolveVisitor(AstNetlist* rootp) { iterate(rootp); } - virtual ~LinkResolveVisitor() override {} + virtual ~LinkResolveVisitor() override = default; }; //###################################################################### @@ -556,7 +556,7 @@ private: public: // CONSTRUCTORS explicit LinkBotupVisitor(AstNetlist* rootp) { iterate(rootp); } - virtual ~LinkBotupVisitor() override {} + virtual ~LinkBotupVisitor() override = default; }; //###################################################################### diff --git a/src/V3List.h b/src/V3List.h index 5022e6d38..0b4bc399b 100644 --- a/src/V3List.h +++ b/src/V3List.h @@ -36,8 +36,8 @@ private: friend class V3ListEnt; public: - V3List() {} - ~V3List() {} + V3List() = default; + ~V3List() = default; // METHODS T begin() const { return m_headp; } T end() const { return nullptr; } @@ -65,7 +65,7 @@ private: } public: - V3ListEnt() {} + V3ListEnt() = default; ~V3ListEnt() { #ifdef VL_DEBUG // Load bogus pointers so we can catch deletion bugs diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index f412649cf..6ac5830f1 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -85,7 +85,7 @@ private: public: // CONSTRUCTORS explicit LocalizeDehierVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LocalizeDehierVisitor() override {} + virtual ~LocalizeDehierVisitor() override = default; }; //###################################################################### diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index e7dcb3955..967c715d3 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -86,7 +86,7 @@ private: } public: - CheckMergeableVisitor() {} + CheckMergeableVisitor() = default; // Return false if this node should not be merged at all because: // - It contains an impure expression diff --git a/src/V3Name.cpp b/src/V3Name.cpp index 0d5401bf5..1ac76a283 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -136,7 +136,7 @@ private: public: // CONSTRUCTORS explicit NameVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~NameVisitor() override {} + virtual ~NameVisitor() override = default; }; //###################################################################### diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 799c7ed87..b8ec760e5 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -99,8 +99,8 @@ public: m_libExtVs.push_back(libext); } } - V3OptionsImp() {} - ~V3OptionsImp() {} + V3OptionsImp() = default; + ~V3OptionsImp() = default; }; //###################################################################### diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 862e7d366..baeda2cb1 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -219,7 +219,7 @@ public: OrderUser() { for (auto& vertexp : m_vertexp) vertexp = nullptr; } - ~OrderUser() {} + ~OrderUser() = default; }; //###################################################################### @@ -366,7 +366,7 @@ public: iterate(nodep); } while (m_newClkMarked); } - virtual ~OrderClkMarkVisitor() override {} + virtual ~OrderClkMarkVisitor() override = default; }; //###################################################################### @@ -397,7 +397,7 @@ private: public: // CONSTRUCTORS explicit OrderClkAssVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~OrderClkAssVisitor() override {} + virtual ~OrderClkAssVisitor() override = default; // METHODS bool isClkAss() const { return m_clkAss; } }; @@ -457,7 +457,7 @@ public: : m_graphp{logicGraphp} , m_outGraphp{outGraphp} , m_vxMakerp{vxMakerp} {} - virtual ~ProcessMoveBuildGraph() {} + virtual ~ProcessMoveBuildGraph() = default; // METHODS void build() { @@ -621,8 +621,8 @@ public: class MTaskVxIdLessThan { public: - MTaskVxIdLessThan() {} - virtual ~MTaskVxIdLessThan() {} + MTaskVxIdLessThan() = default; + virtual ~MTaskVxIdLessThan() = default; // Sort vertex's, which must be AbstractMTask's, into a deterministic // order by comparing their serial IDs. @@ -755,7 +755,7 @@ private: AstMTaskBody* m_mtaskBodyp = nullptr; Logics m_logics; ExecMTask* m_execMTaskp = nullptr; - MTaskState() {} + MTaskState() = default; }; void processMTasks(); typedef enum : uint8_t { LOGIC_INITIAL, LOGIC_SETTLE } InitialLogicE; diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index e24db578a..9ff15d083 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -112,8 +112,8 @@ inline bool operator==(OrderVEdgeType::en lhs, const OrderVEdgeType& rhs) { class OrderGraph : public V3Graph { public: - OrderGraph() {} - virtual ~OrderGraph() override {} + OrderGraph() = default; + virtual ~OrderGraph() override = default; // Methods virtual void loopsVertexCb(V3GraphVertex* vertexp) override; }; @@ -137,7 +137,7 @@ public: : V3GraphVertex{graphp} , m_scopep{scopep} , m_domainp{domainp} {} - virtual ~OrderEitherVertex() override {} + virtual ~OrderEitherVertex() override = default; virtual OrderEitherVertex* clone(V3Graph* graphp) const override = 0; // Methods virtual OrderVEdgeType type() const = 0; @@ -160,7 +160,7 @@ public: : OrderEitherVertex{graphp, nullptr, domainp} { isFromInput(true); // By definition } - virtual ~OrderInputsVertex() override {} + virtual ~OrderInputsVertex() override = default; virtual OrderInputsVertex* clone(V3Graph* graphp) const override { return new OrderInputsVertex(graphp, *this); } @@ -183,7 +183,7 @@ public: OrderLogicVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp, AstNode* nodep) : OrderEitherVertex{graphp, scopep, domainp} , m_nodep{nodep} {} - virtual ~OrderLogicVertex() override {} + virtual ~OrderLogicVertex() override = default; virtual OrderLogicVertex* clone(V3Graph* graphp) const override { return new OrderLogicVertex(graphp, *this); } @@ -212,7 +212,7 @@ public: OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderEitherVertex{graphp, scopep, nullptr} , m_varScp{varScp} {} - virtual ~OrderVarVertex() override {} + virtual ~OrderVarVertex() override = default; virtual OrderVarVertex* clone(V3Graph* graphp) const override = 0; virtual OrderVEdgeType type() const override = 0; virtual FileLine* fileline() const override { return varScp()->fileline(); } @@ -231,7 +231,7 @@ class OrderVarStdVertex : public OrderVarVertex { public: OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarStdVertex() override {} + virtual ~OrderVarStdVertex() override = default; virtual OrderVarStdVertex* clone(V3Graph* graphp) const override { return new OrderVarStdVertex(graphp, *this); } @@ -249,7 +249,7 @@ class OrderVarPreVertex : public OrderVarVertex { public: OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarPreVertex() override {} + virtual ~OrderVarPreVertex() override = default; virtual OrderVarPreVertex* clone(V3Graph* graphp) const override { return new OrderVarPreVertex(graphp, *this); } @@ -271,7 +271,7 @@ public: return new OrderVarPostVertex(graphp, *this); } virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPOST; } - virtual ~OrderVarPostVertex() override {} + virtual ~OrderVarPostVertex() override = default; virtual string name() const override { return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); } @@ -285,7 +285,7 @@ class OrderVarPordVertex : public OrderVarVertex { public: OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarPordVertex() override {} + virtual ~OrderVarPordVertex() override = default; virtual OrderVarPordVertex* clone(V3Graph* graphp) const override { return new OrderVarPordVertex(graphp, *this); } @@ -303,7 +303,7 @@ class OrderVarSettleVertex : public OrderVarVertex { public: OrderVarSettleVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarSettleVertex() override {} + virtual ~OrderVarSettleVertex() override = default; virtual OrderVarSettleVertex* clone(V3Graph* graphp) const override { return new OrderVarSettleVertex(graphp, *this); } @@ -339,7 +339,7 @@ public: , m_logicp{logicp} , m_state{POM_WAIT} , m_domScopep{nullptr} {} - virtual ~OrderMoveVertex() override {} + virtual ~OrderMoveVertex() override = default; virtual OrderMoveVertex* clone(V3Graph* graphp) const override { v3fatalSrc("Unsupported"); return nullptr; @@ -409,7 +409,7 @@ public: , m_domainp{domainp} { UASSERT(!(logicp && varp), "MTaskMoveVertex: logicp and varp may not both be set!\n"); } - virtual ~MTaskMoveVertex() override {} + virtual ~MTaskMoveVertex() override = default; virtual MTaskMoveVertex* clone(V3Graph* graphp) const override { v3fatalSrc("Unsupported"); return nullptr; @@ -454,7 +454,7 @@ public: OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = false) : V3GraphEdge{graphp, fromp, top, weight, cutable} {} - virtual ~OrderEdge() override {} + virtual ~OrderEdge() override = default; virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; } virtual OrderEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const override { @@ -482,7 +482,7 @@ public: OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {} virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_COMBOCUT; } - virtual ~OrderComboCutEdge() override {} + virtual ~OrderComboCutEdge() override = default; virtual OrderComboCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const override { return new OrderComboCutEdge(graphp, fromp, top, *this); @@ -503,7 +503,7 @@ public: OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {} virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_POSTCUT; } - virtual ~OrderPostCutEdge() override {} + virtual ~OrderPostCutEdge() override = default; virtual OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const override { return new OrderPostCutEdge(graphp, fromp, top, *this); @@ -528,7 +528,7 @@ public: V3GraphVertex* top) const override { return new OrderPreCutEdge(graphp, fromp, top, *this); } - virtual ~OrderPreCutEdge() override {} + virtual ~OrderPreCutEdge() override = default; virtual string dotColor() const override { return "khaki"; } virtual bool followComboConnected() const override { return false; } }; diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 8b03ed87a..219356b2f 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -785,7 +785,7 @@ public: // iterate(nodep); } - virtual ~ParamVisitor() override {} + virtual ~ParamVisitor() override = default; }; //---------------------------------------------------------------------- diff --git a/src/V3ParseLex.cpp b/src/V3ParseLex.cpp index 45f0cfb96..709f2fe96 100644 --- a/src/V3ParseLex.cpp +++ b/src/V3ParseLex.cpp @@ -37,7 +37,7 @@ public: // CONSTRUCTORS V3Lexer() : V3LexerBase{nullptr} {} - ~V3Lexer() override {} + ~V3Lexer() override = default; // METHODS void unputString(const char* textp, size_t length) { // Add characters to input stream in back-to-front order diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h index 3837aa096..60a829ace 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -50,7 +50,7 @@ public: pushScope(findNewTable(rootp)); m_symCurrentp = symCurrentp(); } - ~V3ParseSym() {} + ~V3ParseSym() = default; private: // METHODS diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 978587be2..afe723493 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -253,8 +253,8 @@ private: CpMap m_seen; // Set of vertices we've seen // CONSTRUCTORS - PartPropagateCpSelfTest() {} - ~PartPropagateCpSelfTest() {} + PartPropagateCpSelfTest() = default; + ~PartPropagateCpSelfTest() = default; // METHODS protected: @@ -368,8 +368,8 @@ public: // in the future, using another Accessor adaptor. class CpCostAccessor { public: - CpCostAccessor() {} - ~CpCostAccessor() {} + CpCostAccessor() = default; + ~CpCostAccessor() = default; // Return cost of this node uint32_t cost(const V3GraphVertex* vxp) const { const LogicMTask* mtaskp = dynamic_cast(vxp); @@ -692,8 +692,8 @@ private: // which is a unique and stable serial number. class MTaskIdLessThan { public: - MTaskIdLessThan() {} - virtual ~MTaskIdLessThan() {} + MTaskIdLessThan() = default; + virtual ~MTaskIdLessThan() = default; virtual bool operator()(const AbstractMTask* lhsp, const AbstractMTask* rhsp) const { return lhsp->id() < rhsp->id(); } @@ -739,7 +739,7 @@ public: m_bp = ap; } } - virtual ~SiblingMC() {} + virtual ~SiblingMC() = default; // METHODS LogicMTask* ap() const { return m_ap; } LogicMTask* bp() const { return m_bp; } @@ -1663,7 +1663,7 @@ public: // CONSTRUCTORS explicit DpiImportCallVisitor(AstNode* nodep) { iterate(nodep); } bool hasDpiHazard() const { return m_hasDpiHazard; } - virtual ~DpiImportCallVisitor() override {} + virtual ~DpiImportCallVisitor() override = default; private: VL_UNCOPYABLE(DpiImportCallVisitor); @@ -2052,7 +2052,7 @@ public: , m_sandbagNumerator{sandbagNumerator} , m_sandbagDenom{sandbagDenom} , m_ready{m_mtaskCmp} {} - ~PartPackMTasks() {} + ~PartPackMTasks() = default; // METHODS uint32_t completionTime(const ExecMTask* mtaskp, uint32_t thread) { diff --git a/src/V3Partition.h b/src/V3Partition.h index 231ebf8d2..46cc267b2 100644 --- a/src/V3Partition.h +++ b/src/V3Partition.h @@ -41,7 +41,7 @@ public: // CONSTRUCTORS explicit V3Partition(V3Graph* fineDepsGraphp) : m_fineDepsGraphp{fineDepsGraphp} {} - ~V3Partition() {} + ~V3Partition() = default; // METHODS @@ -83,7 +83,7 @@ private: public: // CONSTRUCTORS - PartPtrIdMap() {} + PartPtrIdMap() = default; // METHODS vluint64_t findId(const void* ptrp) const { const auto it = m_id.find(ptrp); diff --git a/src/V3PartitionGraph.h b/src/V3PartitionGraph.h index d79fa83e7..789125bba 100644 --- a/src/V3PartitionGraph.h +++ b/src/V3PartitionGraph.h @@ -32,7 +32,7 @@ class AbstractMTask : public V3GraphVertex { public: AbstractMTask(V3Graph* graphp) : V3GraphVertex{graphp} {} - virtual ~AbstractMTask() override {} + virtual ~AbstractMTask() override = default; virtual uint32_t id() const = 0; virtual uint32_t cost() const = 0; }; @@ -44,7 +44,7 @@ public: // CONSTRUCTORS AbstractLogicMTask(V3Graph* graphp) : AbstractMTask{graphp} {} - virtual ~AbstractLogicMTask() override {} + virtual ~AbstractLogicMTask() override = default; // METHODS // Set of logic vertices in this mtask. Order is not significant. virtual const VxList* vertexListp() const = 0; diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 0b1b0d782..9a4250676 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -83,7 +83,7 @@ public: VDefineRef(const string& name, const string& params) : m_name{name} , m_params{params} {} - ~VDefineRef() {} + ~VDefineRef() = default; }; //************************************************************************* @@ -99,7 +99,7 @@ public: VPreIfEntry(bool on, bool everOn) : m_on{on} , m_everOn{everOn || on} {} // Note everOn includes new state - ~VPreIfEntry() {} + ~VPreIfEntry() = default; }; //************************************************************************* diff --git a/src/V3PreProc.h b/src/V3PreProc.h index de2d02215..aae1dff36 100644 --- a/src/V3PreProc.h +++ b/src/V3PreProc.h @@ -103,7 +103,7 @@ protected: public: static V3PreProc* createPreProc(FileLine* fl); - virtual ~V3PreProc() {} // LCOV_EXCL_LINE // Persistent + virtual ~V3PreProc() = default; // LCOV_EXCL_LINE // Persistent }; #endif // Guard diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp index 54de5495d..bdef192cd 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -151,8 +151,8 @@ private: public: // CONSTRUCTORS - V3PreShellImp() {} - ~V3PreShellImp() {} + V3PreShellImp() = default; + ~V3PreShellImp() = default; }; V3PreShellImp V3PreShellImp::s_preImp; diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 7e432830a..bdbff1af1 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -75,7 +75,7 @@ public: UINFO(4, " PremitAssignVisitor on " << nodep << endl); iterate(nodep); } - virtual ~PremitAssignVisitor() override {} + virtual ~PremitAssignVisitor() override = default; bool noOpt() const { return m_noopt; } }; @@ -397,7 +397,7 @@ private: public: // CONSTRUCTORS explicit PremitVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~PremitVisitor() override {} + virtual ~PremitVisitor() override = default; }; //---------------------------------------------------------------------- diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 6195ffc98..a26971951 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -313,7 +313,7 @@ private: public: // CONSTRUCTORS explicit ScopeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ScopeVisitor() override {} + virtual ~ScopeVisitor() override = default; }; //###################################################################### @@ -391,7 +391,7 @@ private: public: // CONSTRUCTORS explicit ScopeCleanupVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ScopeCleanupVisitor() override {} + virtual ~ScopeCleanupVisitor() override = default; }; //###################################################################### diff --git a/src/V3Scoreboard.cpp b/src/V3Scoreboard.cpp index a4ffda454..cf25c090e 100644 --- a/src/V3Scoreboard.cpp +++ b/src/V3Scoreboard.cpp @@ -30,7 +30,7 @@ public: static uint32_t s_serial = 0; m_id = ++s_serial; } - ScoreboardTestElem() {} + ScoreboardTestElem() = default; // METHODS static uint32_t scoreFn(const ScoreboardTestElem* elp) { return elp->m_score; } diff --git a/src/V3Scoreboard.h b/src/V3Scoreboard.h index beffd2ca7..2aa8207c3 100644 --- a/src/V3Scoreboard.h +++ b/src/V3Scoreboard.h @@ -54,7 +54,7 @@ private: public: // CONSTRUCTORS - SortByValueMap() {} + SortByValueMap() = default; class const_iterator { // TYPES @@ -375,7 +375,7 @@ public: explicit V3Scoreboard(UserScoreFnp scoreFnp, bool slowAsserts) : m_scoreFnp{scoreFnp} , m_slowAsserts{slowAsserts} {} - ~V3Scoreboard() {} + ~V3Scoreboard() = default; // METHODS diff --git a/src/V3SenTree.h b/src/V3SenTree.h index 806b5919f..b1fa10947 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -53,7 +53,7 @@ private: public: // CONSTRUCTORS - SenTreeSet() {} + SenTreeSet() = default; // METHODS void add(AstSenTree* nodep) { m_trees.insert(nodep); } @@ -81,7 +81,7 @@ private: public: // CONSTRUCTORS - SenTreeFinder() {} + SenTreeFinder() = default; // METHODS AstSenTree* getSenTree(AstSenTree* senTreep) { diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 846d303f5..cec2c81ee 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -57,7 +57,7 @@ public: SimStackNode(AstFuncRef* funcp, V3TaskConnects* tconnects) : m_funcp{funcp} , m_tconnects{tconnects} {} - ~SimStackNode() {} + ~SimStackNode() = default; }; typedef std::deque ConstDeque; diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index ccf559bbc..76a31cde6 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -225,7 +225,7 @@ class SliceVisitor : public AstNVisitor { public: // CONSTRUCTORS explicit SliceVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~SliceVisitor() override {} + virtual ~SliceVisitor() override = default; }; //###################################################################### diff --git a/src/V3Split.cpp b/src/V3Split.cpp index bb528c0ae..83fc53856 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -102,7 +102,7 @@ protected: SplitNodeVertex(V3Graph* graphp, AstNode* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~SplitNodeVertex() override {} + virtual ~SplitNodeVertex() override = default; // ACCESSORS // Do not make accessor for nodep(), It may change due to // reordering a lower block, but we don't repair it @@ -119,7 +119,7 @@ class SplitPliVertex : public SplitNodeVertex { public: explicit SplitPliVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitPliVertex() override {} + virtual ~SplitPliVertex() override = default; virtual string name() const override { return "*PLI*"; } virtual string dotColor() const override { return "green"; } }; @@ -128,7 +128,7 @@ class SplitLogicVertex : public SplitNodeVertex { public: SplitLogicVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitLogicVertex() override {} + virtual ~SplitLogicVertex() override = default; virtual string dotColor() const override { return "yellow"; } }; @@ -136,7 +136,7 @@ class SplitVarStdVertex : public SplitNodeVertex { public: SplitVarStdVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitVarStdVertex() override {} + virtual ~SplitVarStdVertex() override = default; virtual string dotColor() const override { return "skyblue"; } }; @@ -144,7 +144,7 @@ class SplitVarPostVertex : public SplitNodeVertex { public: SplitVarPostVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitVarPostVertex() override {} + virtual ~SplitVarPostVertex() override = default; virtual string name() const override { return string("POST ") + SplitNodeVertex::name(); } virtual string dotColor() const override { return "CadetBlue"; } }; @@ -160,7 +160,7 @@ protected: SplitEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = CUTABLE) : V3GraphEdge{graphp, fromp, top, weight, cutable} {} - virtual ~SplitEdge() override {} + virtual ~SplitEdge() override = default; public: // Iterator for graph functions @@ -189,7 +189,7 @@ class SplitPostEdge : public SplitEdge { public: SplitPostEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitPostEdge() override {} + virtual ~SplitPostEdge() override = default; virtual bool followScoreboard() const override { return false; } virtual string dotColor() const override { return "khaki"; } }; @@ -198,7 +198,7 @@ class SplitLVEdge : public SplitEdge { public: SplitLVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitLVEdge() override {} + virtual ~SplitLVEdge() override = default; virtual bool followScoreboard() const override { return true; } virtual string dotColor() const override { return "yellowGreen"; } }; @@ -207,7 +207,7 @@ class SplitRVEdge : public SplitEdge { public: SplitRVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitRVEdge() override {} + virtual ~SplitRVEdge() override = default; virtual bool followScoreboard() const override { return true; } virtual string dotColor() const override { return "green"; } }; @@ -216,7 +216,7 @@ struct SplitScorebdEdge : public SplitEdge { public: SplitScorebdEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitScorebdEdge() override {} + virtual ~SplitScorebdEdge() override = default; virtual bool followScoreboard() const override { return true; } virtual string dotColor() const override { return "blue"; } }; @@ -227,7 +227,7 @@ struct SplitStrictEdge : public SplitEdge { public: SplitStrictEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL, NOT_CUTABLE} {} - virtual ~SplitStrictEdge() override {} + virtual ~SplitStrictEdge() override = default; virtual bool followScoreboard() const override { return true; } virtual string dotColor() const override { return "blue"; } }; @@ -443,7 +443,7 @@ class ReorderVisitor : public SplitReorderBaseVisitor { // CONSTRUCTORS public: explicit ReorderVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ReorderVisitor() override {} + virtual ~ReorderVisitor() override = default; // METHODS protected: @@ -638,7 +638,7 @@ public: // Visit through *nodep and map each AstNodeIf within to the set of // colors it will participate in. Also find the whole set of colors. explicit IfColorVisitor(AstAlways* nodep) { iterate(nodep); } - virtual ~IfColorVisitor() override {} + virtual ~IfColorVisitor() override = default; // METHODS const ColorSet& colors() const { return m_colors; } @@ -703,7 +703,7 @@ public: UINFO(6, " splitting always " << nodep << endl); } - virtual ~EmitSplitVisitor() override {} + virtual ~EmitSplitVisitor() override = default; // METHODS void go() { @@ -804,7 +804,7 @@ public: VL_DO_DANGLING(np->deleteTree(), np); } } - virtual ~RemovePlaceholdersVisitor() override {} + virtual ~RemovePlaceholdersVisitor() override = default; virtual void visit(AstSplitPlaceholder* nodep) override { m_removeSet.insert(nodep); } virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } @@ -844,7 +844,7 @@ public: } } - virtual ~SplitVisitor() override {} + virtual ~SplitVisitor() override = default; // METHODS protected: diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index 48a1c2960..8b69134e6 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -58,7 +58,7 @@ private: public: // CONSTRUCTORS explicit SplitAsFindVisitor(AstAlways* nodep) { iterate(nodep); } - virtual ~SplitAsFindVisitor() override {} + virtual ~SplitAsFindVisitor() override = default; // METHODS AstVarScope* splitVscp() const { return m_splitVscp; } }; @@ -118,7 +118,7 @@ public: , m_modeMatch{modeMatch} { iterate(nodep); } - virtual ~SplitAsCleanVisitor() override {} + virtual ~SplitAsCleanVisitor() override = default; }; //###################################################################### diff --git a/src/V3Stats.h b/src/V3Stats.h index 5b6129e63..084eb312c 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -94,7 +94,7 @@ public: , m_stage{stage} , m_sumit{sumit} , m_perf{perf} {} - virtual ~V3Statistic() {} + virtual ~V3Statistic() = default; }; //============================================================================ diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp index 71db187a3..14ad340ea 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -186,7 +186,7 @@ public: stars(); stages(); } - ~StatsReport() {} + ~StatsReport() = default; }; StatsReport::StatColl StatsReport::s_allStats; diff --git a/src/V3String.h b/src/V3String.h index a8f8361ad..1a700d264 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -131,7 +131,7 @@ public: : VHashSha256{} { insert(data); } - ~VHashSha256() {} + ~VHashSha256() = default; // METHODS string digestBinary(); // Return digest as 32 character binary @@ -169,7 +169,7 @@ public: // CONSTRUCTORS explicit VName(const string& name) : m_name{name} {} - ~VName() {} + ~VName() = default; // METHODS void name(const string& name) { m_name = name; @@ -198,8 +198,8 @@ class VSpellCheck { Candidates m_candidates; // Strings we try to match public: // CONSTRUCTORS - explicit VSpellCheck() {} - ~VSpellCheck() {} + VSpellCheck() = default; + ~VSpellCheck() = default; // METHODS // Push a symbol table value to be considered as a candidate // The first item pushed has highest priority, all else being equal diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index d8a01fbb3..8590a57cf 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -81,7 +81,7 @@ public: m_whole.clear(); for (int i = 0; i < varp->widthWords(); i++) m_words[i].clear(); } - ~SubstVarEntry() {} + ~SubstVarEntry() = default; private: // METHODS @@ -213,7 +213,7 @@ public: UINFO(9, " SubstUseVisitor " << origStep << " " << nodep << endl); iterate(nodep); } - virtual ~SubstUseVisitor() override {} + virtual ~SubstUseVisitor() override = default; // METHODS bool ok() const { return m_ok; } }; diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 3cd98df8d..b107530f8 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -59,7 +59,7 @@ public: TspVertexTmpl(V3Graph* graphp, const T_Key& k) : V3GraphVertex{graphp} , m_key{k} {} - virtual ~TspVertexTmpl() override {} + virtual ~TspVertexTmpl() override = default; const T_Key& key() const { return m_key; } private: @@ -80,7 +80,7 @@ public: // CONSTRUCTORS TspGraphTmpl() : V3Graph{} {} - virtual ~TspGraphTmpl() override {} + virtual ~TspGraphTmpl() override = default; // METHODS void addVertex(const T_Key& key) { @@ -125,7 +125,7 @@ public: // perfectMatching() routine. public: // CONSTRUCTORS - EdgeCmp() {} + EdgeCmp() = default; // METHODS bool operator()(const V3GraphEdge* ap, const V3GraphEdge* bp) { int aCost = ap->weight(); @@ -500,7 +500,7 @@ public: : m_xpos{xpos} , m_ypos{ypos} , m_serial{++m_serialNext} {} - ~TspTestState() {} + ~TspTestState() = default; virtual int cost(const TspStateBase* otherp) const override { return cost(dynamic_cast(otherp)); } diff --git a/src/V3Table.cpp b/src/V3Table.cpp index dcec7c663..6918493e1 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -59,7 +59,7 @@ public: // CONSTRUCTORS explicit TableSimulateVisitor(TableVisitor* cbthis) : m_cbthis{cbthis} {} - virtual ~TableSimulateVisitor() override {} + virtual ~TableSimulateVisitor() override = default; }; //###################################################################### diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 9d210679e..574117607 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -45,7 +45,7 @@ class TaskBaseVertex : public V3GraphVertex { public: explicit TaskBaseVertex(V3Graph* graphp) : V3GraphVertex{graphp} {} - virtual ~TaskBaseVertex() override {} + virtual ~TaskBaseVertex() override = default; bool pure() const { return m_impurep == nullptr; } AstNode* impureNode() const { return m_impurep; } void impure(AstNode* nodep) { m_impurep = nodep; } @@ -62,7 +62,7 @@ public: TaskFTaskVertex(V3Graph* graphp, AstNodeFTask* nodep) : TaskBaseVertex{graphp} , m_nodep{nodep} {} - virtual ~TaskFTaskVertex() override {} + virtual ~TaskFTaskVertex() override = default; AstNodeFTask* nodep() const { return m_nodep; } virtual string name() const override { return nodep()->name(); } virtual string dotColor() const override { return pure() ? "black" : "red"; } @@ -76,7 +76,7 @@ class TaskCodeVertex : public TaskBaseVertex { public: explicit TaskCodeVertex(V3Graph* graphp) : TaskBaseVertex{graphp} {} - virtual ~TaskCodeVertex() override {} + virtual ~TaskCodeVertex() override = default; virtual string name() const override { return "*CODE*"; } virtual string dotColor() const override { return "green"; } }; @@ -85,7 +85,7 @@ class TaskEdge : public V3GraphEdge { public: TaskEdge(V3Graph* graphp, TaskBaseVertex* fromp, TaskBaseVertex* top) : V3GraphEdge{graphp, fromp, top, 1, false} {} - virtual ~TaskEdge() override {} + virtual ~TaskEdge() override = default; virtual string dotLabel() const override { return "w" + cvtToStr(weight()); } }; @@ -281,7 +281,7 @@ public: m_callGraph.removeRedundantEdgesSum(&TaskEdge::followAlwaysTrue); m_callGraph.dumpDotFilePrefixed("task_call"); } - virtual ~TaskStateVisitor() override {} + virtual ~TaskStateVisitor() override = default; VL_UNCOPYABLE(TaskStateVisitor); }; @@ -317,7 +317,7 @@ public: explicit TaskRelinkVisitor(AstBegin* nodep) { // Passed temporary tree iterate(nodep); } - virtual ~TaskRelinkVisitor() override {} + virtual ~TaskRelinkVisitor() override = default; }; //###################################################################### @@ -1378,7 +1378,7 @@ public: : m_statep{statep} { iterate(nodep); } - virtual ~TaskVisitor() override {} + virtual ~TaskVisitor() override = default; }; //###################################################################### diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 28712534e..a1598bb70 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -71,7 +71,7 @@ public: m_activityCode = code; m_slow = false; } - virtual ~TraceActivityVertex() override {} + virtual ~TraceActivityVertex() override = default; // ACCESSORS AstNode* insertp() const { if (!m_insertp) v3fatalSrc("Null insertp; probably called on a special always/slow."); @@ -102,7 +102,7 @@ public: TraceCFuncVertex(V3Graph* graphp, AstCFunc* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TraceCFuncVertex() override {} + virtual ~TraceCFuncVertex() override = default; // ACCESSORS AstCFunc* nodep() const { return m_nodep; } virtual string name() const override { return nodep()->name(); } @@ -119,7 +119,7 @@ public: TraceTraceVertex(V3Graph* graphp, AstTraceDecl* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TraceTraceVertex() override {} + virtual ~TraceTraceVertex() override = default; // ACCESSORS AstTraceDecl* nodep() const { return m_nodep; } virtual string name() const override { return nodep()->name(); } @@ -139,7 +139,7 @@ public: TraceVarVertex(V3Graph* graphp, AstVarScope* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TraceVarVertex() override {} + virtual ~TraceVarVertex() override = default; // ACCESSORS AstVarScope* nodep() const { return m_nodep; } virtual string name() const override { return nodep()->name(); } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 922fac45b..7b1fa24d2 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -87,7 +87,7 @@ public: TristateVertex(V3Graph* graphp, AstNode* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TristateVertex() override {} + virtual ~TristateVertex() override = default; // ACCESSORS AstNode* nodep() const { return m_nodep; } AstVar* varp() const { return VN_CAST(nodep(), Var); } @@ -307,7 +307,7 @@ public: , m_lvalue{lvalue} { iterate(nodep); } - virtual ~TristatePinVisitor() override {} + virtual ~TristatePinVisitor() override = default; }; //###################################################################### diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index fdf90654c..1ff124aee 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -57,7 +57,7 @@ public: m_bitFlags.resize(varp->width() * FLAGS_PER_BIT); for (int i = 0; i < varp->width() * FLAGS_PER_BIT; i++) m_bitFlags[i] = false; } - ~UndrivenVarEntry() {} + ~UndrivenVarEntry() = default; private: // METHODS diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 7afd7a905..5a01d586f 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -179,7 +179,7 @@ class WidthClearVisitor { public: // CONSTRUCTORS explicit WidthClearVisitor(AstNetlist* nodep) { clearWidthRecurse(nodep); } - virtual ~WidthClearVisitor() {} + virtual ~WidthClearVisitor() = default; }; //###################################################################### @@ -5909,7 +5909,7 @@ public: AstNode* mainAcceptEdit(AstNode* nodep) { return userIterateSubtreeReturnEdits(nodep, WidthVP(SELF, BOTH).p()); } - virtual ~WidthVisitor() override {} + virtual ~WidthVisitor() override = default; }; //###################################################################### diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index ff6e3c03a..047dec26e 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -55,8 +55,8 @@ private: public: // CONSTRUCTORS - WidthRemoveVisitor() {} - virtual ~WidthRemoveVisitor() override {} + WidthRemoveVisitor() = default; + virtual ~WidthRemoveVisitor() override = default; AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } }; @@ -171,7 +171,7 @@ public: // Don't want to repairCache, as all needed nodes have been added back in // a repair would prevent dead nodes from being detected } - virtual ~WidthCommitVisitor() override {} + virtual ~WidthCommitVisitor() override = default; }; //###################################################################### diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index c3232066d..71d805d20 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -67,7 +67,7 @@ private: : m_errp{errp} , m_dtypep{dtypep} , m_fromRange{fromRange} {} - ~FromData() {} + ~FromData() = default; }; FromData fromDataForArray(AstNode* nodep, AstNode* basefromp) { // What is the data type and information for this SEL-ish's from()? @@ -579,9 +579,9 @@ private: public: // CONSTRUCTORS - WidthSelVisitor() {} + WidthSelVisitor() = default; + virtual ~WidthSelVisitor() override = default; AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } - virtual ~WidthSelVisitor() override {} }; //###################################################################### diff --git a/src/VlcOptions.h b/src/VlcOptions.h index 423bfd1eb..0efd39e0f 100644 --- a/src/VlcOptions.h +++ b/src/VlcOptions.h @@ -51,8 +51,8 @@ private: public: // CONSTRUCTORS - VlcOptions() {} - ~VlcOptions() {} + VlcOptions() = default; + ~VlcOptions() = default; // METHODS void parseOptsList(int argc, char** argv); diff --git a/src/VlcPoint.h b/src/VlcPoint.h index 208dc5c56..ff88f00e0 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -42,7 +42,7 @@ public: VlcPoint(const string& name, vluint64_t pointNum) : m_name{name} , m_pointNum{pointNum} {} - ~VlcPoint() {} + ~VlcPoint() = default; // ACCESSORS const string& name() const { return m_name; } vluint64_t pointNum() const { return m_pointNum; } @@ -106,8 +106,8 @@ public: ByName::iterator end() { return m_nameMap.end(); } // CONSTRUCTORS - VlcPoints() {} - ~VlcPoints() {} + VlcPoints() = default; + ~VlcPoints() = default; // METHODS void dump() { diff --git a/src/VlcSource.h b/src/VlcSource.h index 06d1cd847..adebdde3a 100644 --- a/src/VlcSource.h +++ b/src/VlcSource.h @@ -39,7 +39,7 @@ public: VlcSourceCount(int lineno, int column) : m_lineno{lineno} , m_column{column} {} - ~VlcSourceCount() {} + ~VlcSourceCount() = default; // ACCESSORS int lineno() const { return m_lineno; } @@ -73,7 +73,7 @@ public: // CONSTRUCTORS explicit VlcSource(const string& name) : m_name{name} {} - ~VlcSource() {} + ~VlcSource() = default; // ACCESSORS const string& name() const { return m_name; } @@ -114,8 +114,8 @@ public: NameMap::iterator end() { return m_sources.end(); } // CONSTRUCTORS - VlcSources() {} - ~VlcSources() {} + VlcSources() = default; + ~VlcSources() = default; // METHODS VlcSource& findNewSource(const string& name) { diff --git a/src/VlcTest.h b/src/VlcTest.h index d1489e661..c95e351d7 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -46,7 +46,7 @@ public: : m_name{name} , m_computrons{comp} , m_testrun{testrun} {} - ~VlcTest() {} + ~VlcTest() = default; // ACCESSORS const string& name() const { return m_name; } @@ -100,7 +100,7 @@ public: ByName::iterator end() { return m_tests.end(); } // CONSTRUCTORS - VlcTests() {} + VlcTests() = default; ~VlcTests() { for (auto it = begin(); it != end(); ++it) { VL_DO_CLEAR(delete *it, *it = nullptr); } } diff --git a/src/VlcTop.h b/src/VlcTop.h index f54725fcf..b00edd110 100644 --- a/src/VlcTop.h +++ b/src/VlcTop.h @@ -45,8 +45,8 @@ private: public: // CONSTRUCTORS - VlcTop() {} - ~VlcTop() {} + VlcTop() = default; + ~VlcTop() = default; // ACCESSORS VlcTests& tests() { return m_tests; } From 0e1e380a55916b96bb7798f211452b568eae1690 Mon Sep 17 00:00:00 2001 From: Marlon James Date: Mon, 16 Nov 2020 18:00:09 -0800 Subject: [PATCH 12/91] Fix test for callCbs() so it can fail (#2613) --- test_regress/t/t_vpi_cbs_called.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/test_regress/t/t_vpi_cbs_called.cpp b/test_regress/t/t_vpi_cbs_called.cpp index c63b95b7a..c5ac031b6 100644 --- a/test_regress/t/t_vpi_cbs_called.cpp +++ b/test_regress/t/t_vpi_cbs_called.cpp @@ -45,6 +45,7 @@ std::vector::const_iterator state_iter; vpiHandle vh_test_cb = 0; unsigned int main_time = 0; +bool got_error = false; #ifdef TEST_VERBOSE bool verbose = true; @@ -55,6 +56,7 @@ bool verbose = false; #define CHECK_RESULT_NZ(got) \ if (!(got)) { \ printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", __FILE__, __LINE__); \ + got_error = true; \ return __LINE__; \ } @@ -63,6 +65,7 @@ bool verbose = false; if ((got) != (exp)) { \ std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << ": GOT = " << (got) \ << " EXP = " << (exp) << std::endl; \ + got_error = true; \ return __LINE__; \ } @@ -188,6 +191,7 @@ static int test_callbacks(p_cb_data cb_data) { } int ret = register_cb(next_state); + if (ret) { return ret; } // Update iterators for next loop ++state_iter; @@ -218,7 +222,7 @@ static int test_callbacks(p_cb_data cb_data) { return ret; } -void register_test_callback() { +static int register_test_callback() { t_cb_data cb_data; bzero(&cb_data, sizeof(cb_data)); s_vpi_time t1; @@ -231,10 +235,13 @@ void register_test_callback() { t1.low = 1; cb_data.time = &t1; cb_data.cb_rtn = test_callbacks; - vpi_register_cb(&cb_data); + vh_test_cb = vpi_register_cb(&cb_data); + CHECK_RESULT_NZ(vh_test_cb); cb_iter = cbs_to_test.cbegin(); state_iter = cb_states.cbegin(); + + return 0; } double sc_time_stamp() { return main_time; } @@ -279,10 +286,14 @@ int main(int argc, char** argv, char** env) { VerilatedVpi::callTimedCbs(); main_time = VerilatedVpi::cbNextDeadline(); - if (main_time == -1) { + if (main_time == -1 && !Verilated::gotFinish()) { if (verbose) { VL_PRINTF("-- { Sim Time %d , No more testcases } --\n", main_time); } - VL_PRINTF("*-* All Finished *-*\n"); - Verilated::gotFinish(true); + if (got_error) { + vl_stop(__FILE__, __LINE__, "TOP-cpp"); + } else { + VL_PRINTF("*-* All Finished *-*\n"); + Verilated::gotFinish(true); + } } // Count updates on rising edge, so cycle through falling edge as well From 1e7c61b23ebd1dc12d8376a734cb3802eaeb8a1b Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 16 Nov 2020 22:35:51 -0500 Subject: [PATCH 13/91] Internals: Refactor huge func in V3Param. No functional change intended. --- src/V3Param.cpp | 196 ++++++++++++++++++++++++------------------------ 1 file changed, 99 insertions(+), 97 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 219356b2f..2cb57c9f3 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -316,6 +316,25 @@ private: } return string("z") + cvtToStr(num); } + string moduleCalcName(AstNodeModule* srcModp, AstCell* cellp, const string& longname) { + string newname = longname; + if (longname.length() > 30 || srcModp->hierBlock()) { + const auto iter = m_longMap.find(longname); + if (iter != m_longMap.end()) { + newname = iter->second; + } else { + if (srcModp->hierBlock()) { + newname = parametrizedHierBlockName(srcModp, cellp->paramsp()); + } else { + newname = srcModp->name(); + // We use all upper case above, so lower here can't conflict + newname += "__pi" + cvtToStr(++m_longId); + } + m_longMap.insert(make_pair(longname, newname)); + } + } + return newname; + } AstNodeDType* arraySubDTypep(AstNodeDType* nodep) { // If an unpacked array, return the subDTypep under it if (AstUnpackArrayDType* adtypep = VN_CAST(nodep, UnpackArrayDType)) { @@ -436,6 +455,83 @@ private: hash.insert(V3Os::trueRandom(64)); } } + AstNodeModule* deepCloneModule(AstNodeModule* srcModp, AstCell* cellp, const string& newname, + const IfaceRefRefs& ifaceRefRefs) { + // Deep clone of new module + // Note all module internal variables will be re-linked to the new modules by clone + // However links outside the module (like on the upper cells) will not. + AstNodeModule* newmodp = srcModp->cloneTree(false); + newmodp->name(newname); + newmodp->user5(false); // We need to re-recurse this module once changed + newmodp->recursive(false); + newmodp->recursiveClone(false); + // Only the first generation of clone holds this property + newmodp->hierBlock(srcModp->hierBlock() && !srcModp->recursiveClone()); + cellp->recursive(false); + // Recursion may need level cleanups + if (newmodp->level() <= m_modp->level()) newmodp->level(m_modp->level() + 1); + if ((newmodp->level() - srcModp->level()) >= (v3Global.opt.moduleRecursionDepth() - 2)) { + cellp->v3error("Exceeded maximum --module-recursion-depth of " + << v3Global.opt.moduleRecursionDepth()); + } + // Keep tree sorted by level + AstNodeModule* insertp = srcModp; + while (VN_IS(insertp->nextp(), NodeModule) + && VN_CAST(insertp->nextp(), NodeModule)->level() < newmodp->level()) { + insertp = VN_CAST(insertp->nextp(), NodeModule); + } + insertp->addNextHere(newmodp); + + m_modNameMap.insert(make_pair(newmodp->name(), ModInfo(newmodp))); + auto iter = m_modNameMap.find(newname); + CloneMap* clonemapp = &(iter->second.m_cloneMap); + UINFO(4, " De-parameterize to new: " << newmodp << endl); + + // Grab all I/O so we can remap our pins later + // Note we allow multiple users of a parameterized model, + // thus we need to stash this info. + collectPins(clonemapp, newmodp); + // Relink parameter vars to the new module + relinkPins(clonemapp, cellp->paramsp()); + // Fix any interface references + for (auto it = ifaceRefRefs.cbegin(); it != ifaceRefRefs.cend(); ++it) { + AstIfaceRefDType* portIrefp = it->first; + AstIfaceRefDType* pinIrefp = it->second; + AstIfaceRefDType* cloneIrefp = portIrefp->clonep(); + UINFO(8, " IfaceOld " << portIrefp << endl); + UINFO(8, " IfaceTo " << pinIrefp << endl); + UASSERT_OBJ(cloneIrefp, portIrefp, "parameter clone didn't hit AstIfaceRefDType"); + UINFO(8, " IfaceClo " << cloneIrefp << endl); + cloneIrefp->ifacep(pinIrefp->ifaceViaCellp()); + UINFO(8, " IfaceNew " << cloneIrefp << endl); + } + // Assign parameters to the constants specified + // DOES clone() so must be finished with module clonep() before here + for (AstPin* pinp = cellp->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (pinp->exprp()) { + if (newmodp->hierBlock()) checkSupportedParam(newmodp, pinp); + if (AstVar* modvarp = pinp->modVarp()) { + AstNode* newp = pinp->exprp(); // Const or InitArray + // Remove any existing parameter + if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree(); + // Set this parameter to value requested by cell + modvarp->valuep(newp->cloneTree(false)); + modvarp->overriddenParam(true); + } else if (AstParamTypeDType* modptp = pinp->modPTypep()) { + AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); + UASSERT_OBJ(dtypep, pinp, "unlinked param dtype"); + if (modptp->childDTypep()) { + pushDeletep(modptp->childDTypep()->unlinkFrBack()); + } + // Set this parameter to value requested by cell + modptp->childDTypep(dtypep->cloneTree(false)); + // Later V3LinkDot will convert the ParamDType to a Typedef + // Not done here as may be localparams, etc, that also need conversion + } + } + } + return newmodp; + } void visitCell(AstCell* nodep, const string& hierName); void visitModules() { // Loop on all modules left to process @@ -887,7 +983,6 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) { portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType); } - AstIfaceRefDType* pinIrefp = nullptr; AstNode* exprp = pinp->exprp(); AstVar* varp @@ -954,116 +1049,23 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { // We don't do this always, as it aids debugability to have intuitive naming. // TODO can use new V3Name hash replacement instead of this // Shorter name is convenient for hierarchical block - string newname = longname; - if (longname.length() > 30 || srcModp->hierBlock()) { - const auto iter = m_longMap.find(longname); - if (iter != m_longMap.end()) { - newname = iter->second; - } else { - if (srcModp->hierBlock()) { - newname = parametrizedHierBlockName(srcModp, nodep->paramsp()); - } else { - newname = srcModp->name(); - // We use all upper case above, so lower here can't conflict - newname += "__pi" + cvtToStr(++m_longId); - } - m_longMap.insert(make_pair(longname, newname)); - } - } + string newname = moduleCalcName(srcModp, nodep, longname); UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); - // // Already made this flavor? AstNodeModule* cellmodp = nullptr; auto iter = m_modNameMap.find(newname); if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp; if (!cellmodp) { - // Deep clone of new module - // Note all module internal variables will be re-linked to the new modules by clone - // However links outside the module (like on the upper cells) will not. - cellmodp = srcModp->cloneTree(false); - cellmodp->name(newname); - cellmodp->user5(false); // We need to re-recurse this module once changed - cellmodp->recursive(false); - cellmodp->recursiveClone(false); - // Only the first generation of clone holds this property - cellmodp->hierBlock(srcModp->hierBlock() && !srcModp->recursiveClone()); - nodep->recursive(false); - // Recursion may need level cleanups - if (cellmodp->level() <= m_modp->level()) cellmodp->level(m_modp->level() + 1); - if ((cellmodp->level() - srcModp->level()) - >= (v3Global.opt.moduleRecursionDepth() - 2)) { - nodep->v3error("Exceeded maximum --module-recursion-depth of " - << v3Global.opt.moduleRecursionDepth()); - } - // Keep tree sorted by level - AstNodeModule* insertp = srcModp; - while (VN_IS(insertp->nextp(), NodeModule) - && VN_CAST(insertp->nextp(), NodeModule)->level() < cellmodp->level()) { - insertp = VN_CAST(insertp->nextp(), NodeModule); - } - insertp->addNextHere(cellmodp); - - m_modNameMap.insert(make_pair(cellmodp->name(), ModInfo(cellmodp))); + cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs); iter = m_modNameMap.find(newname); - CloneMap* clonemapp = &(iter->second.m_cloneMap); - UINFO(4, " De-parameterize to new: " << cellmodp << endl); - - // Grab all I/O so we can remap our pins later - // Note we allow multiple users of a parameterized model, - // thus we need to stash this info. - collectPins(clonemapp, cellmodp); - // Relink parameter vars to the new module - relinkPins(clonemapp, nodep->paramsp()); - - // Fix any interface references - for (IfaceRefRefs::iterator it = ifaceRefRefs.begin(); it != ifaceRefRefs.end(); - ++it) { - AstIfaceRefDType* portIrefp = it->first; - AstIfaceRefDType* pinIrefp = it->second; - AstIfaceRefDType* cloneIrefp = portIrefp->clonep(); - UINFO(8, " IfaceOld " << portIrefp << endl); - UINFO(8, " IfaceTo " << pinIrefp << endl); - UASSERT_OBJ(cloneIrefp, portIrefp, - "parameter clone didn't hit AstIfaceRefDType"); - UINFO(8, " IfaceClo " << cloneIrefp << endl); - cloneIrefp->ifacep(pinIrefp->ifaceViaCellp()); - UINFO(8, " IfaceNew " << cloneIrefp << endl); - } - // Assign parameters to the constants specified - // DOES clone() so must be finished with module clonep() before here - for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - if (pinp->exprp()) { - if (cellmodp->hierBlock()) checkSupportedParam(cellmodp, pinp); - if (AstVar* modvarp = pinp->modVarp()) { - AstNode* newp = pinp->exprp(); // Const or InitArray - // Remove any existing parameter - if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree(); - // Set this parameter to value requested by cell - modvarp->valuep(newp->cloneTree(false)); - modvarp->overriddenParam(true); - } else if (AstParamTypeDType* modptp = pinp->modPTypep()) { - AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); - UASSERT_OBJ(dtypep, pinp, "unlinked param dtype"); - if (modptp->childDTypep()) { - pushDeletep(modptp->childDTypep()->unlinkFrBack()); - } - // Set this parameter to value requested by cell - modptp->childDTypep(dtypep->cloneTree(false)); - // Later V3LinkDot will convert the ParamDType to a Typedef - // Not done here as may be localparams, etc, that also need conversion - } - } - } - + UASSERT(iter != m_modNameMap.end(), "should find just-made module"); } else { UINFO(4, " De-parameterize to old: " << cellmodp << endl); } - // Have child use this module instead. nodep->modp(cellmodp); nodep->modName(newname); - // We need to relink the pins to the new module CloneMap* clonemapp = &(iter->second.m_cloneMap); relinkPins(clonemapp, nodep->pinsp()); From 5b3717b369355fa931a962e58fdbfae08f0ac969 Mon Sep 17 00:00:00 2001 From: Tomasz Gorochowik Date: Tue, 17 Nov 2020 12:37:55 +0100 Subject: [PATCH 14/91] Tests: Memory clean up in tests (#2645) This patch normalizes what the tests do before exiting. After this change each test should call final on the top module and explicitly free the top module object before exiting. --- test_regress/t/t_clk_2in.cpp | 3 +++ test_regress/t/t_dpi_accessors.cpp | 1 + test_regress/t/t_dpi_export_context2_bad.cpp | 1 + test_regress/t/t_dpi_export_context_bad.cpp | 3 +++ test_regress/t/t_dpi_vams.cpp | 3 +++ test_regress/t/t_enum_public.cpp | 3 +++ test_regress/t/t_flag_fi.cpp | 1 + test_regress/t/t_func_rand.cpp | 2 ++ test_regress/t/t_math_imm2.cpp | 3 +++ test_regress/t/t_mem_multi_io2.cpp | 3 +++ test_regress/t/t_mem_multi_io3.cpp | 3 +++ test_regress/t/t_mem_slot.cpp | 3 +++ test_regress/t/t_multitop_sig.cpp | 4 ++++ test_regress/t/t_order_multidriven.cpp | 4 ++++ test_regress/t/t_order_quad.cpp | 3 ++- test_regress/t/t_param_public.cpp | 3 +++ test_regress/t/t_sc_names.cpp | 1 + test_regress/t/t_scope_map.cpp | 2 ++ test_regress/t/t_timescale.cpp | 1 + test_regress/t/t_timescale_parse.cpp | 1 + test_regress/t/t_trace_cat.cpp | 1 + test_regress/t/t_trace_public_func.cpp | 1 + test_regress/t/t_trace_public_sig.cpp | 1 + test_regress/t/t_tri_gate.cpp | 1 + test_regress/t/t_tri_inout.cpp | 1 + test_regress/t/t_tri_inz.cpp | 1 + test_regress/t/t_tri_pullup.cpp | 1 + test_regress/t/t_tri_select.cpp | 1 + test_regress/t/t_var_pinsizes.cpp | 2 ++ test_regress/t/t_vpi_sc.cpp | 1 + test_regress/t/t_x_assign.cpp | 1 + 31 files changed, 59 insertions(+), 1 deletion(-) diff --git a/test_regress/t/t_clk_2in.cpp b/test_regress/t/t_clk_2in.cpp index ba601f846..fc5a0233f 100644 --- a/test_regress/t/t_clk_2in.cpp +++ b/test_regress/t/t_clk_2in.cpp @@ -50,4 +50,7 @@ int main(int argc, char* argv[]) { } topp->check = 1; clockit(0, 0); + + topp->final(); + VL_DO_DANGLING(delete topp, topp); } diff --git a/test_regress/t/t_dpi_accessors.cpp b/test_regress/t/t_dpi_accessors.cpp index e3f227ab1..c5d7152d9 100644 --- a/test_regress/t/t_dpi_accessors.cpp +++ b/test_regress/t/t_dpi_accessors.cpp @@ -673,6 +673,7 @@ int main() { // Tidy up dut->final(); + VL_DO_DANGLING(delete dut, dut); cout << "*-* All Finished *-*" << endl; } diff --git a/test_regress/t/t_dpi_export_context2_bad.cpp b/test_regress/t/t_dpi_export_context2_bad.cpp index 77ce4668c..ec2b10216 100644 --- a/test_regress/t/t_dpi_export_context2_bad.cpp +++ b/test_regress/t/t_dpi_export_context2_bad.cpp @@ -27,6 +27,7 @@ int main(int argc, char* argv[]) { Verilated::debug(0); topp->eval(); + VL_DO_DANGLING(delete topp, topp); return 1; } int dpii_task() { diff --git a/test_regress/t/t_dpi_export_context_bad.cpp b/test_regress/t/t_dpi_export_context_bad.cpp index a42ceff51..407c8b5b4 100644 --- a/test_regress/t/t_dpi_export_context_bad.cpp +++ b/test_regress/t/t_dpi_export_context_bad.cpp @@ -44,5 +44,8 @@ int main(int argc, char* argv[]) { topp->eval(); dpix_task(); // Missing svSetScope + + topp->final(); + VL_DO_DANGLING(delete topp, topp); return 1; } diff --git a/test_regress/t/t_dpi_vams.cpp b/test_regress/t/t_dpi_vams.cpp index 4722f8636..264eb18cd 100644 --- a/test_regress/t/t_dpi_vams.cpp +++ b/test_regress/t/t_dpi_vams.cpp @@ -51,5 +51,8 @@ int main(int argc, char* argv[]) { } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results\n"); } + + topp->final(); + VL_DO_DANGLING(delete topp, topp); return 0; } diff --git a/test_regress/t/t_enum_public.cpp b/test_regress/t/t_enum_public.cpp index 598275ffc..328140331 100644 --- a/test_regress/t/t_enum_public.cpp +++ b/test_regress/t/t_enum_public.cpp @@ -24,4 +24,7 @@ int main(int argc, char* argv[]) { for (int i = 0; i < 10; i++) { // topp->eval(); } + + topp->final(); + VL_DO_DANGLING(delete topp, topp); } diff --git a/test_regress/t/t_flag_fi.cpp b/test_regress/t/t_flag_fi.cpp index 4c0a89ed1..c977decf8 100644 --- a/test_regress/t/t_flag_fi.cpp +++ b/test_regress/t/t_flag_fi.cpp @@ -29,6 +29,7 @@ int main(int argc, char* argv[]) { if (!gotit) { vl_fatal(__FILE__, __LINE__, "dut", "Never got call to myfunction"); } topp->final(); + VL_DO_DANGLING(delete topp, topp); return 0; } diff --git a/test_regress/t/t_func_rand.cpp b/test_regress/t/t_func_rand.cpp index f69fd7243..6a93db0ff 100644 --- a/test_regress/t/t_func_rand.cpp +++ b/test_regress/t/t_func_rand.cpp @@ -24,5 +24,7 @@ int main(int argc, char* argv[]) { if (topp->Rand != 0xfeed0fad) { vl_fatal(__FILE__, __LINE__, "top", "Unexpected value for Rand output\n"); } + topp->final(); + VL_DO_DANGLING(delete topp, topp); printf("*-* All Finished *-*\n"); } diff --git a/test_regress/t/t_math_imm2.cpp b/test_regress/t/t_math_imm2.cpp index 999ef1157..163e797b7 100644 --- a/test_regress/t/t_math_imm2.cpp +++ b/test_regress/t/t_math_imm2.cpp @@ -44,6 +44,9 @@ int main(int argc, char* argv[]) { } } + sim->final(); + VL_DO_DANGLING(delete sim, sim); + if (errs) { vl_stop(__FILE__, __LINE__, "TOP-cpp"); exit(10); diff --git a/test_regress/t/t_mem_multi_io2.cpp b/test_regress/t/t_mem_multi_io2.cpp index 145b02ba3..7c18d04e3 100644 --- a/test_regress/t/t_mem_multi_io2.cpp +++ b/test_regress/t/t_mem_multi_io2.cpp @@ -78,6 +78,9 @@ int main() for (int j = 0; j < 5; j++) check("o345", READ(o345[i][j]), i * 8 + j); } + tb->final(); + VL_DO_DANGLING(delete tb, tb); + if (pass) { VL_PRINTF("*-* All Finished *-*\n"); } else { diff --git a/test_regress/t/t_mem_multi_io3.cpp b/test_regress/t/t_mem_multi_io3.cpp index 9068af3f9..9db98b288 100644 --- a/test_regress/t/t_mem_multi_io3.cpp +++ b/test_regress/t/t_mem_multi_io3.cpp @@ -20,6 +20,9 @@ int main() Verilated::debug(0); tb = new VM_PREFIX("tb"); + tb->final(); + VL_DO_DANGLING(delete tb, tb); + // Just a constructor test VL_PRINTF("*-* All Finished *-*\n"); return 0; diff --git a/test_regress/t/t_mem_slot.cpp b/test_regress/t/t_mem_slot.cpp index 86d3b984e..501c9113f 100644 --- a/test_regress/t/t_mem_slot.cpp +++ b/test_regress/t/t_mem_slot.cpp @@ -55,5 +55,8 @@ int main(int argc, char* argv[]) { for (i = 0; i < 100; i++) // StepSim(sim, random() % 3, random() % 2, random() % 2, random() % 3); + sim->final(); + VL_DO_DANGLING(delete sim, sim); + printf("*-* All Finished *-*\n"); } diff --git a/test_regress/t/t_multitop_sig.cpp b/test_regress/t/t_multitop_sig.cpp index e548d25ad..e89b40853 100644 --- a/test_regress/t/t_multitop_sig.cpp +++ b/test_regress/t/t_multitop_sig.cpp @@ -39,5 +39,9 @@ int main(int argc, char* argv[]) { CHECK_RESULT(topp->b__02Eout, 1); CHECK_RESULT(topp->uniq_out, 0); } + + topp->final(); + VL_DO_DANGLING(delete topp, topp); + printf("*-* All Finished *-*\n"); } diff --git a/test_regress/t/t_order_multidriven.cpp b/test_regress/t/t_order_multidriven.cpp index 8679cdca3..5f6003e4b 100644 --- a/test_regress/t/t_order_multidriven.cpp +++ b/test_regress/t/t_order_multidriven.cpp @@ -56,5 +56,9 @@ int main() { } vcd->close(); + + vcore->final(); + VL_DO_DANGLING(delete vcore, vcore); + printf("*-* All Finished *-*\n"); } diff --git a/test_regress/t/t_order_quad.cpp b/test_regress/t/t_order_quad.cpp index 89773b790..9f6bd98d8 100644 --- a/test_regress/t/t_order_quad.cpp +++ b/test_regress/t/t_order_quad.cpp @@ -38,12 +38,13 @@ int main(int argc, char* argv[]) { topp->eval(); check(topp->y, 0x3c00000000ULL); - topp->final(); if (!fail) { VL_PRINTF("*-* All Finished *-*\n"); topp->final(); } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results\n"); } + + VL_DO_DANGLING(delete topp, topp); return 0; } diff --git a/test_regress/t/t_param_public.cpp b/test_regress/t/t_param_public.cpp index 093d5acb6..f2e158a78 100644 --- a/test_regress/t/t_param_public.cpp +++ b/test_regress/t/t_param_public.cpp @@ -26,4 +26,7 @@ int main(int argc, char* argv[]) { for (int i = 0; i < 10; i++) { // topp->eval(); } + + topp->final(); + VL_DO_DANGLING(delete topp, topp); } diff --git a/test_regress/t/t_sc_names.cpp b/test_regress/t/t_sc_names.cpp index 163916db5..ba71d8c14 100644 --- a/test_regress/t/t_sc_names.cpp +++ b/test_regress/t/t_sc_names.cpp @@ -24,5 +24,6 @@ int sc_main(int argc, char* argv[]) { } else { vl_fatal(__FILE__, __LINE__, "tb", "Unexpected results\n"); } + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_scope_map.cpp b/test_regress/t/t_scope_map.cpp index 39d28c3d0..020bee9d4 100644 --- a/test_regress/t/t_scope_map.cpp +++ b/test_regress/t/t_scope_map.cpp @@ -161,6 +161,8 @@ int main(int argc, char** argv, char** env) { tfp->close(); top->final(); + VL_DO_DANGLING(delete top, top); + VL_PRINTF("*-* All Finished *-*\n"); return 0; diff --git a/test_regress/t/t_timescale.cpp b/test_regress/t/t_timescale.cpp index 1471cc2d3..f4a673912 100644 --- a/test_regress/t/t_timescale.cpp +++ b/test_regress/t/t_timescale.cpp @@ -50,6 +50,7 @@ int main(int argc, char** argv, char** env) { CHECK_RESULT(VL_TIME_STR_CONVERT(0), 0); top->final(); + VL_DO_DANGLING(delete top, top); printf("*-* All Finished *-*\n"); return 0; } diff --git a/test_regress/t/t_timescale_parse.cpp b/test_regress/t/t_timescale_parse.cpp index eb9fcc18a..c1464fe97 100644 --- a/test_regress/t/t_timescale_parse.cpp +++ b/test_regress/t/t_timescale_parse.cpp @@ -19,4 +19,5 @@ int main() { tb->eval(); tb->final(); + VL_DO_DANGLING(delete tb, tb); } diff --git a/test_regress/t/t_trace_cat.cpp b/test_regress/t/t_trace_cat.cpp index b4a9c6125..c0374121d 100644 --- a/test_regress/t/t_trace_cat.cpp +++ b/test_regress/t/t_trace_cat.cpp @@ -58,6 +58,7 @@ int main(int argc, char** argv, char** env) { } tfp->close(); top->final(); + VL_DO_DANGLING(delete top, top); printf("*-* All Finished *-*\n"); return 0; } diff --git a/test_regress/t/t_trace_public_func.cpp b/test_regress/t/t_trace_public_func.cpp index c43a13dbc..b77045813 100644 --- a/test_regress/t/t_trace_public_func.cpp +++ b/test_regress/t/t_trace_public_func.cpp @@ -46,6 +46,7 @@ int main(int argc, char** argv, char** env) { } tfp->close(); top->final(); + VL_DO_DANGLING(delete top, top); printf("*-* All Finished *-*\n"); return 0; } diff --git a/test_regress/t/t_trace_public_sig.cpp b/test_regress/t/t_trace_public_sig.cpp index 2c996203f..c77db8584 100644 --- a/test_regress/t/t_trace_public_sig.cpp +++ b/test_regress/t/t_trace_public_sig.cpp @@ -46,6 +46,7 @@ int main(int argc, char** argv, char** env) { } tfp->close(); top->final(); + VL_DO_DANGLING(delete top, top); printf("*-* All Finished *-*\n"); return 0; } diff --git a/test_regress/t/t_tri_gate.cpp b/test_regress/t/t_tri_gate.cpp index 6b1c881a6..89810bce7 100644 --- a/test_regress/t/t_tri_gate.cpp +++ b/test_regress/t/t_tri_gate.cpp @@ -54,5 +54,6 @@ int main() { } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from tristate test\n"); } + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_tri_inout.cpp b/test_regress/t/t_tri_inout.cpp index bd0cb1426..6156bfdbf 100644 --- a/test_regress/t/t_tri_inout.cpp +++ b/test_regress/t/t_tri_inout.cpp @@ -54,5 +54,6 @@ int main() { } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from inout test\n"); } + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_tri_inz.cpp b/test_regress/t/t_tri_inz.cpp index 0e47c3b8d..c9393b5f3 100644 --- a/test_regress/t/t_tri_inz.cpp +++ b/test_regress/t/t_tri_inz.cpp @@ -44,5 +44,6 @@ int main() { } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from t_tri_inz\n"); } + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_tri_pullup.cpp b/test_regress/t/t_tri_pullup.cpp index 7885093fd..a85093968 100644 --- a/test_regress/t/t_tri_pullup.cpp +++ b/test_regress/t/t_tri_pullup.cpp @@ -63,5 +63,6 @@ int main() { } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from pullup test\n"); } + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_tri_select.cpp b/test_regress/t/t_tri_select.cpp index d034b85f9..b2efad8fa 100644 --- a/test_regress/t/t_tri_select.cpp +++ b/test_regress/t/t_tri_select.cpp @@ -66,5 +66,6 @@ int main() { } else { vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from t_tri_select\n"); } + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_var_pinsizes.cpp b/test_regress/t/t_var_pinsizes.cpp index 32624893c..a5c75e363 100644 --- a/test_regress/t/t_var_pinsizes.cpp +++ b/test_regress/t/t_var_pinsizes.cpp @@ -15,6 +15,7 @@ int main() { VL_PRINTF("*-* All Finished *-*\n"); tb->final(); + VL_DO_DANGLING(delete tb, tb); return 0; } @@ -23,5 +24,6 @@ int sc_main(int argc, char* argv[]) { VL_PRINTF("*-* All Finished *-*\n"); tb->final(); + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_vpi_sc.cpp b/test_regress/t/t_vpi_sc.cpp index 6cdf5adf9..85c7b9078 100644 --- a/test_regress/t/t_vpi_sc.cpp +++ b/test_regress/t/t_vpi_sc.cpp @@ -12,5 +12,6 @@ int sc_main(int argc, char* argv[]) { VL_PRINTF("*-* All Finished *-*\n"); tb->final(); + VL_DO_DANGLING(delete tb, tb); return 0; } diff --git a/test_regress/t/t_x_assign.cpp b/test_regress/t/t_x_assign.cpp index 760b6f7ec..502301c7c 100644 --- a/test_regress/t/t_x_assign.cpp +++ b/test_regress/t/t_x_assign.cpp @@ -48,6 +48,7 @@ int main(int argc, const char** argv) { exit(1); } + VL_DO_DANGLING(delete top, top); std::cout << "*-* All Finished *-*" << std::endl; return 0; } From 899e7bacb2749676ccf53ea8ae851ae7412c07b9 Mon Sep 17 00:00:00 2001 From: Marlon James Date: Tue, 17 Nov 2020 14:19:51 -0800 Subject: [PATCH 15/91] Fix VPI callback list iteration (#2644) The end iterator always points to an element past the end of the list. When new elements are added to the back of the list, they are inserted before the end iterator. Instead, track the last element in the list at the start of processing and stop after it's been processed. --- include/verilated_vpi.cpp | 18 ++- test_regress/t/t_vpi_cb_iter.cpp | 202 +++++++++++++++++++++++++++++++ test_regress/t/t_vpi_cb_iter.pl | 24 ++++ test_regress/t/t_vpi_cb_iter.v | 29 +++++ 4 files changed, 269 insertions(+), 4 deletions(-) create mode 100644 test_regress/t/t_vpi_cb_iter.cpp create mode 100755 test_regress/t/t_vpi_cb_iter.pl create mode 100644 test_regress/t/t_vpi_cb_iter.v diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 43e6feecd..e9a64241a 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -475,16 +475,21 @@ public: static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE { VpioCbList& cbObjList = s_s.m_cbObjLists[reason]; bool called = false; - const auto end = cbObjList.end(); // prevent looping over newly added elements - for (auto it = cbObjList.begin(); it != end;) { + if (cbObjList.empty()) return called; + const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements + for (auto it = cbObjList.begin(); true;) { + // cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist + bool was_last = it == last; if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup it = cbObjList.erase(it); + if (was_last) break; continue; } VerilatedVpioCb* vop = *it++; VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback %d %p\n", reason, vop);); (vop->cb_rtnp())(vop->cb_datap()); called = true; + if (was_last) break; } return called; } @@ -494,10 +499,14 @@ public: bool called = false; typedef std::set VpioVarSet; VpioVarSet update; // set of objects to update after callbacks - const auto end = cbObjList.end(); // prevent looping over newly added elements - for (auto it = cbObjList.begin(); it != end;) { + if (cbObjList.empty()) return called; + const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements + for (auto it = cbObjList.begin(); true;) { + // cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist + bool was_last = it == last; if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup it = cbObjList.erase(it); + if (was_last) break; continue; } VerilatedVpioCb* vop = *it++; @@ -516,6 +525,7 @@ public: called = true; } } + if (was_last) break; } for (const auto& ip : update) { memcpy(ip->prevDatap(), ip->varDatap(), ip->entSize()); } return called; diff --git a/test_regress/t/t_vpi_cb_iter.cpp b/test_regress/t/t_vpi_cb_iter.cpp new file mode 100644 index 000000000..f9dd322d4 --- /dev/null +++ b/test_regress/t/t_vpi_cb_iter.cpp @@ -0,0 +1,202 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2020 by Wilson Snyder and Marlon James. 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 +// +//************************************************************************* + +#include "Vt_vpi_cb_iter.h" +#include "verilated.h" +#include "verilated_vpi.h" + +#include +#include +#include +#include +#include + +#include "TestSimulator.h" +#include "TestVpi.h" + +#include "vpi_user.h" + +bool got_error = false; + +vpiHandle vh_value_cb = 0; +vpiHandle vh_rw_cb = 0; + +unsigned int last_value_cb_time = 0; +unsigned int last_rw_cb_time = 0; + +unsigned int main_time = 0; + +#ifdef TEST_VERBOSE +bool verbose = true; +#else +bool verbose = false; +#endif + +#define CHECK_RESULT_NZ(got) \ + if (!(got)) { \ + printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", __FILE__, __LINE__); \ + got_error = true; \ + } + +// Use cout to avoid issues with %d/%lx etc +#define CHECK_RESULT_NE(got, exp) \ + if ((got) == (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << ": GOT = " << (got) \ + << " EXP = !" << (exp) << std::endl; \ + got_error = true; \ + } + +// Use cout to avoid issues with %d/%lx etc +#define CHECK_RESULT(got, exp) \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << ": GOT = " << (got) \ + << " EXP = " << (exp) << std::endl; \ + got_error = true; \ + } +static void reregister_value_cb(); +static void reregister_rw_cb(); + +static int the_value_callback(p_cb_data cb_data) { + reregister_value_cb(); + return 0; +} + +static int the_rw_callback(p_cb_data cb_data) { + reregister_rw_cb(); + return 0; +} + +static void reregister_value_cb() { + if (vh_value_cb) { + if (verbose) { vpi_printf(const_cast("- Removing cbValueChange callback\n")); } + int ret = vpi_remove_cb(vh_value_cb); + CHECK_RESULT(ret, 1); + + if (verbose) { + vpi_printf(const_cast("- last_value_cb_time %d , main_time %d\n"), + last_value_cb_time, main_time); + } + CHECK_RESULT_NE(main_time, last_value_cb_time); + last_value_cb_time = main_time; + } + if (verbose) { vpi_printf(const_cast("- Registering cbValueChange callback\n")); } + t_cb_data cb_data_testcase; + bzero(&cb_data_testcase, sizeof(cb_data_testcase)); + cb_data_testcase.cb_rtn = the_value_callback; + cb_data_testcase.reason = cbValueChange; + + vpiHandle vh1 = VPI_HANDLE("count"); + CHECK_RESULT_NZ(vh1); + + s_vpi_value v; + v.format = vpiSuppressVal; + + cb_data_testcase.obj = vh1; + cb_data_testcase.value = &v; + + vh_value_cb = vpi_register_cb(&cb_data_testcase); + CHECK_RESULT_NZ(vh_value_cb); +} + +static void reregister_rw_cb() { + if (vh_rw_cb) { + if (verbose) { vpi_printf(const_cast("- Removing cbReadWriteSynch callback\n")); } + int ret = vpi_remove_cb(vh_rw_cb); + CHECK_RESULT(ret, 1); + + if (verbose) { + vpi_printf(const_cast("- last_rw_cb_time %d , main_time %d\n"), last_rw_cb_time, + main_time); + } + CHECK_RESULT_NE(main_time, last_rw_cb_time); + last_rw_cb_time = main_time; + } + if (verbose) { vpi_printf(const_cast("- Registering cbReadWriteSynch callback\n")); } + t_cb_data cb_data_testcase; + bzero(&cb_data_testcase, sizeof(cb_data_testcase)); + cb_data_testcase.cb_rtn = the_rw_callback; + cb_data_testcase.reason = cbReadWriteSynch; + + vh_rw_cb = vpi_register_cb(&cb_data_testcase); + CHECK_RESULT_NZ(vh_rw_cb); +} + +static int the_filler_callback(p_cb_data cb_data) { return 0; } + +static void register_filler_cb() { + if (verbose) { + vpi_printf(const_cast("- Registering filler cbReadWriteSynch callback\n")); + } + t_cb_data cb_data_1; + bzero(&cb_data_1, sizeof(cb_data_1)); + cb_data_1.cb_rtn = the_filler_callback; + cb_data_1.reason = cbReadWriteSynch; + + vpiHandle vh1 = vpi_register_cb(&cb_data_1); + CHECK_RESULT_NZ(vh1); + + if (verbose) { + vpi_printf(const_cast("- Registering filler cbValueChange callback\n")); + } + t_cb_data cb_data_2; + bzero(&cb_data_2, sizeof(cb_data_2)); + cb_data_2.cb_rtn = the_filler_callback; + cb_data_2.reason = cbValueChange; + + vpiHandle vh2 = VPI_HANDLE("count"); + CHECK_RESULT_NZ(vh2); + + s_vpi_value v; + v.format = vpiSuppressVal; + + cb_data_2.obj = vh2; + cb_data_2.value = &v; + + vpiHandle vh3 = vpi_register_cb(&cb_data_2); + CHECK_RESULT_NZ(vh3); +} + +double sc_time_stamp() { return main_time; } + +int main(int argc, char** argv, char** env) { + double sim_time = 100; + Verilated::commandArgs(argc, argv); + Verilated::debug(0); + + VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out + + reregister_value_cb(); + CHECK_RESULT_NZ(vh_value_cb); + reregister_rw_cb(); + CHECK_RESULT_NZ(vh_rw_cb); + register_filler_cb(); + + topp->eval(); + topp->clk = 0; + + while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { + main_time += 1; + if (verbose) { VL_PRINTF("Sim Time %d got_error %d\n", main_time, got_error); } + topp->clk = !topp->clk; + topp->eval(); + VerilatedVpi::callValueCbs(); + VerilatedVpi::callCbs(cbReadWriteSynch); + if (got_error) { vl_stop(__FILE__, __LINE__, "TOP-cpp"); } + } + + if (!Verilated::gotFinish()) { + vl_fatal(__FILE__, __LINE__, "main", "%Error: Timeout; never got a $finish"); + } + topp->final(); + + VL_DO_DANGLING(delete topp, topp); + exit(0L); +} diff --git a/test_regress/t/t_vpi_cb_iter.pl b/test_regress/t/t_vpi_cb_iter.pl new file mode 100755 index 000000000..0d8f23641 --- /dev/null +++ b/test_regress/t/t_vpi_cb_iter.pl @@ -0,0 +1,24 @@ +#!/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 and Marlon James. 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(vlt => 1); + +compile( + make_top_shell => 0, + make_main => 0, + verilator_flags2 => ["--exe --vpi $Self->{t_dir}/$Self->{name}.cpp"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_vpi_cb_iter.v b/test_regress/t/t_vpi_cb_iter.v new file mode 100644 index 000000000..9c4d0fa91 --- /dev/null +++ b/test_regress/t/t_vpi_cb_iter.v @@ -0,0 +1,29 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 Wilson Snyder and Marlon James. +// SPDX-License-Identifier: CC0-1.0 + + +module t (/*AUTOARG*/ + // Inputs + input clk + ); + + reg [31:0] count /*verilator public_flat_rd */; + + // Test loop + initial begin + count = 0; + end + + always @(posedge clk) begin + count <= count + 2; + + if (count == 10) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule : t From 2f718b9ea04d813dd17ebc23d6a11207f7d49082 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 17 Nov 2020 21:10:29 -0500 Subject: [PATCH 16/91] Show IEEE reference in array port message, plus internal cleanups. --- src/V3Param.cpp | 6 +++--- src/V3Width.cpp | 17 +++++++---------- test_regress/t/t_inst_array_bad.out | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 2cb57c9f3..dae9078b8 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -532,7 +532,7 @@ private: } return newmodp; } - void visitCell(AstCell* nodep, const string& hierName); + void visitCellDeparam(AstCell* nodep, const string& hierName); void visitModules() { // Loop on all modules left to process // Hitting a cell adds to the appropriate level of this level-sorted list, @@ -558,7 +558,7 @@ private: if (string* genHierNamep = (string*)cellp->user5p()) { fullName += *genHierNamep; } - visitCell(cellp, fullName); + visitCellDeparam(cellp, fullName); } } } @@ -887,7 +887,7 @@ public: //---------------------------------------------------------------------- // VISITs -void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { +void ParamVisitor::visitCellDeparam(AstCell* nodep, const string& hierName) { // Cell: Check for parameters in the instantiation. iterateChildren(nodep); UASSERT_OBJ(nodep->modp(), nodep, "Not linked?"); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 5a01d586f..583d1df52 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -198,8 +198,7 @@ private: // STATE WidthVP* m_vup = nullptr; // Current node state bool m_paramsOnly; // Computing parameter value; limit operation - AstRange* m_cellRangep - = nullptr; // Range for arrayed instantiations, nullptr for normal instantiations + AstCell* m_cellp = nullptr; // Current cell for arrayed instantiations AstNodeFTask* m_ftaskp = nullptr; // Current function/task AstNodeProcedure* m_procedurep = nullptr; // Current final/always AstLambdaArgRef* m_lambdaArgRefp = nullptr; // Argument to above lambda @@ -4052,8 +4051,8 @@ private: if (conDTypep == pinDTypep // If match, we're golden || similarDTypeRecurse(conDTypep, pinDTypep)) { userIterateAndNext(nodep->exprp(), WidthVP(subDTypep, FINAL).p()); - } else if (m_cellRangep) { - int numInsts = m_cellRangep->elementsConst(); + } else if (m_cellp->rangep()) { + int numInsts = m_cellp->rangep()->elementsConst(); if (conwidth == pinwidth) { // Arrayed instants: widths match so connect to each instance subDTypep = conDTypep; // = same expr dtype @@ -4069,7 +4068,7 @@ private: << " requires " << pinwidth << " or " << pinwidth * numInsts << " bits, but connection's " << nodep->exprp()->prettyTypeName() << " generates " << conwidth - << " bits."); + << " bits. (IEEE 1800-2017 23.3.3)"); subDTypep = conDTypep; // = same expr dtype } userIterateAndNext(nodep->exprp(), WidthVP(subDTypep, FINAL).p()); @@ -4138,6 +4137,8 @@ private: // if (debug()) nodep->dumpTree(cout, "- PinOut: "); } virtual void visit(AstCell* nodep) override { + VL_RESTORER(m_cellp); + m_cellp = nodep; if (!m_paramsOnly) { if (VN_IS(nodep->modp(), NotFoundModule)) { // We've resolved parameters and hit a module that we couldn't resolve. It's @@ -4147,14 +4148,10 @@ private: << nodep->modName() << "'"); v3Global.opt.filePathLookedMsg(nodep->modNameFileline(), nodep->modName()); } - if (nodep->rangep()) { - m_cellRangep = nodep->rangep(); - userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p()); - } + if (nodep->rangep()) userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->pinsp(), nullptr); } userIterateAndNext(nodep->paramsp(), nullptr); - m_cellRangep = nullptr; } virtual void visit(AstGatePin* nodep) override { if (m_vup->prelim()) { diff --git a/test_regress/t/t_inst_array_bad.out b/test_regress/t/t_inst_array_bad.out index 312b0b4c3..b438a2a0d 100644 --- a/test_regress/t/t_inst_array_bad.out +++ b/test_regress/t/t_inst_array_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_inst_array_bad.v:19:28: Input port connection 'onebit' as part of a module instance array requires 1 or 8 bits, but connection's VARREF 'onebitbad' generates 9 bits. +%Error: t/t_inst_array_bad.v:19:28: Input port connection 'onebit' as part of a module instance array requires 1 or 8 bits, but connection's VARREF 'onebitbad' generates 9 bits. (IEEE 1800-2017 23.3.3) : ... In instance t 19 | sub sub [7:0] (allbits, onebitbad, bitout); | ^~~~~~~~~ From e6f7510895aca89fe1c64984532205684fa7c540 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 17 Nov 2020 22:14:18 -0500 Subject: [PATCH 17/91] Add check for rand_mode/constraint_mode. --- src/V3Width.cpp | 7 +++++++ test_regress/t/t_class_builtin_bad.out | 9 +++++++++ test_regress/t/t_class_builtin_bad.pl | 19 +++++++++++++++++++ test_regress/t/t_class_builtin_bad.v | 20 ++++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 test_regress/t/t_class_builtin_bad.out create mode 100755 test_regress/t/t_class_builtin_bad.pl create mode 100644 test_regress/t/t_class_builtin_bad.v diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 583d1df52..9e6c68ff8 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -4186,6 +4186,13 @@ private: nodep->didWidth(true); return; } + if (nodep->classMethod() && nodep->name() == "rand_mode") { + nodep->v3error("The 'rand_mode' method is built-in and cannot be overridden" + " (IEEE 1800-2017 18.8)"); + } else if (nodep->classMethod() && nodep->name() == "constraint_mode") { + nodep->v3error("The 'constraint_mode' method is built-in and cannot be overridden" + " (IEEE 1800-2017 18.9)"); + } // Function hasn't been widthed, so make it so. // Would use user1 etc, but V3Width called from too many places to spend a user nodep->doingWidth(true); diff --git a/test_regress/t/t_class_builtin_bad.out b/test_regress/t/t_class_builtin_bad.out new file mode 100644 index 000000000..525420077 --- /dev/null +++ b/test_regress/t/t_class_builtin_bad.out @@ -0,0 +1,9 @@ +%Error: t/t_class_builtin_bad.v:8:17: The 'rand_mode' method is built-in and cannot be overridden (IEEE 1800-2017 18.8) + : ... In instance t + 8 | function int rand_mode(bit onoff); + | ^~~~~~~~~ +%Error: t/t_class_builtin_bad.v:11:17: The 'constraint_mode' method is built-in and cannot be overridden (IEEE 1800-2017 18.9) + : ... In instance t + 11 | function int constraint_mode(bit onoff); + | ^~~~~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_builtin_bad.pl b/test_regress/t/t_class_builtin_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_class_builtin_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_builtin_bad.v b/test_regress/t/t_class_builtin_bad.v new file mode 100644 index 000000000..54f29e150 --- /dev/null +++ b/test_regress/t/t_class_builtin_bad.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + function int rand_mode(bit onoff); + return 1; + endfunction + function int constraint_mode(bit onoff); + return 1; + endfunction +endclass + +module t (/*AUTOARG*/); + initial begin + Cls c; + end +endmodule From 82b2af3b833bb044b21556d5f882b3c240025deb Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 17 Nov 2020 22:48:37 -0500 Subject: [PATCH 18/91] Commentary --- include/verilated.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/verilated.cpp b/include/verilated.cpp index 396b0cd5b..cd301f38b 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -294,7 +294,7 @@ vluint64_t vl_rand64() VL_MT_SAFE { if (VL_UNLIKELY(!t_seeded)) { t_seeded = true; { - const VerilatedLockGuard lock(s_mutex); + const VerilatedLockGuard lock(s_mutex); // Otherwise vl_sys_rand32 is unsafe if (Verilated::randSeed() != 0) { t_state[0] = ((static_cast(Verilated::randSeed()) << 32) ^ (static_cast(Verilated::randSeed()))); From 19e4013ab5bb038ed3144b8d6c55ea88b3d6f1a8 Mon Sep 17 00:00:00 2001 From: Yutetsu TAKATSUKASA Date: Wed, 18 Nov 2020 23:44:45 +0900 Subject: [PATCH 19/91] Allow conversion from const void * to QData (#2650) --- include/verilated.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/verilated.h b/include/verilated.h index c9a198e19..71b2e0c29 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -753,9 +753,9 @@ static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE { u.q = lhs; return u.fp; } -/// Return QData from void* -static inline QData VL_CVT_VP_Q(void* fp) VL_PURE { - union { void* fp; QData q; } u; +/// Return QData from const void* +static inline QData VL_CVT_VP_Q(const void* fp) VL_PURE { + union { const void* fp; QData q; } u; u.q = 0; u.fp = fp; return u.q; From b500e579917962b1d95769903884356d881de3d0 Mon Sep 17 00:00:00 2001 From: Yutetsu TAKATSUKASA Date: Thu, 19 Nov 2020 06:52:03 +0900 Subject: [PATCH 20/91] Add an overload of VL_CVT_PACK_STR_NN for lvalue (#2651) --- include/verilated_heavy.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 5cf4530b0..933a3a6a2 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -783,6 +783,7 @@ inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE { return VL_CVT_PACK_STR_NW(VL_WQ_WORDS_E, lw); } inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE { return lhs; } +inline std::string& VL_CVT_PACK_STR_NN(std::string& lhs) VL_PURE { return lhs; } inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE { WData lw[VL_WQ_WORDS_E]; VL_SET_WI(lw, lhs); From b3760911e714222165db2fbe56726d1119004273 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 18 Nov 2020 19:47:07 -0500 Subject: [PATCH 21/91] Internals: Param minor cleanups. No functional change intended. --- src/V3Param.cpp | 62 ++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index dae9078b8..e27824c74 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -606,41 +606,41 @@ private: m_cellps.push_back(nodep); } virtual void visit(AstNodeFTask* nodep) override { - m_ftaskp = nodep; - iterateChildren(nodep); - m_ftaskp = nullptr; + VL_RESTORER(m_ftaskp); + { + m_ftaskp = nodep; + iterateChildren(nodep); + } } // Make sure all parameters are constantified virtual void visit(AstVar* nodep) override { - if (!nodep->user5SetOnce()) { // Process once - iterateChildren(nodep); - if (nodep->isParam()) { - if (!nodep->valuep()) { - nodep->v3error("Parameter without initial value is never given value" - << " (IEEE 1800-2017 6.20.1): " << nodep->prettyNameQ()); - } else { - V3Const::constifyParamsEdit(nodep); // The variable, not just the var->init() - if (!VN_IS(nodep->valuep(), Const) - && !VN_IS(nodep->valuep(), Unbounded)) { // Complex init, like an array - // Make a new INITIAL to set the value. - // This allows the normal array/struct handling code to properly - // initialize the parameter. - nodep->addNext(new AstInitial( - nodep->fileline(), - new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), - nodep->valuep()->cloneTree(true)))); - if (m_ftaskp) { - // We put the initial in wrong place under a function. We - // should move the parameter out of the function and to the - // module, with appropriate dotting, but this confuses LinkDot - // (as then name isn't found later), so punt - probably can - // treat as static function variable when that is supported. - nodep->v3warn( - E_UNSUPPORTED, - "Unsupported: Parameters in functions with complex assign"); - } + if (nodep->user5SetOnce()) return; // Process once + iterateChildren(nodep); + if (nodep->isParam()) { + if (!nodep->valuep()) { + nodep->v3error("Parameter without initial value is never given value" + << " (IEEE 1800-2017 6.20.1): " << nodep->prettyNameQ()); + } else { + V3Const::constifyParamsEdit(nodep); // The variable, not just the var->init() + if (!VN_IS(nodep->valuep(), Const) + && !VN_IS(nodep->valuep(), Unbounded)) { // Complex init, like an array + // Make a new INITIAL to set the value. + // This allows the normal array/struct handling code to properly + // initialize the parameter. + nodep->addNext(new AstInitial( + nodep->fileline(), + new AstAssign(nodep->fileline(), + new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), + nodep->valuep()->cloneTree(true)))); + if (m_ftaskp) { + // We put the initial in wrong place under a function. We + // should move the parameter out of the function and to the + // module, with appropriate dotting, but this confuses LinkDot + // (as then name isn't found later), so punt - probably can + // treat as static function variable when that is supported. + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: Parameters in functions with complex assign"); } } } From fa771415194a36ad9bb33c025fdf4b1fbd98e291 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 18 Nov 2020 20:12:14 -0500 Subject: [PATCH 22/91] Fix unpacked array parameters near functions (#2639). --- Changes | 2 ++ src/V3Param.cpp | 11 ++---- test_regress/t/t_param_array6.pl | 21 +++++++++++ test_regress/t/t_param_array6.v | 61 ++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 9 deletions(-) create mode 100755 test_regress/t/t_param_array6.pl create mode 100644 test_regress/t/t_param_array6.v diff --git a/Changes b/Changes index 5fed7394f..a89ef1124 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] +**** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] + * Verilator 4.104 2020-11-14 diff --git a/src/V3Param.cpp b/src/V3Param.cpp index e27824c74..a73845d39 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -245,7 +245,6 @@ private: typedef std::deque CellList; CellList m_cellps; // Cells left to process (in this module) - AstNodeFTask* m_ftaskp = nullptr; // Function/task reference AstNodeModule* m_modp = nullptr; // Current module being processed string m_unlinkedTxt; // Text for AstUnlinkedRef UnrollStateful m_unroller; // Loop unroller @@ -605,13 +604,6 @@ private: nodep->user5p(genHierNamep); m_cellps.push_back(nodep); } - virtual void visit(AstNodeFTask* nodep) override { - VL_RESTORER(m_ftaskp); - { - m_ftaskp = nodep; - iterateChildren(nodep); - } - } // Make sure all parameters are constantified virtual void visit(AstVar* nodep) override { @@ -633,7 +625,7 @@ private: new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), nodep->valuep()->cloneTree(true)))); - if (m_ftaskp) { + if (nodep->isFuncLocal()) { // We put the initial in wrong place under a function. We // should move the parameter out of the function and to the // module, with appropriate dotting, but this confuses LinkDot @@ -648,6 +640,7 @@ private: } // Make sure varrefs cause vars to constify before things above virtual void visit(AstVarRef* nodep) override { + // Might jump across functions, so beware if ever add a m_funcp if (nodep->varp()) iterate(nodep->varp()); } bool ifaceParamReplace(AstVarXRef* nodep, AstNode* candp) { diff --git a/test_regress/t/t_param_array6.pl b/test_regress/t/t_param_array6.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_param_array6.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_param_array6.v b/test_regress/t/t_param_array6.v new file mode 100644 index 000000000..34766e731 --- /dev/null +++ b/test_regress/t/t_param_array6.v @@ -0,0 +1,61 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Anderson Ignacio da Silva. +// SPDX-License-Identifier: CC0-1.0 + +package test_pkg; + localparam [31:0] test_arr [4][4:0] + = '{ + '{'h0000, 'h1000, 'h2000, 'h3000, 'h4000}, + '{'h0FFF, 'h1FFF, 'h2FFF, 'h3FFF, 'h4FFF}, + '{ 'd0, 'd0, 'd0, 'd0, 'd0}, + '{ 'd0, 'd1, 'd2, 'd3, 'd4} + }; + + typedef struct packed{ + logic [7:0] val_1; + logic [7:0] val_2; + } test_ret_t; +endpackage + +module t import test_pkg::*; (clk); + input clk; + + function automatic test_ret_t test_f(logic [31:0] val); + test_ret_t temp; + + temp = test_ret_t'(0); + for (int i=0; i<5; i++) begin + if (val >= test_arr[0][i] && val <= test_arr[1][i]) begin + temp.val_1 = test_arr[2][i][7:0]; + temp.val_2 = test_arr[3][i][7:0]; + end + end + return temp; + endfunction + + test_ret_t temp; + logic [31:0] random; + + int cyc; + bit [63:0] sum; + + always @ (posedge clk) begin + cyc <= cyc + 1; + random <= {17'b0, cyc[3:0], 11'b0}; + temp <= test_f(random); +`ifdef TEST_VERBOSE + $display("rand: %h / Values -> val_1: %d / val_2: %d", random, temp.val_1, temp.val_2); +`endif + if (cyc > 10 && cyc < 90) begin + sum <= {48'h0, temp} ^ {sum[62:0],sum[63]^sum[2]^sum[0]}; + end + else if (cyc == 99) begin + $displayh(sum); + if (sum != 64'h74d34ea7a775f994) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule From c0888c1b0ffae3afea7d8c36e05db0fd18fd42e4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 18 Nov 2020 21:03:23 -0500 Subject: [PATCH 23/91] Internals: Use newline instead of endl to avoid unneeded flush. --- include/verilated.cpp | 2 +- include/verilated_cov.cpp | 2 +- src/V3Ast.cpp | 10 ++--- src/V3AstNodes.cpp | 4 +- src/V3Cdc.cpp | 14 +++---- src/V3Changed.cpp | 5 +-- src/V3Config.cpp | 9 ++-- src/V3Const.cpp | 7 ++-- src/V3Delayed.cpp | 8 ++-- src/V3Error.cpp | 2 +- src/V3File.cpp | 13 +++--- src/V3Gate.cpp | 8 ++-- src/V3Graph.cpp | 4 +- src/V3GraphAcyc.cpp | 4 +- src/V3Hashed.cpp | 10 ++--- src/V3InstrCount.cpp | 2 +- src/V3LinkCells.cpp | 8 ++-- src/V3LinkDot.cpp | 56 ++++++++++++------------- src/V3Number.cpp | 2 +- src/V3Options.cpp | 3 +- src/V3Order.cpp | 20 ++++----- src/V3Partition.cpp | 2 +- src/V3PreProc.cpp | 2 +- src/V3StatsReport.cpp | 33 +++++++-------- src/V3String.cpp | 8 ++-- src/V3SymTable.h | 5 +-- src/V3TSP.cpp | 4 +- src/V3Task.cpp | 16 ++++---- src/V3Tristate.cpp | 2 +- src/V3Unroll.cpp | 5 +-- src/V3Waiver.cpp | 18 ++++---- src/V3Width.cpp | 24 +++++------ src/VlcPoint.h | 4 +- src/VlcTest.h | 4 +- src/VlcTop.cpp | 18 ++++---- src/verilog.y | 14 +++---- test_regress/t/t_dpi_accessors.cpp | 66 +++++++++++++++--------------- 37 files changed, 203 insertions(+), 215 deletions(-) diff --git a/include/verilated.cpp b/include/verilated.cpp index cd301f38b..9f3f23b64 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -1045,7 +1045,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf const char* pos = formatp; for (; *pos && !_vl_vsss_eof(fp, floc); ++pos) { // VL_DBG_MSGF("_vlscan fmt='"< 8) { os << indent << " "; dumpPtrs(os); } if (s_debugFileline >= 9) { os << fileline()->warnContextSecondary(); } if (maxDepth == 1) { - if (op1p() || op2p() || op3p() || op4p()) { os << indent << "1: ...(maxDepth)" << endl; } + if (op1p() || op2p() || op3p() || op4p()) os << indent << "1: ...(maxDepth)\n"; } else { for (const AstNode* nodep = op1p(); nodep; nodep = nodep->nextp()) { nodep->dumpTree(os, indent + "1:", maxDepth - 1); @@ -1127,9 +1127,9 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo const std::unique_ptr logsp(V3File::new_ofstream(filename, append)); if (logsp->fail()) v3fatal("Can't write " << filename); *logsp << "Verilator Tree Dump (format 0x3900) from to " << endl; + *logsp << "> to \n"; if (editCountGbl() == editCountLast() && !(v3Global.opt.dumpTree() >= 9)) { - *logsp << endl; + *logsp << '\n'; *logsp << "No changes since last dump!\n"; } else { dumpTree(*logsp); @@ -1199,7 +1199,7 @@ void AstNode::v3errorEnd(std::ostringstream& str) const { std::ostringstream nsstr; nsstr << str.str(); if (debug()) { - nsstr << endl; + nsstr << '\n'; nsstr << "-node: "; const_cast(this)->dump(nsstr); nsstr << endl; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index c620cb432..9ad9a58c1 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1397,7 +1397,7 @@ void AstTypeTable::dump(std::ostream& str) const { this->AstNode::dump(str); for (int i = 0; i < static_cast(AstBasicDTypeKwd::_ENUM_MAX); ++i) { if (AstBasicDType* subnodep = m_basicps[i]) { - str << endl; // Newline from caller, so newline first + str << '\n'; // Newline from caller, so newline first str << "\t\t" << std::setw(8) << AstBasicDTypeKwd(i).ascii(); str << " -> "; subnodep->dump(str); @@ -1407,7 +1407,7 @@ void AstTypeTable::dump(std::ostream& str) const { const DetailedMap& mapr = m_detailedMap; for (const auto& itr : mapr) { AstBasicDType* dtypep = itr.second; - str << endl; // Newline from caller, so newline first + str << '\n'; // Newline from caller, so newline first str << "\t\tdetailed -> "; dtypep->dump(str); } diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 891420e47..65e69ed04 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -150,7 +150,7 @@ private: } else { *m_ofp << " "; } - *m_ofp << nodep->prettyTypeName() << " " << endl; + *m_ofp << nodep->prettyTypeName() << "\n"; string lastPrefix = m_prefix; m_prefix = lastPrefix + "1:"; iterateAndNextNull(nodep->op1p()); @@ -292,7 +292,7 @@ private: told_file = true; std::cerr << V3Error::msgPrefix() << " See details in " << m_ofFilename << endl; } - *m_ofp << "%Warning-" << code.ascii() << ": " << nodep->fileline() << " " << msg << endl; + *m_ofp << "%Warning-" << code.ascii() << ": " << nodep->fileline() << " " << msg << '\n'; } void setNodeHazard(AstNode* nodep) { @@ -462,7 +462,7 @@ private: string front = pad(filelineWidth(), nodep->fileline()->ascii() + ":") + " " + prefix + " +- "; if (VN_IS(nodep, VarScope)) { - *m_ofp << front << "Variable: " << nodep->prettyName() << endl; + *m_ofp << front << "Variable: " << nodep->prettyName() << '\n'; } else { V3EmitV::verilogPrefixedTree(nodep, *m_ofp, prefix + " +- ", filelineWidth(), vertexp->srcDomainp(), true); @@ -509,7 +509,7 @@ private: string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__cdc_edges.txt"; const std::unique_ptr ofp(V3File::new_ofstream(filename)); if (ofp->fail()) v3fatal("Can't write " << filename); - *ofp << "Edge Report for " << v3Global.opt.prefix() << endl; + *ofp << "Edge Report for " << v3Global.opt.prefix() << '\n'; std::deque report; // Sort output by name for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { @@ -536,7 +536,7 @@ private: V3EmitV::verilogForTree(vvertexp->dstDomainp(), os); } os << std::setw(0); - os << endl; + os << '\n'; report.push_back(os.str()); } } @@ -732,7 +732,7 @@ public: m_ofp = V3File::new_ofstream(filename); if (m_ofp->fail()) v3fatal("Can't write " << filename); m_ofFilename = filename; - *m_ofp << "CDC Report for " << v3Global.opt.prefix() << endl; + *m_ofp << "CDC Report for " << v3Global.opt.prefix() << '\n'; *m_ofp << "Each dump below traces logic from inputs/source flops to destination flop(s).\n"; *m_ofp << "First source logic is listed, then a variable that logic generates,\n"; @@ -745,7 +745,7 @@ public: if (false) { *m_ofp << "\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ", 40, nullptr, true); - *m_ofp << endl; + *m_ofp << '\n'; } } virtual ~CdcVisitor() override { diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 6d80a0a7b..7cf53bdfa 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -117,10 +117,9 @@ private: "Unsupported: Can't detect more than " << cvtToStr(DETECTARRAY_MAX_INDEXES) << " array indexes (probably with UNOPTFLAT warning suppressed): " - << m_vscp->prettyName() << endl + << m_vscp->prettyName() << '\n' << m_vscp->warnMore() - << "... Could recompile with DETECTARRAY_MAX_INDEXES increased" - << endl); + << "... Could recompile with DETECTARRAY_MAX_INDEXES increased"); return; } m_statep->maybeCreateChgFuncp(); diff --git a/src/V3Config.cpp b/src/V3Config.cpp index d58608116..e37421159 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -405,7 +405,7 @@ void V3Config::addInline(FileLine* fl, const string& module, const string& ftask V3ConfigResolver::s().modules().at(module).setInline(on); } else { if (!on) { - fl->v3error("no_inline not supported for tasks" << endl); + fl->v3error("no_inline not supported for tasks"); } else { V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setNoInline(on); } @@ -416,15 +416,14 @@ void V3Config::addVarAttr(FileLine* fl, const string& module, const string& ftas const string& var, AstAttrType attr, AstSenTree* sensep) { // Semantics: sensep only if public_flat_rw if ((attr != AstAttrType::VAR_PUBLIC_FLAT_RW) && sensep) { - sensep->v3error("sensitivity not expected for attribute" << endl); + sensep->v3error("sensitivity not expected for attribute"); return; } // Semantics: Most of the attributes operate on signals if (var.empty()) { if (attr == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) { if (ftask.empty()) { - fl->v3error("isolate_assignments only applies to signals or functions/tasks" - << endl); + fl->v3error("isolate_assignments only applies to signals or functions/tasks"); } else { V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setIsolate(true); } @@ -437,7 +436,7 @@ void V3Config::addVarAttr(FileLine* fl, const string& module, const string& ftas V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setPublic(true); } } else { - fl->v3error("missing -signal" << endl); + fl->v3error("missing -signal"); } } else { V3ConfigModule& mod = V3ConfigResolver::s().modules().at(module); diff --git a/src/V3Const.cpp b/src/V3Const.cpp index b2370d1ce..b34485311 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1262,7 +1262,7 @@ private: AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep; nodep->v3error("Expecting expression to be constant, but can't determine constant for " - << nodep->prettyTypeName() << endl + << nodep->prettyTypeName() << '\n' << errorp->warnOther() << "... Location of non-constant " << errorp->prettyTypeName() << ": " << simvis.whyNotMessage()); VL_DO_DANGLING(replaceZero(nodep), nodep); @@ -1930,8 +1930,9 @@ private: nodep->replaceWith(ifp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (ifSameAssign(nodep)) { - UINFO(4, "IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})" - << endl); + UINFO( + 4, + "IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})\n"); AstNodeAssign* ifp = VN_CAST(nodep->ifsp(), NodeAssign); AstNodeAssign* elsep = VN_CAST(nodep->elsesp(), NodeAssign); ifp->unlinkFrBack(); diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index c2f80ca6d..e37f1d7f1 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -160,10 +160,10 @@ private: varrefp->varp()->v3warn( MULTIDRIVEN, "Signal has multiple driving blocks with different clocking: " - << varrefp->varp()->prettyNameQ() << endl - << varrefp->warnOther() << "... Location of first driving block" << endl - << varrefp->warnContextPrimary() << endl - << oldactivep->warnOther() << "... Location of other driving block" << endl + << varrefp->varp()->prettyNameQ() << '\n' + << varrefp->warnOther() << "... Location of first driving block\n" + << varrefp->warnContextPrimary() << '\n' + << oldactivep->warnOther() << "... Location of other driving block\n" << oldactivep->warnContextSecondary()); varrefp->varp()->user2(true); } diff --git a/src/V3Error.cpp b/src/V3Error.cpp index 84df9285f..e8f8c6e18 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -234,7 +234,7 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { s_describedWarnings = true; } if (s_errorCode.dangerous()) { - std::cerr << warnMore() << "*** See the manual before disabling this," << endl; + std::cerr << warnMore() << "*** See the manual before disabling this,\n"; std::cerr << warnMore() << "else you may end up with different sim results." << endl; } diff --git a/src/V3File.cpp b/src/V3File.cpp index 59a2236c0..0d1fc5986 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -159,12 +159,12 @@ inline void V3FileDependImp::writeDepend(const string& filename) { if (!i.target()) *ofp << i.filename() << " "; } - *ofp << endl; + *ofp << '\n'; if (v3Global.opt.makePhony()) { - *ofp << endl; + *ofp << '\n'; for (const DependFile& i : m_filenameList) { - if (!i.target()) *ofp << i.filename() << ":" << endl; + if (!i.target()) *ofp << i.filename() << ":\n"; } } } @@ -183,9 +183,8 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm string cmdline = stripQuotes(cmdlineIn); *ofp << "# DESCR" - << "IPTION: Verilator output: Timestamp data for --skip-identical. Delete at will." - << endl; - *ofp << "C \"" << cmdline << "\"" << endl; + << "IPTION: Verilator output: Timestamp data for --skip-identical. Delete at will.\n"; + *ofp << "C \"" << cmdline << "\"\n"; for (std::set::iterator iter = m_filenameList.begin(); iter != m_filenameList.end(); ++iter) { @@ -209,7 +208,7 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm *ofp << " " << std::setw(11) << iter->mstime(); *ofp << " " << std::setw(11) << iter->mnstime(); *ofp << " \"" << iter->filename() << "\""; - *ofp << endl; + *ofp << '\n'; } } diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index b0b7d0a20..25b45e040 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -810,10 +810,10 @@ void GateVisitor::warnSignals() { vscp->varp()->user2(true); // Warn only once per signal vscp->v3warn(SYNCASYNCNET, "Signal flopped as both synchronous and async: " - << vscp->prettyNameQ() << endl - << ap->warnOther() << "... Location of async usage" << endl - << ap->warnContextPrimary() << endl - << sp->warnOther() << "... Location of sync usage" << endl + << vscp->prettyNameQ() << '\n' + << ap->warnOther() << "... Location of async usage\n" + << ap->warnContextPrimary() << '\n' + << sp->warnOther() << "... Location of sync usage\n" << sp->warnContextSecondary()); } } diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index 8001d55b6..1e7216bfd 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -279,7 +279,7 @@ void V3Graph::dump(std::ostream& os) { for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { os << "\tNode: " << vertexp->name(); if (vertexp->color()) os << " color=" << vertexp->color(); - os << endl; + os << '\n'; // Print edges for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { dumpEdge(os, vertexp, edgep); @@ -296,7 +296,7 @@ void V3Graph::dumpEdge(std::ostream& os, V3GraphVertex* vertexp, V3GraphEdge* ed if (edgep->fromp() == vertexp) os << "-> " << edgep->top()->name(); if (edgep->top() == vertexp) os << "<- " << edgep->fromp()->name(); if (edgep->cutable()) os << " [CUTABLE]"; - os << endl; + os << '\n'; } } diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 4eff24c30..dce97d011 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -59,7 +59,7 @@ private: typedef std::list OrigEdgeList; // List of orig edges, see also GraphAcyc's decl V3GraphEdge* origEdgep() const { OrigEdgeList* oEListp = static_cast(userp()); - if (!oEListp) v3fatalSrc("No original edge associated with acyc edge " << this << endl); + if (!oEListp) v3fatalSrc("No original edge associated with acyc edge " << this); return (oEListp->front()); } @@ -155,7 +155,7 @@ private: breakEdgep->cut(); OrigEdgeList* oEListp = static_cast(breakEdgep->userp()); if (!oEListp) { - v3fatalSrc("No original edge associated with cutting edge " << breakEdgep << endl); + v3fatalSrc("No original edge associated with cutting edge " << breakEdgep); } // The breakGraph edge may represent multiple real edges; cut them all for (const auto& origEdgep : *oEListp) { diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index e830f0ab7..a9600f699 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -172,19 +172,19 @@ void V3Hashed::dumpFile(const string& filename, bool tree) { if (it == end()) break; num_in_bucket++; } - *logp << "\n*** STATS:\n" << endl; + *logp << "\n*** STATS:\n\n"; *logp << " #InBucket Occurrences\n"; for (const auto& i : dist) { - *logp << " " << std::setw(9) << i.first << " " << std::setw(12) << i.second << endl; + *logp << " " << std::setw(9) << i.first << " " << std::setw(12) << i.second << '\n'; } - *logp << "\n*** Dump:\n" << endl; + *logp << "\n*** Dump:\n\n"; for (const auto& itr : *this) { if (lasthash != itr.first) { lasthash = itr.first; - *logp << " " << itr.first << endl; + *logp << " " << itr.first << '\n'; } - *logp << "\t" << itr.second << endl; + *logp << "\t" << itr.second << '\n'; // Dumping the entire tree may make nearly N^2 sized dumps, // because the nodes under this one may also be in the hash table! if (tree) itr.second->dumpTree(*logp, " "); diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 5eb23fae9..894aceba4 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -284,7 +284,7 @@ private: ++m_depth; if (unsigned costPlus1 = nodep->user4()) { *m_osp << " " << indent() << "cost " << std::setw(6) << std::left << (costPlus1 - 1) - << " " << nodep << endl; + << " " << nodep << '\n'; iterateChildren(nodep); } --m_depth; diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 73e688c3e..a5f8e78c7 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -78,7 +78,7 @@ void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) { vvertexp->modp()->v3warn(E_UNSUPPORTED, "Unsupported: Recursive multiple modules (module instantiates " "something leading back to itself): " - << vvertexp->modp()->prettyNameQ() << endl + << vvertexp->modp()->prettyNameQ() << '\n' << V3Error::warnMore() << "... note: self-recursion (module instantiating itself " "directly) is supported."); @@ -482,10 +482,10 @@ private: || nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP) || hierBlocks.find(nodep->name()) != hierBlocks.end())) { nodep->v3warn(MODDUP, "Duplicate declaration of module: " - << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << foundp->warnOther() - << "... Location of original declaration" << endl + << "... Location of original declaration\n" << foundp->warnContextSecondary()); } nodep->unlinkFrBack(); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 5d07c5457..df155c683 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -180,7 +180,7 @@ public: // left side is what we will import into os << "\t" << samn << "\t" << it->first << " (" << it->first->nodep()->typeName() << ") <- " << it->second << " " - << it->second->nodep() << endl; + << it->second->nodep() << '\n'; } } } @@ -269,15 +269,15 @@ public: UINFO(4, "Var2 " << fnodep << endl); if (nodep->type() == fnodep->type()) { nodep->v3error("Duplicate declaration of " - << nodeTextType(fnodep) << ": " << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + << nodeTextType(fnodep) << ": " << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << fnodep->warnOther() << "... Location of original declaration\n" << fnodep->warnContextSecondary()); } else { nodep->v3error("Unsupported in C: " << ucfirst(nodeTextType(nodep)) << " has the same name as " - << nodeTextType(fnodep) << ": " << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + << nodeTextType(fnodep) << ": " << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << fnodep->warnOther() << "... Location of original declaration\n" << fnodep->warnContextSecondary()); } @@ -481,7 +481,7 @@ public: ifacerefp->modportFileline()->v3error( "Modport not found under interface " << ifacerefp->prettyNameQ(ifacerefp->ifaceName()) << ": " - << ifacerefp->prettyNameQ(ifacerefp->modportName()) << endl + << ifacerefp->prettyNameQ(ifacerefp->modportName()) << '\n' << (suggest.empty() ? "" : ifacerefp->warnMore() + suggest)); } } @@ -1081,15 +1081,15 @@ class LinkDotFindVisitor : public AstNVisitor { if (didAnsiWarn++) ansiWarn = false; } nodep->v3error("Duplicate declaration of signal: " - << nodep->prettyNameQ() << endl + << nodep->prettyNameQ() << '\n' << (ansiWarn ? nodep->warnMore() + "... note: ANSI ports must have" " type declared with the I/O (IEEE " "1800-2017 23.2.2.2)\n" : "") - << nodep->warnContextPrimary() << endl + << nodep->warnContextPrimary() << '\n' << findvarp->warnOther() - << "... Location of original declaration" << endl + << "... Location of original declaration\n" << findvarp->warnContextSecondary()); // Combining most likely reduce other errors findvarp->combineType(nodep); @@ -1119,8 +1119,8 @@ class LinkDotFindVisitor : public AstNVisitor { && !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) { nodep->v3warn(VARHIDDEN, "Declaration of signal hides declaration in upper scope: " - << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << foundp->nodep()->warnOther() << "... Location of original declaration\n" << foundp->nodep()->warnContextSecondary()); @@ -1204,8 +1204,8 @@ class LinkDotFindVisitor : public AstNVisitor { if (foundp->parentp() == m_curSymp // Only when on same level && !foundp->imported()) { // and not from package nodep->v3error("Duplicate declaration of enum value: " - << nodep->prettyName() << endl - << nodep->warnContextPrimary() << endl + << nodep->prettyName() << '\n' + << nodep->warnContextPrimary() << '\n' << foundp->nodep()->warnOther() << "... Location of original declaration\n" << foundp->nodep()->warnContextSecondary()); @@ -1215,8 +1215,8 @@ class LinkDotFindVisitor : public AstNVisitor { && !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) { nodep->v3warn(VARHIDDEN, "Declaration of enum value hides declaration in upper scope: " - << nodep->prettyName() << endl - << nodep->warnContextPrimary() << endl + << nodep->prettyName() << '\n' + << nodep->warnContextPrimary() << '\n' << foundp->nodep()->warnOther() << "... Location of original declaration\n" << nodep->warnContextSecondary()); @@ -1417,8 +1417,8 @@ private: } else { if (refp->user4()) { nodep->v3error("Duplicate declaration of port: " - << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << refp->warnOther() << "... Location of original declaration\n" << refp->warnContextSecondary()); } @@ -1811,7 +1811,7 @@ private: LinkNodeMatcherVar()); nodep->v3error("Signal definition not found, and implicit disabled with " "`default_nettype: " - << nodep->prettyNameQ() << endl + << nodep->prettyNameQ() << '\n' << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } @@ -1822,7 +1822,7 @@ private: LinkNodeMatcherVar()); nodep->v3warn(IMPLICIT, "Signal definition not found, creating implicitly: " - << nodep->prettyNameQ() << endl + << nodep->prettyNameQ() << '\n' << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } } @@ -1876,8 +1876,8 @@ private: } void markAndCheckPinDup(AstNode* nodep, AstNode* refp, const char* whatp) { if (refp->user5p() && refp->user5p() != nodep) { - nodep->v3error("Duplicate " << whatp << " connection: " << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + nodep->v3error("Duplicate " << whatp << " connection: " << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << refp->user5p()->warnOther() << "... Location of original " << whatp << " connection\n" << refp->user5p()->warnContextSecondary()); @@ -1973,7 +1973,7 @@ private: : m_statep->suggestSymFlat(m_pinSymp, nodep->name(), LinkNodeMatcherVarIO())); nodep->v3error(ucfirst(whatp) - << " not found: " << nodep->prettyNameQ() << endl + << " not found: " << nodep->prettyNameQ() << '\n' << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } else if (AstVar* refp = VN_CAST(foundp->nodep(), Var)) { if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) { @@ -2327,7 +2327,7 @@ private: string suggest = m_statep->suggestSymFallback( m_ds.m_dotSymp, nodep->name(), VNodeMatcher()); nodep->v3error("Can't find definition of " - << expectWhat << ": " << nodep->prettyNameQ() << endl + << expectWhat << ": " << nodep->prettyNameQ() << '\n' << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } else { nodep->v3error("Can't find definition of " @@ -2605,14 +2605,14 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); return; } else { - nodep->v3error("Unsupported or unknown PLI call: " - << nodep->prettyNameQ() << endl); + nodep->v3error( + "Unsupported or unknown PLI call: " << nodep->prettyNameQ()); } } else { string suggest = m_statep->suggestSymFallback(dotSymp, nodep->name(), LinkNodeMatcherFTask()); nodep->v3error("Can't find definition of task/function: " - << nodep->prettyNameQ() << endl + << nodep->prettyNameQ() << '\n' << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } } else { @@ -2773,7 +2773,7 @@ private: m_curSymp, cpackagerefp->name(), LinkNodeMatcherClass{}); cpackagerefp->v3error( "Class to extend not found: " - << cpackagerefp->prettyNameQ() << endl + << cpackagerefp->prettyNameQ() << '\n' << (suggest.empty() ? "" : cpackagerefp->warnMore() + suggest)); } } @@ -2810,7 +2810,7 @@ private: if (!VN_IS(nodep->packagep(), Class) && !VN_IS(nodep->packagep(), Package)) { cpackagerefp->v3error( "'::' expected to reference a class/package but referenced " - << nodep->packagep()->prettyTypeName() << endl + << nodep->packagep()->prettyTypeName() << '\n' << cpackagerefp->warnMore() + "... Suggest '.' instead of '::'"); } } diff --git a/src/V3Number.cpp b/src/V3Number.cpp index cf6ef219b..551229f4e 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -227,7 +227,7 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) if (product.bitsValue(width(), 4)) { // Overflowed static int warned = 0; v3error("Too many digits for " - << width() << " bit number: " << sourcep << std::endl + << width() << " bit number: " << sourcep << '\n' << ((!m_sized && !warned++) ? ( V3Error::warnMore() + "... As that number was unsized" + " ('d...) it is limited to 32 bits (IEEE 1800-2017 " diff --git a/src/V3Options.cpp b/src/V3Options.cpp index b8ec760e5..b388d8394 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -547,8 +547,7 @@ void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) { } else if (!shown_notfound_msg) { shown_notfound_msg = true; if (m_impp->m_incDirUsers.empty()) { - fl->v3error("This may be because there's no search path specified with -I." - << endl); + fl->v3error("This may be because there's no search path specified with -I."); } std::cerr << V3Error::warnMore() << "... Looked in:" << endl; for (const string& dir : m_impp->m_incDirUsers) { diff --git a/src/V3Order.cpp b/src/V3Order.cpp index baeda2cb1..7653e7054 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -113,7 +113,7 @@ static bool domainsExclusive(const AstSenTree* fromp, const AstSenTree* top); // Functions for above graph classes void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) { - if (debug()) cout << "-Info-Loop: " << vertexp << " " << endl; + if (debug()) cout << "-Info-Loop: " << vertexp << "\n"; if (OrderLogicVertex* vvertexp = dynamic_cast(vertexp)) { std::cerr << vvertexp->nodep()->fileline()->warnOther() << " Example path: " << vvertexp->nodep()->typeName() << endl; @@ -273,7 +273,7 @@ private: if (m_inClocked) { varrefp->v3warn( CLKDATA, "Clock used as data (on rhs of assignment) in sequential block " - << varrefp->prettyNameQ() << endl); + << varrefp->prettyNameQ()); } else { m_hasClk = true; UINFO(5, "node is already marked as clocker " << varrefp << endl); @@ -290,8 +290,8 @@ private: // do the marking if (m_hasClk) { if (nodep->lhsp()->width() > m_rightClkWidth) { - nodep->v3warn(CLKDATA, "Clock is assigned to part of data signal " << nodep->lhsp() - << endl); + nodep->v3warn(CLKDATA, + "Clock is assigned to part of data signal " << nodep->lhsp()); UINFO(4, "CLKDATA: lhs with width " << nodep->lhsp()->width() << endl); UINFO(4, " but rhs clock with width " << m_rightClkWidth << endl); return; // skip the marking @@ -870,7 +870,7 @@ private: m_graph.userClearVertices(); // May be very large vector, so only report the "most important" // elements. Up to 10 of the widest - std::cerr << V3Error::warnMore() << "... Widest candidate vars to split:" << endl; + std::cerr << V3Error::warnMore() << "... Widest candidate vars to split:\n"; std::stable_sort(m_unoptflatVars.begin(), m_unoptflatVars.end(), OrderVarWidthCmp()); std::unordered_set canSplitList; int lim = m_unoptflatVars.size() < 10 ? m_unoptflatVars.size() : 10; @@ -885,10 +885,10 @@ private: std::cerr << ", can split_var"; canSplitList.insert(varp); } - std::cerr << std::endl; + std::cerr << '\n'; } // Up to 10 of the most fanned out - std::cerr << V3Error::warnMore() << "... Most fanned out candidate vars to split:" << endl; + std::cerr << V3Error::warnMore() << "... Most fanned out candidate vars to split:\n"; std::stable_sort(m_unoptflatVars.begin(), m_unoptflatVars.end(), OrderVarFanoutCmp()); lim = m_unoptflatVars.size() < 10 ? m_unoptflatVars.size() : 10; for (int i = 0; i < lim; i++) { @@ -902,7 +902,7 @@ private: std::cerr << ", can split_var"; canSplitList.insert(varp); } - std::cerr << endl; + std::cerr << '\n'; } if (!canSplitList.empty()) { std::cerr << V3Error::warnMore() @@ -1573,9 +1573,9 @@ void OrderVisitor::processEdgeReport() { } } - *logp << "Signals and their clock domains:" << endl; + *logp << "Signals and their clock domains:\n"; stable_sort(report.begin(), report.end()); - for (const string& i : report) *logp << i << endl; + for (const string& i : report) *logp << i << '\n'; } void OrderVisitor::processMoveClear() { diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index afe723493..b927ad644 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -663,7 +663,7 @@ public: // Dump for (const LogicMTask* mtaskp : path) { - *osp << "begin mtask with cost " << mtaskp->cost() << endl; + *osp << "begin mtask with cost " << mtaskp->cost() << '\n'; for (VxList::const_iterator lit = mtaskp->vertexListp()->begin(); lit != mtaskp->vertexListp()->end(); ++lit) { const OrderLogicVertex* logicp = (*lit)->logicp(); diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 9a4250676..344b939c2 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -855,7 +855,7 @@ void V3PreProcImp::dumpDefines(std::ostream& os) { // No need to print "()" below as already part of params() if (!it->second.params().empty()) os << it->second.params(); if (!it->second.value().empty()) os << " " << it->second.value(); - os << endl; + os << '\n'; } } diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp index 14ad340ea..e93491eec 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -39,13 +39,12 @@ class StatsReport { static StatColl s_allStats; ///< All statistics void header() { - os << "Verilator Statistics Report\n"; - os << endl; + os << "Verilator Statistics Report\n\n"; - os << "Information:" << endl; - os << " " << V3Options::version() << endl; - os << " Arguments: " << v3Global.opt.allArgsString() << endl; - os << endl; + os << "Information:\n"; + os << " " << V3Options::version() << '\n'; + os << " Arguments: " << v3Global.opt.allArgsString() << '\n'; + os << '\n'; } void sumit() { @@ -85,28 +84,26 @@ class StatsReport { } // Print organized by stage - os << "Global Statistics:\n"; - os << endl; + os << "Global Statistics:\n\n"; for (const auto& itr : byName) { const V3Statistic* repp = itr.second; if (repp->perf()) continue; os << " " << std::left << std::setw(maxWidth) << repp->name(); repp->dump(os); - os << endl; + os << '\n'; } - os << endl; + os << '\n'; // Print organized by stage - os << "Performance Statistics:\n"; - os << endl; + os << "Performance Statistics:\n\n"; for (const auto& itr : byName) { const V3Statistic* repp = itr.second; if (!repp->perf()) continue; os << " " << std::left << std::setw(maxWidth) << repp->name(); repp->dump(os); - os << endl; + os << '\n'; } - os << endl; + os << '\n'; } void stages() { @@ -136,7 +133,7 @@ class StatsReport { // Header os << " Stat " << std::left << std::setw(maxWidth - 5 - 2) << ""; for (const string& i : stages) os << " " << std::left << std::setw(9) << i; - os << endl; + os << '\n'; os << " -------- " << std::left << std::setw(maxWidth - 5 - 2) << ""; for (auto it = stages.begin(); it != stages.end(); ++it) { os << " " << std::left << std::setw(9) << "-------"; @@ -157,10 +154,10 @@ class StatsReport { if ((pos = commaName.find(',')) != string::npos) commaName.erase(pos); if (lastCommaName != commaName) { lastCommaName = commaName; - os << endl; + os << '\n'; } } - os << endl; + os << '\n'; col = 0; os << " " << std::left << std::setw(maxWidth) << repp->name(); } @@ -171,7 +168,7 @@ class StatsReport { repp->dump(os); col++; } - os << endl; + os << '\n'; } public: diff --git a/src/V3String.cpp b/src/V3String.cpp index d8d2c32cd..418101436 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -345,13 +345,13 @@ void VHashSha256::selfTestOne(const string& data, const string& data2, const str VHashSha256 digest(data); if (data2 != "") digest.insert(data2); if (VL_UNCOVERABLE(digest.digestHex() != exp)) { - std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE - << " ... got=" << digest.digestHex() << endl // LCOV_EXCL_LINE + std::cerr << "%Error: When hashing '" << data + data2 << "'\n" // LCOV_EXCL_LINE + << " ... got=" << digest.digestHex() << '\n' // LCOV_EXCL_LINE << " ... exp=" << exp << endl; // LCOV_EXCL_LINE } if (VL_UNCOVERABLE(digest.digestSymbol() != exp64)) { - std::cerr << "%Error: When hashing '" << data + data2 << "'" << endl // LCOV_EXCL_LINE - << " ... got=" << digest.digestSymbol() << endl // LCOV_EXCL_LINE + std::cerr << "%Error: When hashing '" << data + data2 << "'\n" // LCOV_EXCL_LINE + << " ... got=" << digest.digestSymbol() << '\n' // LCOV_EXCL_LINE << " ... exp=" << exp64 << endl; // LCOV_EXCL_LINE } } diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 6fbdca71f..e77b982d7 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -72,7 +72,7 @@ public: os << " fallb=se" << cvtToHex(m_fallbackp); if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix; os << " n=" << nodep(); - os << endl; + os << '\n'; if (VL_UNCOVERABLE(doneSymsr.find(this) != doneSymsr.end())) { os << indent << "| ^ duplicate, so no children printed\n"; // LCOV_EXCL_LINE } else { @@ -126,8 +126,7 @@ public: if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) { if (!V3Error::errorCount()) { // Else may have just reported warning if (debug() >= 9 || V3Error::debugDefault()) dump(cout, "- err-dump: ", 1); - entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name - << endl); + entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name); } } else { m_idNameMap.insert(make_pair(name, entp)); diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index b107530f8..07a6d9e84 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -346,10 +346,10 @@ public: os << "At " << nameComment << ", dumping graph. Keys:\n"; for (V3GraphVertex* vxp = verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { Vertex* tspvp = castVertexp(vxp); - os << " " << tspvp->key() << endl; + os << " " << tspvp->key() << '\n'; for (V3GraphEdge* edgep = tspvp->outBeginp(); edgep; edgep = edgep->outNextp()) { Vertex* neighborp = castVertexp(edgep->top()); - os << " has edge " << edgep->user() << " to " << neighborp->key() << endl; + os << " has edge " << edgep->user() << " to " << neighborp->key() << '\n'; } } } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 574117607..8cb19bedb 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -146,11 +146,11 @@ public: if (!vxp->pure()) { nodep->v3warn( IMPURE, "Unsupported: External variable referenced by non-inlined function/task: " - << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << vxp->impureNode()->warnOther() << "... Location of the external reference: " - << vxp->impureNode()->prettyNameQ() << endl + << vxp->impureNode()->prettyNameQ() << '\n' << vxp->impureNode()->warnContextSecondary()); } // And, we need to check all tasks this task calls @@ -837,11 +837,11 @@ private: } else if (iter->second.second != dpiproto) { nodep->v3error( "Duplicate declaration of DPI function with different formal arguments: " - << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl - << nodep->warnMore() << "... New prototype: " << dpiproto << endl + << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' + << nodep->warnMore() << "... New prototype: " << dpiproto << '\n' << iter->second.first->warnOther() - << "... Original prototype: " << iter->second.second << endl + << "... Original prototype: " << iter->second.second << '\n' << iter->second.first->warnContextSecondary()); return true; } else { @@ -862,7 +862,7 @@ private: portp->v3warn( E_UNSUPPORTED, "Unsupported: DPI argument of type " - << portp->basicp()->prettyTypeName() << endl + << portp->basicp()->prettyTypeName() << '\n' << portp->warnMore() << "... For best portability, use bit, byte, int, or longint"); // We don't warn on logic either, although the 4-stateness is lost. diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 7b1fa24d2..086ecbb30 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -449,7 +449,7 @@ class TristateVisitor : public TristateBaseVisitor { } else { if (oldpullp->direction() != pullp->direction()) { pullp->v3warn(E_UNSUPPORTED, "Unsupported: Conflicting pull directions.\n" - << pullp->warnContextPrimary() << endl + << pullp->warnContextPrimary() << '\n' << oldpullp->warnOther() << "... Location of conflicting pull.\n" << oldpullp->warnContextSecondary()); diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 7a9c15e04..7a0165c15 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -118,11 +118,10 @@ private: m_forVarp = VN_CAST(initAssp->lhsp(), VarRef)->varp(); m_forVscp = VN_CAST(initAssp->lhsp(), VarRef)->varScopep(); if (VN_IS(nodep, GenFor) && !m_forVarp->isGenVar()) { - nodep->v3error("Non-genvar used in generate for: " // - << m_forVarp->prettyNameQ() << endl); + nodep->v3error("Non-genvar used in generate for: " << m_forVarp->prettyNameQ()); } else if (!VN_IS(nodep, GenFor) && m_forVarp->isGenVar()) { nodep->v3error("Genvar not legal in non-generate for (IEEE 1800-2017 27.4): " - << m_forVarp->prettyNameQ() << endl + << m_forVarp->prettyNameQ() << '\n' << nodep->warnMore() << "... Suggest move for loop upwards to generate-level scope."); } diff --git a/src/V3Waiver.cpp b/src/V3Waiver.cpp index 6cfa87687..31b6b9c86 100644 --- a/src/V3Waiver.cpp +++ b/src/V3Waiver.cpp @@ -34,20 +34,18 @@ void V3Waiver::write(const std::string& filename) { if (ofp->fail()) v3fatal("Can't write " << filename); *ofp << "// DESCR" - "IPTION: Verilator output: Waivers generated with --waiver-output" - << std::endl - << endl; + "IPTION: Verilator output: Waivers generated with --waiver-output\n\n"; - *ofp << "`verilator_config" << endl << endl; + *ofp << "`verilator_config\n\n"; - *ofp << "// Below you find suggested waivers. You have three options:" << endl; - *ofp << "// 1. Fix the reason for the linter warning" << endl; - *ofp << "// 2. Keep the waiver permanently if you are sure this is okay" << endl; - *ofp << "// 3. Keep the waiver temporarily to suppress the output" << endl << endl; + *ofp << "// Below you find suggested waivers. You have three options:\n"; + *ofp << "// 1. Fix the reason for the linter warning\n"; + *ofp << "// 2. Keep the waiver permanently if you are sure this is okay\n"; + *ofp << "// 3. Keep the waiver temporarily to suppress the output\n\n"; - if (s_waiverList.size() == 0) { *ofp << "// No waivers needed - great!" << endl; } + if (s_waiverList.empty()) *ofp << "// No waivers needed - great!\n"; - for (const auto& i : s_waiverList) *ofp << "// " << i << std::endl << endl; + for (const auto& i : s_waiverList) *ofp << "// " << i << "\n\n"; } V3Waiver::WaiverList V3Waiver::s_waiverList; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 9e6c68ff8..17979e595 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1605,10 +1605,10 @@ private: virtual void visit(AstTypedef* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed if (auto* refp = checkRefToTypedefRecurse(nodep, nodep)) { - nodep->v3error("Typedef has self-reference: " << nodep->prettyNameQ() << endl - << nodep->warnContextPrimary() << endl + nodep->v3error("Typedef has self-reference: " << nodep->prettyNameQ() << '\n' + << nodep->warnContextPrimary() << '\n' << refp->warnOther() - << "... Location of reference" << endl + << "... Location of reference\n" << refp->warnContextSecondary()); // May cause internel error but avoids infinite loop on dump refp->typedefp(nullptr); @@ -1959,8 +1959,8 @@ private: if (inits.find(num) != inits.end()) { // IEEE says illegal AstNode* otherp = inits.find(num)->second; itemp->v3error("Overlapping enumeration value: " - << itemp->prettyNameQ() << endl - << itemp->warnContextPrimary() << endl + << itemp->prettyNameQ() << '\n' + << itemp->warnContextPrimary() << '\n' << otherp->warnOther() << "... Location of original declaration\n" << otherp->warnContextSecondary()); } else { @@ -2249,7 +2249,7 @@ private: } UINFO(1, "found object " << foundp << endl); nodep->v3fatalSrc("MemberSel of non-variable\n" - << nodep->warnContextPrimary() << endl + << nodep->warnContextPrimary() << '\n' << foundp->warnOther() << "... Location of found object\n" << foundp->warnContextSecondary()); } @@ -4079,7 +4079,7 @@ private: << " requires matching types;" << " ref requires " << pinDTypep->prettyDTypeNameQ() << " data type but connection is " - << conDTypep->prettyDTypeNameQ() << " data type." << endl); + << conDTypep->prettyDTypeNameQ() << " data type."); } else if (nodep->modVarp()->isTristate()) { if (pinwidth != conwidth) { nodep->v3warn(E_UNSUPPORTED, @@ -5411,9 +5411,7 @@ private: case AstType::atMulS: newp = new AstMul(fl, lhsp, rhsp); break; case AstType::atShiftR: newp = new AstShiftRS(fl, lhsp, rhsp); break; case AstType::atShiftRS: newp = new AstShiftR(fl, lhsp, rhsp); break; - default: - nodep->v3fatalSrc("Node needs sign change, but bad case: " << nodep << endl); - break; + default: nodep->v3fatalSrc("Node needs sign change, but bad case: " << nodep); break; } UINFO(6, " ReplaceWithUOrSVersion: " << nodep << " w/ " << newp << endl); nodep->replaceWith(newp); @@ -5451,7 +5449,7 @@ private: case AstType::atMul: case AstType::atMulS: newp = new AstMulD(fl, lhsp, rhsp); break; default: - nodep->v3fatalSrc("Node needs conversion to double, but bad case: " << nodep << endl); + nodep->v3fatalSrc("Node needs conversion to double, but bad case: " << nodep); break; } UINFO(6, " ReplaceWithDVersion: " << nodep << " w/ " << newp << endl); @@ -5483,7 +5481,7 @@ private: case AstType::atLte: case AstType::atLteS: newp = new AstLteN(fl, lhsp, rhsp); break; default: - nodep->v3fatalSrc("Node needs conversion to string, but bad case: " << nodep << endl); + nodep->v3fatalSrc("Node needs conversion to string, but bad case: " << nodep); break; } UINFO(6, " ReplaceWithNVersion: " << nodep << " w/ " << newp << endl); @@ -5502,7 +5500,7 @@ private: switch (nodep->type()) { case AstType::atNegate: newp = new AstNegateD(fl, lhsp); break; default: - nodep->v3fatalSrc("Node needs conversion to double, but bad case: " << nodep << endl); + nodep->v3fatalSrc("Node needs conversion to double, but bad case: " << nodep); break; } UINFO(6, " ReplaceWithDVersion: " << nodep << " w/ " << newp << endl); diff --git a/src/VlcPoint.h b/src/VlcPoint.h index ff88f00e0..e87c0de0f 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -77,13 +77,13 @@ public: } static void dumpHeader() { cout << "Points:\n"; - cout << " Num, TestsCover, Count, Name" << endl; + cout << " Num, TestsCover, Count, Name\n"; } void dump() const { cout << " " << std::setw(8) << std::setfill('0') << pointNum(); cout << ", " << std::setw(7) << std::setfill(' ') << testsCovering(); cout << ", " << std::setw(7) << std::setfill(' ') << count(); - cout << ", \"" << name() << "\"" << endl; + cout << ", \"" << name() << "\"\n"; } }; diff --git a/src/VlcTest.h b/src/VlcTest.h index c95e351d7..8db9a2059 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -65,7 +65,7 @@ public: static void dumpHeader() { cout << "Tests:\n"; // cout<<" Testrun, Computrons,"; // Currently not loaded - cout << " Covered, Rank, RankPts, Filename" << endl; + cout << " Covered, Rank, RankPts, Filename\n"; } void dump(bool bucketsToo) { if (testrun() || computrons() != 0.0) { // currently unused // LCOV_EXCL_LINE @@ -76,7 +76,7 @@ public: cout << " " << std::setw(7) << std::setfill(' ') << bucketsCovered(); cout << ", " << std::setw(7) << std::setfill(' ') << rank(); cout << ", " << std::setw(7) << std::setfill(' ') << rankPoints(); - cout << ", \"" << name() << "\"" << endl; + cout << ", \"" << name() << "\"\n"; if (bucketsToo) m_buckets.dump(); } }; diff --git a/src/VlcTop.cpp b/src/VlcTop.cpp index 4ff050d5f..ee7c57153 100644 --- a/src/VlcTop.cpp +++ b/src/VlcTop.cpp @@ -69,10 +69,10 @@ void VlcTop::writeCoverage(const string& filename) { return; } - os << "# SystemC::Coverage-3" << endl; + os << "# SystemC::Coverage-3\n"; for (const auto& i : m_points) { const VlcPoint& point = m_points.pointNumber(i.second); - os << "C '" << point.name() << "' " << point.count() << endl; + os << "C '" << point.name() << "' " << point.count() << '\n'; } } @@ -109,7 +109,7 @@ void VlcTop::writeInfo(const string& filename) { os << "TN:verilator_coverage\n"; for (auto& si : m_sources) { VlcSource& source = si.second; - os << "SF:" << source.name() << endl; + os << "SF:" << source.name() << '\n'; VlcSource::LinenoMap& lines = source.lines(); for (auto& li : lines) { int lineno = li.first; @@ -206,7 +206,7 @@ void VlcTop::annotateCalc() { unsigned thresh = (!threshStr.empty()) ? atoi(threshStr.c_str()) : opt.annotateMin(); bool ok = (point.count() >= thresh); UINFO(9, "AnnoCalc count " << filename << ":" << lineno << ":" << point.column() << " " - << point.count() << " " << point.linescov() << endl); + << point.count() << " " << point.linescov() << '\n'); // Base coverage source.incCount(lineno, point.column(), point.count(), ok); // Additional lines covered by this statement @@ -263,8 +263,8 @@ void VlcTop::annotateCalcNeeded() { } float pct = totCases ? (100 * totOk / totCases) : 0; cout << "Total coverage (" << totOk << "/" << totCases << ") "; - cout << std::fixed << std::setw(3) << std::setprecision(2) << pct << "%" << endl; - if (totOk != totCases) cout << "See lines with '%00' in " << opt.annotateOut() << endl; + cout << std::fixed << std::setw(3) << std::setprecision(2) << pct << "%\n"; + if (totOk != totCases) cout << "See lines with '%00' in " << opt.annotateOut() << '\n'; } void VlcTop::annotateOutputFiles(const string& dirname) { @@ -290,7 +290,7 @@ void VlcTop::annotateOutputFiles(const string& dirname) { return; } - os << "\t// verilator_coverage annotation" << endl; + os << "\t// verilator_coverage annotation\n"; int lineno = 0; while (!is.eof()) { @@ -308,7 +308,7 @@ void VlcTop::annotateOutputFiles(const string& dirname) { // UINFO(0,"Source // "<toUInt(), $7->toUInt()+1); } | vltOffFront yVLT_D_FILE yaSTRING yVLT_D_MATCH yaSTRING { if (($1==V3ErrorCode::I_COVERAGE) || ($1==V3ErrorCode::I_TRACING)) { - $1->v3error("Argument -match only supported for lint_off"<1->v3error("Argument -match only supported for lint_off"); } else { V3Config::addWaiver($1,*$3,*$5); }} @@ -6305,11 +6305,11 @@ vltOffFront: | yVLT_LINT_OFF { $$ = V3ErrorCode::I_LINT; } | yVLT_LINT_OFF yVLT_D_MSG idAny { $$ = V3ErrorCode((*$3).c_str()); - if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: "<<*$3<v3warn(DEPRECATED, "Deprecated -msg in configuration files, use -rule instead."<v3error("Unknown Error Code: " << *$3); } + $2->v3warn(DEPRECATED, "Deprecated -msg in configuration files, use -rule instead."); } | yVLT_LINT_OFF yVLT_D_RULE idAny { $$ = V3ErrorCode((*$3).c_str()); - if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: "<<*$3<v3error("Unknown Error Code: " << *$3); } } ; vltOnFront: @@ -6318,11 +6318,11 @@ vltOnFront: | yVLT_LINT_ON { $$ = V3ErrorCode::I_LINT; } | yVLT_LINT_ON yVLT_D_MSG idAny { $$ = V3ErrorCode((*$3).c_str()); - if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: "<<*$3<v3warn(DEPRECATED, "Deprecated -msg in configuration files, use -rule instead."<v3error("Unknown Error Code: " << *$3); } + $2->v3warn(DEPRECATED, "Deprecated -msg in configuration files, use -rule instead."); } | yVLT_LINT_ON yVLT_D_RULE idAny { $$ = V3ErrorCode((*$3).c_str()); - if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: "<<*$3<v3error("Unknown Error Code: " << *$3); } } ; vltDModuleE: diff --git a/test_regress/t/t_dpi_accessors.cpp b/test_regress/t/t_dpi_accessors.cpp index c5d7152d9..c20c81745 100644 --- a/test_regress/t/t_dpi_accessors.cpp +++ b/test_regress/t/t_dpi_accessors.cpp @@ -69,8 +69,8 @@ int main() { dut->eval(); #ifdef TEST_VERBOSE - cout << "Initial DPI values" << endl; - cout << "==================" << endl; + cout << "Initial DPI values\n"; + cout << "==================\n"; #endif int a = (int)a_read(); @@ -106,8 +106,8 @@ int main() { // Check we can read a scalar register. #ifdef TEST_VERBOSE - cout << "Test of scalar register reading" << endl; - cout << "===============================" << endl; + cout << "Test of scalar register reading\n"; + cout << "===============================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -132,8 +132,8 @@ int main() { // Check we can read a vector register. #ifdef TEST_VERBOSE - cout << "Test of vector register reading" << endl; - cout << "===============================" << endl; + cout << "Test of vector register reading\n"; + cout << "===============================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -156,8 +156,8 @@ int main() { // Test we can read an array element #ifdef TEST_VERBOSE cout << endl; - cout << "Test of array element reading" << endl; - cout << "=============================" << endl; + cout << "Test of array element reading\n"; + cout << "=============================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -180,8 +180,8 @@ int main() { // Check we can read a scalar wire #ifdef TEST_VERBOSE cout << endl; - cout << "Test of scalar wire reading" << endl; - cout << "===========================" << endl; + cout << "Test of scalar wire reading\n"; + cout << "===========================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -209,8 +209,8 @@ int main() { // Check we can read a vector wire #ifdef TEST_VERBOSE cout << endl; - cout << "Test of vector wire reading" << endl; - cout << "===========================" << endl; + cout << "Test of vector wire reading\n"; + cout << "===========================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -239,8 +239,8 @@ int main() { // Check we can write a scalar register #ifdef TEST_VERBOSE cout << endl; - cout << "Test of scalar register writing" << endl; - cout << "===============================" << endl; + cout << "Test of scalar register writing\n"; + cout << "===============================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -268,8 +268,8 @@ int main() { // Check we can write a vector register #ifdef TEST_VERBOSE cout << endl; - cout << "Test of vector register writing" << endl; - cout << "===============================" << endl; + cout << "Test of vector register writing\n"; + cout << "===============================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -297,8 +297,8 @@ int main() { // Test we can write an array element #ifdef TEST_VERBOSE cout << endl; - cout << "Test of array element writing" << endl; - cout << "=============================" << endl; + cout << "Test of array element writing\n"; + cout << "=============================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -326,8 +326,8 @@ int main() { // Check we can read a vector register slice #ifdef TEST_VERBOSE cout << endl; - cout << "Test of vector register slice reading" << endl; - cout << "=====================================" << endl; + cout << "Test of vector register slice reading\n"; + cout << "=====================================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -353,8 +353,8 @@ int main() { // Test we can read an array element slice #ifdef TEST_VERBOSE cout << endl; - cout << "Test of array element slice reading" << endl; - cout << "===================================" << endl; + cout << "Test of array element slice reading\n"; + cout << "===================================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -382,8 +382,8 @@ int main() { // Check we can read a vector wire slice #ifdef TEST_VERBOSE cout << endl; - cout << "Test of vector wire slice reading" << endl; - cout << "=================================" << endl; + cout << "Test of vector wire slice reading\n"; + cout << "=================================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -413,8 +413,8 @@ int main() { // Check we can write a vector register slice #ifdef TEST_VERBOSE cout << endl; - cout << "Test of vector register slice writing" << endl; - cout << "=====================================" << endl; + cout << "Test of vector register slice writing\n"; + cout << "=====================================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -452,8 +452,8 @@ int main() { // Test we can write an array element slice #ifdef TEST_VERBOSE cout << endl; - cout << "Test of array element slice writing" << endl; - cout << "===================================" << endl; + cout << "Test of array element slice writing\n"; + cout << "===================================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -497,8 +497,8 @@ int main() { // Check we can read complex registers #ifdef TEST_VERBOSE cout << endl; - cout << "Test of complex register reading" << endl; - cout << "================================" << endl; + cout << "Test of complex register reading\n"; + cout << "================================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -577,8 +577,8 @@ int main() { // Test we can write a complex register #ifdef TEST_VERBOSE cout << endl; - cout << "Test of complex register writing" << endl; - cout << "================================" << endl; + cout << "Test of complex register writing\n"; + cout << "================================\n"; #endif for (int i = 0; !Verilated::gotFinish() && (i < 4); i++) { @@ -674,7 +674,7 @@ int main() { // Tidy up dut->final(); VL_DO_DANGLING(delete dut, dut); - cout << "*-* All Finished *-*" << endl; + cout << "*-* All Finished *-*\n"; } // Local Variables: From b6ded59c2bfc89722fd37cc9e08284f32485ca8e Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 18 Nov 2020 21:32:16 -0500 Subject: [PATCH 24/91] Internals: Use and enforce class final for ~5% performance boost. --- include/verilated.h | 23 +- include/verilated_cov.cpp | 8 +- include/verilated_cov.h | 2 +- include/verilated_cov_key.h | 2 +- include/verilated_fst_c.h | 4 +- include/verilated_heavy.h | 12 +- include/verilated_imp.h | 12 +- include/verilated_save.h | 8 +- include/verilated_sc.h | 2 +- include/verilated_sym_props.h | 8 +- include/verilated_syms.h | 6 +- include/verilated_threads.h | 8 +- include/verilated_trace.h | 6 +- include/verilated_vcd_c.h | 6 +- include/verilated_vcd_sc.h | 2 +- include/verilated_vpi.cpp | 28 +- include/verilated_vpi.h | 2 +- include/verilatedos.h | 5 +- src/V3Active.cpp | 8 +- src/V3Active.h | 2 +- src/V3ActiveTop.cpp | 2 +- src/V3ActiveTop.h | 2 +- src/V3Assert.cpp | 2 +- src/V3Assert.h | 2 +- src/V3AssertPre.cpp | 2 +- src/V3AssertPre.h | 2 +- src/V3Ast.h | 128 ++--- src/V3AstNodes.cpp | 2 +- src/V3AstNodes.h | 720 +++++++++++++-------------- src/V3Begin.cpp | 6 +- src/V3Begin.h | 2 +- src/V3Branch.cpp | 2 +- src/V3Branch.h | 2 +- src/V3Broken.cpp | 6 +- src/V3Broken.h | 2 +- src/V3CCtors.cpp | 2 +- src/V3CCtors.h | 2 +- src/V3CUse.cpp | 6 +- src/V3CUse.h | 2 +- src/V3Case.cpp | 4 +- src/V3Case.h | 2 +- src/V3Cast.cpp | 2 +- src/V3Cast.h | 2 +- src/V3Cdc.cpp | 14 +- src/V3Cdc.h | 2 +- src/V3Changed.cpp | 6 +- src/V3Changed.h | 2 +- src/V3Class.cpp | 2 +- src/V3Class.h | 2 +- src/V3Clean.cpp | 2 +- src/V3Clean.h | 2 +- src/V3Clock.cpp | 2 +- src/V3Clock.h | 2 +- src/V3Combine.cpp | 8 +- src/V3Combine.h | 2 +- src/V3Config.cpp | 14 +- src/V3Config.h | 2 +- src/V3Const.cpp | 6 +- src/V3Const.h | 2 +- src/V3Coverage.cpp | 2 +- src/V3Coverage.h | 2 +- src/V3CoverageJoin.cpp | 2 +- src/V3CoverageJoin.h | 2 +- src/V3Dead.cpp | 4 +- src/V3Dead.h | 2 +- src/V3Delayed.cpp | 2 +- src/V3Delayed.h | 2 +- src/V3Depth.cpp | 2 +- src/V3Depth.h | 2 +- src/V3DepthBlock.cpp | 2 +- src/V3DepthBlock.h | 2 +- src/V3Descope.cpp | 2 +- src/V3Descope.h | 2 +- src/V3EmitC.cpp | 8 +- src/V3EmitC.h | 2 +- src/V3EmitCBase.h | 4 +- src/V3EmitCInlines.cpp | 2 +- src/V3EmitCMain.cpp | 2 +- src/V3EmitCMain.h | 2 +- src/V3EmitCMake.cpp | 2 +- src/V3EmitCMake.h | 2 +- src/V3EmitCSyms.cpp | 2 +- src/V3EmitMk.cpp | 4 +- src/V3EmitMk.h | 2 +- src/V3EmitV.cpp | 10 +- src/V3EmitV.h | 2 +- src/V3EmitXml.cpp | 6 +- src/V3EmitXml.h | 2 +- src/V3Error.h | 4 +- src/V3Expand.cpp | 2 +- src/V3Expand.h | 2 +- src/V3File.cpp | 8 +- src/V3File.h | 20 +- src/V3FileLine.h | 6 +- src/V3Gate.cpp | 32 +- src/V3Gate.h | 2 +- src/V3GenClk.cpp | 6 +- src/V3GenClk.h | 2 +- src/V3Global.h | 4 +- src/V3Graph.h | 8 +- src/V3GraphAcyc.cpp | 6 +- src/V3GraphAlg.cpp | 14 +- src/V3GraphAlg.h | 2 +- src/V3GraphDfa.cpp | 6 +- src/V3GraphDfa.h | 6 +- src/V3GraphPathChecker.h | 2 +- src/V3GraphStream.h | 4 +- src/V3GraphTest.cpp | 18 +- src/V3Hashed.cpp | 2 +- src/V3Hashed.h | 4 +- src/V3HierBlock.cpp | 2 +- src/V3HierBlock.h | 4 +- src/V3Inline.cpp | 10 +- src/V3Inline.h | 2 +- src/V3Inst.cpp | 8 +- src/V3Inst.h | 2 +- src/V3InstrCount.cpp | 6 +- src/V3InstrCount.h | 2 +- src/V3LangCode.h | 2 +- src/V3LanguageWords.h | 2 +- src/V3Life.cpp | 10 +- src/V3Life.h | 2 +- src/V3LifePost.cpp | 4 +- src/V3LifePost.h | 2 +- src/V3LinkCells.cpp | 8 +- src/V3LinkCells.h | 2 +- src/V3LinkDot.cpp | 24 +- src/V3LinkDot.h | 2 +- src/V3LinkInc.cpp | 2 +- src/V3LinkInc.h | 2 +- src/V3LinkJump.cpp | 2 +- src/V3LinkJump.h | 2 +- src/V3LinkLValue.cpp | 2 +- src/V3LinkLValue.h | 2 +- src/V3LinkLevel.h | 2 +- src/V3LinkParse.cpp | 2 +- src/V3LinkParse.h | 2 +- src/V3LinkResolve.cpp | 4 +- src/V3LinkResolve.h | 2 +- src/V3Localize.cpp | 6 +- src/V3Localize.h | 2 +- src/V3MergeCond.cpp | 6 +- src/V3MergeCond.h | 2 +- src/V3Name.cpp | 2 +- src/V3Name.h | 2 +- src/V3Number.h | 2 +- src/V3Options.cpp | 2 +- src/V3Options.h | 10 +- src/V3Order.cpp | 21 +- src/V3Order.h | 2 +- src/V3OrderGraph.h | 32 +- src/V3Os.h | 2 +- src/V3Param.cpp | 4 +- src/V3Param.h | 2 +- src/V3Parse.h | 2 +- src/V3ParseImp.h | 2 +- src/V3ParseLex.cpp | 2 +- src/V3ParseSym.h | 2 +- src/V3Partition.cpp | 26 +- src/V3Partition.h | 4 +- src/V3PartitionGraph.h | 6 +- src/V3PreLex.h | 4 +- src/V3PreProc.cpp | 8 +- src/V3PreProc.h | 2 +- src/V3PreShell.cpp | 2 +- src/V3PreShell.h | 2 +- src/V3Premit.cpp | 4 +- src/V3Premit.h | 2 +- src/V3ProtectLib.cpp | 2 +- src/V3ProtectLib.h | 2 +- src/V3Reloop.cpp | 2 +- src/V3Reloop.h | 2 +- src/V3Scope.cpp | 4 +- src/V3Scope.h | 2 +- src/V3Scoreboard.cpp | 2 +- src/V3Scoreboard.h | 10 +- src/V3SenTree.h | 4 +- src/V3Simulate.h | 4 +- src/V3Slice.cpp | 2 +- src/V3Slice.h | 2 +- src/V3Split.cpp | 30 +- src/V3Split.h | 2 +- src/V3SplitAs.cpp | 8 +- src/V3SplitAs.h | 2 +- src/V3SplitVar.cpp | 14 +- src/V3SplitVar.h | 2 +- src/V3Stats.cpp | 2 +- src/V3Stats.h | 6 +- src/V3StatsReport.cpp | 2 +- src/V3String.h | 8 +- src/V3Subst.cpp | 10 +- src/V3Subst.h | 2 +- src/V3SymTable.h | 4 +- src/V3TSP.cpp | 4 +- src/V3TSP.h | 2 +- src/V3Table.cpp | 4 +- src/V3Table.h | 2 +- src/V3Task.cpp | 14 +- src/V3Task.h | 2 +- src/V3Trace.cpp | 10 +- src/V3Trace.h | 2 +- src/V3TraceDecl.cpp | 2 +- src/V3TraceDecl.h | 2 +- src/V3Tristate.cpp | 10 +- src/V3Tristate.h | 2 +- src/V3Undriven.cpp | 4 +- src/V3Undriven.h | 2 +- src/V3Unknown.cpp | 2 +- src/V3Unknown.h | 2 +- src/V3Unroll.cpp | 2 +- src/V3Unroll.h | 4 +- src/V3Waiver.h | 2 +- src/V3Width.cpp | 6 +- src/V3Width.h | 2 +- src/V3WidthCommit.h | 4 +- src/V3WidthSel.cpp | 2 +- src/VlcBucket.h | 2 +- src/VlcOptions.h | 2 +- src/VlcPoint.h | 4 +- src/VlcSource.h | 6 +- src/VlcTest.h | 4 +- src/VlcTop.h | 2 +- src/astgen | 4 +- test_regress/t/t_dist_portability.pl | 30 +- 224 files changed, 976 insertions(+), 949 deletions(-) diff --git a/include/verilated.h b/include/verilated.h index 71b2e0c29..fb2ca3671 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -129,7 +129,7 @@ extern vluint32_t VL_THREAD_ID() VL_MT_SAFE; #define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing /// Mutex, wrapped to allow -fthread_safety checks -class VL_CAPABILITY("mutex") VerilatedMutex { +class VL_CAPABILITY("mutex") VerilatedMutex final { private: std::mutex m_mutex; // Mutex public: @@ -155,7 +155,7 @@ public: }; /// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks -class VL_SCOPED_CAPABILITY VerilatedLockGuard { +class VL_SCOPED_CAPABILITY VerilatedLockGuard final { VL_UNCOPYABLE(VerilatedLockGuard); private: @@ -174,14 +174,14 @@ public: #else // !VL_THREADED /// Empty non-threaded mutex to avoid #ifdefs in consuming code -class VerilatedMutex { +class VerilatedMutex final { public: void lock() {} void unlock() {} }; /// Empty non-threaded lock guard to avoid #ifdefs in consuming code -class VerilatedLockGuard { +class VerilatedLockGuard final { VL_UNCOPYABLE(VerilatedLockGuard); public: @@ -194,7 +194,7 @@ public: #endif // VL_THREADED /// Remember the calling thread at construction time, and make sure later calls use same thread -class VerilatedAssertOneThread { +class VerilatedAssertOneThread final { // MEMBERS #if defined(VL_THREADED) && defined(VL_DEBUG) vluint32_t m_threadid; /// Thread that is legal @@ -230,7 +230,7 @@ public: class VerilatedScope; -class VerilatedModule { +class VerilatedModule VL_NOT_FINAL { VL_UNCOPYABLE(VerilatedModule); private: @@ -269,7 +269,8 @@ public: #define VL_CELL(instname, type) ///< Declare a cell, ala SP_CELL /// Declare a module, ala SC_MODULE -#define VL_MODULE(modname) class modname : public VerilatedModule +#define VL_MODULE(modname) class modname VL_NOT_FINAL : public VerilatedModule +// Not class final in VL_MODULE, as users might be abstracting our models (--hierarchical) /// Constructor, ala SC_CTOR #define VL_CTOR(modname) modname(const char* __VCname = "") @@ -298,7 +299,7 @@ public: //=========================================================================== /// Verilator symbol table base class -class VerilatedSyms { +class VerilatedSyms VL_NOT_FINAL { public: // But for internal use only #ifdef VL_THREADED VerilatedEvalMsgQueue* __Vm_evalMsgQp; @@ -311,7 +312,7 @@ public: // But for internal use only /// Verilator global class information class /// This class is initialized by main thread only. Reading post-init is thread safe. -class VerilatedScope { +class VerilatedScope final { public: typedef enum : vluint8_t { SCOPE_MODULE, @@ -359,7 +360,7 @@ public: // But internals only - called from VerilatedModule's Type type() const { return m_type; } }; -class VerilatedHierarchy { +class VerilatedHierarchy final { public: static void add(VerilatedScope* fromp, VerilatedScope* top); }; @@ -367,7 +368,7 @@ public: //=========================================================================== /// Verilator global static information class -class Verilated { +class Verilated final { // MEMBERS // Slow path variables static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED diff --git a/include/verilated_cov.cpp b/include/verilated_cov.cpp index 6d71400df..9db5eacb7 100644 --- a/include/verilated_cov.cpp +++ b/include/verilated_cov.cpp @@ -29,7 +29,7 @@ // VerilatedCovImpBase /// Implementation base class for constants -struct VerilatedCovImpBase { +struct VerilatedCovImpBase VL_NOT_FINAL { // TYPES enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values @@ -39,7 +39,7 @@ struct VerilatedCovImpBase { // VerilatedCovImpItem /// Implementation class for a VerilatedCov item -class VerilatedCovImpItem : VerilatedCovImpBase { +class VerilatedCovImpItem VL_NOT_FINAL : VerilatedCovImpBase { public: // But only local to this file // MEMBERS int m_keys[MAX_KEYS]; ///< Key @@ -63,7 +63,7 @@ public: // But only local to this file /// This isn't in the header file for auto-magic conversion because it /// inlines to too much code and makes compilation too slow. -template class VerilatedCoverItemSpec : public VerilatedCovImpItem { +template class VerilatedCoverItemSpec final : public VerilatedCovImpItem { private: // MEMBERS T* m_countp; ///< Count value @@ -87,7 +87,7 @@ public: /// All value and keys are indexed into a unique number. Thus we can greatly reduce /// the storage requirements for otherwise identical keys. -class VerilatedCovImp : VerilatedCovImpBase { +class VerilatedCovImp final : VerilatedCovImpBase { private: // TYPES typedef std::map ValueIndexMap; diff --git a/include/verilated_cov.h b/include/verilated_cov.h index aef8eda67..331eed6c8 100644 --- a/include/verilated_cov.h +++ b/include/verilated_cov.h @@ -88,7 +88,7 @@ template std::string vlCovCvtToStr(const T& t) VL_PURE { /// Global class with methods affecting all coverage data. /// All public methods in this class are thread safe. -class VerilatedCov { +class VerilatedCov final { VL_UNCOPYABLE(VerilatedCov); public: diff --git a/include/verilated_cov_key.h b/include/verilated_cov_key.h index d4788d435..9a184a518 100644 --- a/include/verilated_cov_key.h +++ b/include/verilated_cov_key.h @@ -102,7 +102,7 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr /// Verilator coverage global class. /// This class is thread safe. -class VerilatedCovKey { +class VerilatedCovKey final { public: static std::string shortKey(const std::string& key) VL_PURE { // VLCOVGEN_SHORT_AUTO_EDIT_BEGIN diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index f4aaf08ec..a4c4a779c 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -35,7 +35,7 @@ /// Base class to create a Verilator FST dump /// This is an internally used class - see VerilatedFstC for what to call from applications -class VerilatedFst : public VerilatedTrace { +class VerilatedFst final : public VerilatedTrace { private: // Give the superclass access to private bits (to avoid virtual functions) friend class VerilatedTrace; @@ -128,7 +128,7 @@ template <> void VerilatedTrace::set_time_resolution(const std::st /// Also derived for use in SystemC simulations. /// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE -class VerilatedFstC { +class VerilatedFstC final { VerilatedFst m_sptrace; ///< Trace file being created // CONSTRUCTORS diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 933a3a6a2..3346cd2be 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -46,7 +46,7 @@ extern std::string VL_TO_STRING_W(int words, WDataInP obj); //=================================================================== // Shuffle RNG -class VlURNG { +class VlURNG final { public: typedef size_t result_type; static constexpr size_t min() { return 0; } @@ -57,7 +57,7 @@ public: //=================================================================== // Readmem/Writemem operation classes -class VlReadMem { +class VlReadMem final { bool m_hex; // Hex format int m_bits; // Bit width of values const std::string& m_filename; // Filename @@ -74,7 +74,7 @@ public: void setData(void* valuep, const std::string& rhs); }; -class VlWriteMem { +class VlWriteMem final { bool m_hex; // Hex format int m_bits; // Bit width of values FILE* m_fp; // File handle for filename @@ -93,7 +93,7 @@ public: // // Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound // For dynamic arrays it is always zero -template class VlQueue { +template class VlQueue final { private: // TYPES typedef std::deque Deque; @@ -424,7 +424,7 @@ template std::string VL_TO_STRING(const VlQueue& obj) { // This is only used when we need an upper-level container and so can't // simply use a C style array (which is just a pointer). -template class VlWide { +template class VlWide final { WData m_storage[T_Words]; public: @@ -460,7 +460,7 @@ template std::string VL_TO_STRING(const VlWide& o // There are no multithreaded locks on this; the base variable must // be protected by other means // -template class VlAssocArray { +template class VlAssocArray final { private: // TYPES typedef std::map Map; diff --git a/include/verilated_imp.h b/include/verilated_imp.h index 1b92f4798..ba0993570 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -46,7 +46,7 @@ class VerilatedScope; #ifdef VL_THREADED /// Message, enqueued on an mtask, and consumed on the main eval thread -class VerilatedMsg { +class VerilatedMsg final { public: // TYPES struct Cmp { @@ -78,7 +78,7 @@ public: /// Each thread has a queue it pushes to /// This assumes no thread starts pushing the next tick until the previous has drained. /// If more aggressiveness is needed, a double-buffered scheme might work well. -class VerilatedEvalMsgQueue { +class VerilatedEvalMsgQueue final { typedef std::multiset VerilatedThreadQueue; std::atomic m_depth; ///< Current depth of queue (see comments below) @@ -130,7 +130,7 @@ public: }; /// Each thread has a local queue to build up messages until the end of the eval() call -class VerilatedThreadMsgQueue { +class VerilatedThreadMsgQueue final { std::queue m_queue; public: @@ -174,7 +174,7 @@ public: #endif // VL_THREADED // FILE* list constructed from a file-descriptor -class VerilatedFpList { +class VerilatedFpList final { FILE* m_fp[31]; std::size_t m_sz = 0; @@ -193,7 +193,7 @@ public: //====================================================================== // VerilatedImp -class VerilatedImpData { +class VerilatedImpData final { // Whole class is internal use only - Global information shared between verilated*.cpp files. protected: friend class Verilated; @@ -264,7 +264,7 @@ protected: } }; -class VerilatedImp { +class VerilatedImp final { // Whole class is internal use only - Global information shared between verilated*.cpp files. protected: friend class Verilated; diff --git a/include/verilated_save.h b/include/verilated_save.h index 5729591d9..ca12c57ca 100644 --- a/include/verilated_save.h +++ b/include/verilated_save.h @@ -28,7 +28,7 @@ // VerilatedSerialize - convert structures to a stream representation // This class is not thread safe, it must be called by a single thread -class VerilatedSerialize { +class VerilatedSerialize VL_NOT_FINAL { protected: // MEMBERS // For speed, keep m_cp as the first member of this structure @@ -87,7 +87,7 @@ private: // VerilatedDeserial - load structures from a stream representation // This class is not thread safe, it must be called by a single thread -class VerilatedDeserialize { +class VerilatedDeserialize VL_NOT_FINAL { protected: // MEMBERS // For speed, keep m_cp as the first member of this structure @@ -154,7 +154,7 @@ private: // VerilatedSave - serialize to a file // This class is not thread safe, it must be called by a single thread -class VerilatedSave : public VerilatedSerialize { +class VerilatedSave final : public VerilatedSerialize { private: int m_fd = -1; ///< File descriptor we're writing to @@ -174,7 +174,7 @@ public: // VerilatedRestore - deserialize from a file // This class is not thread safe, it must be called by a single thread -class VerilatedRestore : public VerilatedDeserialize { +class VerilatedRestore final : public VerilatedDeserialize { private: int m_fd = -1; ///< File descriptor we're writing to diff --git a/include/verilated_sc.h b/include/verilated_sc.h index b250d224b..a807b8302 100644 --- a/include/verilated_sc.h +++ b/include/verilated_sc.h @@ -34,7 +34,7 @@ // This class is thread safe (though most of SystemC is not). #define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv)) -class VlScBvExposer : public sc_bv_base { +class VlScBvExposer final : public sc_bv_base { public: static const vluint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE { return static_cast(&base)->sp_datatp(); diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h index 9419e3309..2df07855e 100644 --- a/include/verilated_sym_props.h +++ b/include/verilated_sym_props.h @@ -36,7 +36,7 @@ /// Thread safety: Assume is constructed only with model, then any number of readers // See also V3Ast::VNumRange -class VerilatedRange { +class VerilatedRange final { int m_left = 0; int m_right = 0; @@ -68,7 +68,7 @@ public: /// Verilator variable /// Thread safety: Assume is constructed only with model, then any number of readers -class VerilatedVarProps { +class VerilatedVarProps VL_NOT_FINAL { // TYPES enum { MAGIC = 0xddc4f829 }; // MEMBERS @@ -187,7 +187,7 @@ public: //=========================================================================== /// Verilator DPI open array variable -class VerilatedDpiOpenVar { +class VerilatedDpiOpenVar final { // MEMBERS const VerilatedVarProps* m_propsp; // Variable properties void* m_datap; // Location of data (local to thread always, so safe) @@ -225,7 +225,7 @@ public: /// Verilator variable /// Thread safety: Assume is constructed only with model, then any number of readers -class VerilatedVar : public VerilatedVarProps { +class VerilatedVar final : public VerilatedVarProps { // MEMBERS void* m_datap; // Location of data const char* m_namep; // Name - slowpath diff --git a/include/verilated_syms.h b/include/verilated_syms.h index 2a643b341..c8f8514fc 100644 --- a/include/verilated_syms.h +++ b/include/verilated_syms.h @@ -42,7 +42,7 @@ struct VerilatedCStrCmp { }; /// Map of sorted scope names to find associated scope class -class VerilatedScopeNameMap +class VerilatedScopeNameMap final : public std::map { public: VerilatedScopeNameMap() = default; @@ -50,7 +50,7 @@ public: }; /// Map of sorted variable names to find associated variable class -class VerilatedVarNameMap : public std::map { +class VerilatedVarNameMap final : public std::map { public: VerilatedVarNameMap() = default; ~VerilatedVarNameMap() = default; @@ -58,7 +58,7 @@ public: typedef std::vector VerilatedScopeVector; -class VerilatedHierarchyMap : public std::map { +class VerilatedHierarchyMap final : public std::map { public: VerilatedHierarchyMap() = default; ~VerilatedHierarchyMap() = default; diff --git a/include/verilated_threads.h b/include/verilated_threads.h index 1592b2eaf..4b6678c92 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -52,7 +52,7 @@ typedef void* VlThrSymTab; typedef void (*VlExecFnp)(bool, VlThrSymTab); /// Track dependencies for a single MTask. -class VlMTaskVertex { +class VlMTaskVertex final { // MEMBERS static std::atomic s_yields; // Statistics @@ -124,7 +124,7 @@ public: }; // Profiling support -class VlProfileRec { +class VlProfileRec final { protected: friend class VlThreadPool; enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER }; @@ -168,7 +168,7 @@ public: class VlThreadPool; -class VlWorkerThread { +class VlWorkerThread final { private: // TYPES struct ExecRec { @@ -247,7 +247,7 @@ public: static void startWorker(VlWorkerThread* workerp); }; -class VlThreadPool { +class VlThreadPool final { // TYPES typedef std::vector ProfileTrace; typedef std::set ProfileSet; diff --git a/include/verilated_trace.h b/include/verilated_trace.h index adffb68c3..bb4bc68b9 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -40,7 +40,7 @@ // Threaded tracing // A simple synchronized first in first out queue -template class VerilatedThreadQueue { // LCOV_EXCL_LINE // lcov bug +template class VerilatedThreadQueue final { // LCOV_EXCL_LINE // lcov bug private: VerilatedMutex m_mutex; // Protects m_queue std::condition_variable_any m_cv; @@ -83,7 +83,7 @@ public: // Commands used by thread tracing. Anonymous enum in class, as we want // it scoped, but we also want the automatic conversion to integer types. -class VerilatedTraceCommand { +class VerilatedTraceCommand final { public: // These must all fit in 4 bit at the moment, as the tracing routines // pack parameters in the top bits. @@ -110,7 +110,7 @@ public: // VerilatedTrace uses F-bounded polymorphism to access duck-typed // implementations in the format specific derived class, which must be passed // as the type parameter T_Derived -template class VerilatedTrace { +template class VerilatedTrace VL_NOT_FINAL { public: //========================================================================= // Generic tracing internals diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index 1bc9080a3..8424bd6e6 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -34,7 +34,7 @@ class VerilatedVcd; // VerilatedFile /// File handling routines, which can be overrode for e.g. socket I/O -class VerilatedVcdFile { +class VerilatedVcdFile final { private: int m_fd = 0; ///< File descriptor we're writing to public: @@ -51,7 +51,7 @@ public: /// Base class to create a Verilator VCD dump /// This is an internally used class - see VerilatedVcdC for what to call from applications -class VerilatedVcd : public VerilatedTrace { +class VerilatedVcd VL_NOT_FINAL : public VerilatedTrace { private: // Give the superclass access to private bits (to avoid virtual functions) friend class VerilatedTrace; @@ -329,7 +329,7 @@ template <> void VerilatedTrace::set_time_resolution(const std::st /// Also derived for use in SystemC simulations. /// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE -class VerilatedVcdC { +class VerilatedVcdC VL_NOT_FINAL { VerilatedVcd m_sptrace; ///< Trace file being created // CONSTRUCTORS diff --git a/include/verilated_vcd_sc.h b/include/verilated_vcd_sc.h index 15d0aae61..2836879c1 100644 --- a/include/verilated_vcd_sc.h +++ b/include/verilated_vcd_sc.h @@ -31,7 +31,7 @@ /// This class is passed to the SystemC simulation kernel, just like a /// documented SystemC trace format. -class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC { +class VerilatedVcdSc final : sc_trace_file, public VerilatedVcdC { // CONSTRUCTORS VL_UNCOPYABLE(VerilatedVcdSc); diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index e9a64241a..3f0b34218 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -55,7 +55,7 @@ constexpr unsigned VL_VPI_LINE_SIZE = 8192; // Implementation // Base VPI handled object -class VerilatedVpio { +class VerilatedVpio VL_NOT_FINAL { // MEM MANGLEMENT static VL_THREAD_LOCAL vluint8_t* t_freeHead; @@ -101,7 +101,7 @@ public: typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data*); -class VerilatedVpioCb : public VerilatedVpio { +class VerilatedVpioCb final : public VerilatedVpio { t_cb_data m_cbData; s_vpi_value m_value; QData m_time; @@ -125,7 +125,7 @@ public: QData time() const { return m_time; } }; -class VerilatedVpioConst : public VerilatedVpio { +class VerilatedVpioConst final : public VerilatedVpio { vlsint32_t m_num; public: @@ -139,7 +139,7 @@ public: vlsint32_t num() const { return m_num; } }; -class VerilatedVpioParam : public VerilatedVpio { +class VerilatedVpioParam final : public VerilatedVpio { const VerilatedVar* m_varp; const VerilatedScope* m_scopep; @@ -165,7 +165,7 @@ public: } }; -class VerilatedVpioRange : public VerilatedVpio { +class VerilatedVpioRange final : public VerilatedVpio { const VerilatedRange* m_range; vlsint32_t m_iteration = 0; @@ -191,7 +191,7 @@ public: } }; -class VerilatedVpioScope : public VerilatedVpio { +class VerilatedVpioScope VL_NOT_FINAL : public VerilatedVpio { protected: const VerilatedScope* m_scopep; @@ -208,7 +208,7 @@ public: virtual const char* fullname() const override { return m_scopep->name(); } }; -class VerilatedVpioVar : public VerilatedVpio { +class VerilatedVpioVar VL_NOT_FINAL : public VerilatedVpio { const VerilatedVar* m_varp; const VerilatedScope* m_scopep; vluint8_t* m_prevDatap = nullptr; // Previous value of data, for cbValueChange @@ -266,7 +266,7 @@ public: } }; -class VerilatedVpioMemoryWord : public VerilatedVpioVar { +class VerilatedVpioMemoryWord final : public VerilatedVpioVar { public: VerilatedVpioMemoryWord(const VerilatedVar* varp, const VerilatedScope* scopep, vlsint32_t index, int offset) @@ -290,7 +290,7 @@ public: } }; -class VerilatedVpioVarIter : public VerilatedVpio { +class VerilatedVpioVarIter final : public VerilatedVpio { const VerilatedScope* m_scopep; VerilatedVarNameMap::const_iterator m_it; bool m_started = false; @@ -321,7 +321,7 @@ public: } }; -class VerilatedVpioMemoryWordIter : public VerilatedVpio { +class VerilatedVpioMemoryWordIter final : public VerilatedVpio { const vpiHandle m_handle; const VerilatedVar* m_varp; vlsint32_t m_iteration; @@ -351,7 +351,7 @@ public: } }; -class VerilatedVpioModule : public VerilatedVpioScope { +class VerilatedVpioModule final : public VerilatedVpioScope { const char* m_name; const char* m_fullname; @@ -370,7 +370,7 @@ public: virtual const char* fullname() const override { return m_fullname; } }; -class VerilatedVpioModuleIter : public VerilatedVpio { +class VerilatedVpioModuleIter final : public VerilatedVpio { const std::vector* m_vec; std::vector::const_iterator m_it; @@ -405,7 +405,7 @@ struct VerilatedVpiTimedCbsCmp { class VerilatedVpiError; -class VerilatedVpiImp { +class VerilatedVpiImp final { enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime + 1 }; // Maxium callback reason typedef std::list VpioCbList; typedef std::set, VerilatedVpiTimedCbsCmp> VpioTimedCbs; @@ -534,7 +534,7 @@ public: static VerilatedVpiError* error_info() VL_MT_UNSAFE_ONE; // getter for vpi error info }; -class VerilatedVpiError { +class VerilatedVpiError final { //// Container for vpi error info t_vpi_error_info m_errorInfo; diff --git a/include/verilated_vpi.h b/include/verilated_vpi.h index 4ecfc55ca..eebb3736b 100644 --- a/include/verilated_vpi.h +++ b/include/verilated_vpi.h @@ -33,7 +33,7 @@ //====================================================================== -class VerilatedVpi { +class VerilatedVpi final { public: /// Call timed callbacks /// Users should call this from their main loops diff --git a/include/verilatedos.h b/include/verilatedos.h index 7ba4ff55c..abe297843 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -374,7 +374,10 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type //========================================================================= // Class definition helpers -// Used to declare a class as uncopyable; put after a private: +/// Used to indicate a base class, e.g. cannot label "class final" +#define VL_NOT_FINAL + +/// Used to declare a class as uncopyable; put after a private: #define VL_UNCOPYABLE(Type) \ Type(const Type& other) = delete; \ Type& operator=(const Type&) = delete diff --git a/src/V3Active.cpp b/src/V3Active.cpp index dae137c95..c2ab0f7cd 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -43,12 +43,12 @@ //###################################################################### // Collect existing active names -class ActiveBaseVisitor : public AstNVisitor { +class ActiveBaseVisitor VL_NOT_FINAL : public AstNVisitor { protected: VL_DEBUG_FUNC; // Declare debug() }; -class ActiveNamer : public ActiveBaseVisitor { +class ActiveNamer final : public ActiveBaseVisitor { private: // STATE AstScope* m_scopep = nullptr; // Current scope to add statement to @@ -138,7 +138,7 @@ public: //###################################################################### // Active AssignDly replacement functions -class ActiveDlyVisitor : public ActiveBaseVisitor { +class ActiveDlyVisitor final : public ActiveBaseVisitor { public: enum CheckType : uint8_t { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH }; @@ -211,7 +211,7 @@ public: //###################################################################### // Active class functions -class ActiveVisitor : public ActiveBaseVisitor { +class ActiveVisitor final : public ActiveBaseVisitor { private: // NODE STATE // Each call to V3Const::constify diff --git a/src/V3Active.h b/src/V3Active.h index cc0629e0b..79fff9303 100644 --- a/src/V3Active.h +++ b/src/V3Active.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Active { +class V3Active final { public: static void activeAll(AstNetlist* nodep); }; diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index 72d2f0580..3982acb29 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -35,7 +35,7 @@ //###################################################################### // Active class functions -class ActiveTopVisitor : public AstNVisitor { +class ActiveTopVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist diff --git a/src/V3ActiveTop.h b/src/V3ActiveTop.h index 27a7b18d1..9bc677ff8 100644 --- a/src/V3ActiveTop.h +++ b/src/V3ActiveTop.h @@ -25,7 +25,7 @@ //============================================================================ -class V3ActiveTop { +class V3ActiveTop final { public: static void activeTopAll(AstNetlist* nodep); }; diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 981d705ae..dea371906 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -26,7 +26,7 @@ //###################################################################### // Assert class functions -class AssertVisitor : public AstNVisitor { +class AssertVisitor final : public AstNVisitor { private: // NODE STATE/TYPES // Cleared on netlist diff --git a/src/V3Assert.h b/src/V3Assert.h index d72625aba..934a2032d 100644 --- a/src/V3Assert.h +++ b/src/V3Assert.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Assert { +class V3Assert final { public: static void assertAll(AstNetlist* nodep); }; diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 0c288ea8f..59a89461a 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -26,7 +26,7 @@ //###################################################################### // Assert class functions -class AssertPreVisitor : public AstNVisitor { +class AssertPreVisitor final : public AstNVisitor { // Removes clocks and other pre-optimizations // Eventually inlines calls to sequences, properties, etc. // We're not parsing the tree, or anything more complicated. diff --git a/src/V3AssertPre.h b/src/V3AssertPre.h index 41eceb57c..862756748 100644 --- a/src/V3AssertPre.h +++ b/src/V3AssertPre.h @@ -25,7 +25,7 @@ //============================================================================ -class V3AssertPre { +class V3AssertPre final { public: static void assertPreAll(AstNetlist* nodep); }; diff --git a/src/V3Ast.h b/src/V3Ast.h index d086a4def..5326f1515 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -71,7 +71,7 @@ typedef std::set MTaskIdSet; // Set of mtaskIds for Var sorting //###################################################################### -class AstType { +class AstType final { public: #include "V3Ast__gen_types.h" // From ./astgen // Above include has: @@ -94,7 +94,7 @@ inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return o //###################################################################### -class VLifetime { +class VLifetime final { public: enum en : uint8_t { NONE, AUTOMATIC, STATIC }; enum en m_e; @@ -123,7 +123,7 @@ inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) { //###################################################################### -class VAccess { +class VAccess final { public: enum en : uint8_t { READ, // Read/Consumed, variable not changed @@ -166,7 +166,7 @@ inline std::ostream& operator<<(std::ostream& os, const VAccess& rhs) { return o //###################################################################### -class VSigning { +class VSigning final { public: enum en : uint8_t { UNSIGNED, @@ -203,7 +203,7 @@ inline std::ostream& operator<<(std::ostream& os, const VSigning& rhs) { //###################################################################### -class AstPragmaType { +class AstPragmaType final { public: enum en : uint8_t { ILLEGAL, @@ -236,7 +236,7 @@ inline bool operator==(AstPragmaType::en lhs, const AstPragmaType& rhs) { return //###################################################################### -class AstCFuncType { +class AstCFuncType final { public: enum en : uint8_t { FT_NORMAL, @@ -269,7 +269,7 @@ inline bool operator==(AstCFuncType::en lhs, const AstCFuncType& rhs) { return l //###################################################################### -class VEdgeType { +class VEdgeType final { public: // REMEMBER to edit the strings below too enum en : uint8_t { @@ -355,7 +355,7 @@ inline bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs == //###################################################################### -class AstAttrType { +class AstAttrType final { public: // clang-format off enum en: uint8_t { @@ -436,7 +436,7 @@ inline bool operator==(AstAttrType::en lhs, const AstAttrType& rhs) { return lhs //###################################################################### -class AstBasicDTypeKwd { +class AstBasicDTypeKwd final { public: enum en : uint8_t { UNKNOWN, @@ -572,7 +572,7 @@ inline bool operator==(AstBasicDTypeKwd::en lhs, const AstBasicDTypeKwd& rhs) { //###################################################################### -class VDirection { +class VDirection final { public: enum en : uint8_t { NONE, INPUT, OUTPUT, INOUT, REF, CONSTREF }; enum en m_e; @@ -617,7 +617,7 @@ inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) { //###################################################################### /// Boolean or unknown -class VBoolOrUnknown { +class VBoolOrUnknown final { public: enum en : uint8_t { BU_FALSE = 0, BU_TRUE = 1, BU_UNKNOWN = 2, _ENUM_END }; enum en m_e; @@ -656,7 +656,7 @@ inline std::ostream& operator<<(std::ostream& os, const VBoolOrUnknown& rhs) { //###################################################################### /// Join type -class VJoinType { +class VJoinType final { public: enum en : uint8_t { JOIN = 0, JOIN_ANY = 1, JOIN_NONE = 2 }; enum en m_e; @@ -689,7 +689,7 @@ inline std::ostream& operator<<(std::ostream& os, const VJoinType& rhs) { //###################################################################### -class AstVarType { +class AstVarType final { public: enum en : uint8_t { UNKNOWN, @@ -757,7 +757,7 @@ inline std::ostream& operator<<(std::ostream& os, const AstVarType& rhs) { //###################################################################### -class VBranchPred { +class VBranchPred final { public: enum en : uint8_t { BP_UNKNOWN = 0, BP_LIKELY, BP_UNLIKELY, _ENUM_END }; enum en m_e; @@ -798,7 +798,7 @@ inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) { //###################################################################### -class VVarAttrClocker { +class VVarAttrClocker final { public: enum en : uint8_t { CLOCKER_UNKNOWN = 0, CLOCKER_YES, CLOCKER_NO, _ENUM_END }; enum en m_e; @@ -841,7 +841,7 @@ inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) { //###################################################################### -class VAlwaysKwd { +class VAlwaysKwd final { public: enum en : uint8_t { ALWAYS, ALWAYS_FF, ALWAYS_LATCH, ALWAYS_COMB }; enum en m_e; @@ -864,7 +864,7 @@ inline bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs = //###################################################################### -class VCaseType { +class VCaseType final { public: enum en : uint8_t { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE }; enum en m_e; @@ -883,7 +883,7 @@ inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == //###################################################################### -class AstDisplayType { +class AstDisplayType final { public: enum en : uint8_t { DT_DISPLAY, DT_WRITE, DT_INFO, DT_ERROR, DT_WARNING, DT_FATAL }; enum en m_e; @@ -915,7 +915,7 @@ inline bool operator==(AstDisplayType::en lhs, const AstDisplayType& rhs) { //###################################################################### -class VDumpCtlType { +class VDumpCtlType final { public: enum en : uint8_t { FILE, VARS, ALL, FLUSH, LIMIT, OFF, ON }; enum en m_e; @@ -941,7 +941,7 @@ inline bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return l //###################################################################### -class VParseRefExp { +class VParseRefExp final { public: enum en : uint8_t { PX_NONE, // Used in V3LinkParse only @@ -975,7 +975,7 @@ inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) { // VNumRange - Structure containing numeric range information // See also AstRange, which is a symbolic version of this -class VNumRange { +class VNumRange final { public: int m_hi = 0; // HI part, HI always >= LO int m_lo = 0; // LO @@ -1048,7 +1048,7 @@ inline std::ostream& operator<<(std::ostream& os, const VNumRange& rhs) { //###################################################################### -class VUseType { +class VUseType final { public: enum en : uint8_t { IMP_INCLUDE, // Implementation (.cpp) needs an include @@ -1081,7 +1081,7 @@ inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) { //###################################################################### -class VBasicTypeKey { +class VBasicTypeKey final { public: int m_width; // From AstNodeDType: Bit width of operation int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation @@ -1123,7 +1123,7 @@ class WidthVP; class V3GraphVertex; class VSymEnt; -class VNUser { +class VNUser final { union { void* up; int ui; @@ -1159,7 +1159,7 @@ public: // user2. When the member goes out of scope it will be automagically // freed up. -class AstUserInUseBase { +class AstUserInUseBase VL_NOT_FINAL { protected: static void allocate(int id, uint32_t& cntGblRef, bool& userBusyRef) { // Perhaps there's still a AstUserInUse in scope for this? @@ -1190,7 +1190,7 @@ protected: // We let AstNode peek into here, because when under low optimization even // an accessor would be way too slow. // clang-format off -class AstUser1InUse : AstUserInUseBase { +class AstUser1InUse final : AstUserInUseBase { protected: friend class AstNode; static uint32_t s_userCntGbl; // Count of which usage of userp() this is @@ -1201,7 +1201,7 @@ public: static void clear() { clearcnt(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } static void check() { checkcnt(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } }; -class AstUser2InUse : AstUserInUseBase { +class AstUser2InUse final : AstUserInUseBase { protected: friend class AstNode; static uint32_t s_userCntGbl; // Count of which usage of userp() this is @@ -1212,7 +1212,7 @@ public: static void clear() { clearcnt(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } static void check() { checkcnt(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } }; -class AstUser3InUse : AstUserInUseBase { +class AstUser3InUse final : AstUserInUseBase { protected: friend class AstNode; static uint32_t s_userCntGbl; // Count of which usage of userp() this is @@ -1223,7 +1223,7 @@ public: static void clear() { clearcnt(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } static void check() { checkcnt(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } }; -class AstUser4InUse : AstUserInUseBase { +class AstUser4InUse final : AstUserInUseBase { protected: friend class AstNode; static uint32_t s_userCntGbl; // Count of which usage of userp() this is @@ -1234,7 +1234,7 @@ public: static void clear() { clearcnt(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } static void check() { checkcnt(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } }; -class AstUser5InUse : AstUserInUseBase { +class AstUser5InUse final : AstUserInUseBase { protected: friend class AstNode; static uint32_t s_userCntGbl; // Count of which usage of userp() this is @@ -1251,7 +1251,7 @@ public: // AstNVisitor -- Allows new functions to be called on each node // type without changing the base classes. See "Modern C++ Design". -class AstNVisitor { +class AstNVisitor VL_NOT_FINAL { private: // MEMBERS std::vector m_deleteps; // Nodes to delete when doDeletes() called @@ -1298,7 +1298,7 @@ public: // AstNRelinker -- Holds the state of a unlink so a new node can be // added at the same point. -class AstNRelinker { +class AstNRelinker final { protected: friend class AstNode; enum RelinkWhatEn : uint8_t { @@ -1328,7 +1328,7 @@ inline std::ostream& operator<<(std::ostream& os, const AstNRelinker& rhs) { //###################################################################### // V3Hash -- Node hashing for V3Combine -class V3Hash { +class V3Hash final { // A hash of a tree of nodes, consisting of 8 bits with the number of nodes in the hash // and 24 bit value hash of relevant information about the node. // A value of 0 is illegal @@ -1381,7 +1381,7 @@ std::ostream& operator<<(std::ostream& os, const V3Hash& rhs); //###################################################################### // Callback base class to determine if node matches some formula -class VNodeMatcher { +class VNodeMatcher VL_NOT_FINAL { public: virtual bool nodeMatch(const AstNode* nodep) const { return true; } }; @@ -1399,7 +1399,7 @@ public: } \ } while (false) -class AstNode { +class AstNode VL_NOT_FINAL { // v ASTNODE_PREFETCH depends on below ordering of members AstNode* m_nextp; // Next peer in the parent's list AstNode* m_backp; // Node that points to this one (via next/op1/op2/...) @@ -1914,7 +1914,7 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); } } \ Ast##name* clonep() const { return static_cast(AstNode::clonep()); } -class AstNodeMath : public AstNode { +class AstNodeMath VL_NOT_FINAL : public AstNode { // Math -- anything that's part of an expression tree public: AstNodeMath(AstType t, FileLine* fl) @@ -1934,7 +1934,7 @@ public: bool isOpaque() { return VN_IS(this, CvtPackString); } }; -class AstNodeTermop : public AstNodeMath { +class AstNodeTermop VL_NOT_FINAL : public AstNodeMath { // Terminal operator -- a operator with no "inputs" public: AstNodeTermop(AstType t, FileLine* fl) @@ -1947,7 +1947,7 @@ public: virtual void dump(std::ostream& str) const override; }; -class AstNodeUniop : public AstNodeMath { +class AstNodeUniop VL_NOT_FINAL : public AstNodeMath { // Unary math public: AstNodeUniop(AstType t, FileLine* fl, AstNode* lhsp) @@ -1973,7 +1973,7 @@ public: virtual bool same(const AstNode*) const override { return true; } }; -class AstNodeBiop : public AstNodeMath { +class AstNodeBiop VL_NOT_FINAL : public AstNodeMath { // Binary math public: AstNodeBiop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs) @@ -2005,7 +2005,7 @@ public: virtual bool same(const AstNode*) const override { return true; } }; -class AstNodeTriop : public AstNodeMath { +class AstNodeTriop VL_NOT_FINAL : public AstNodeMath { // Trinary math public: AstNodeTriop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) @@ -2038,7 +2038,7 @@ public: virtual bool same(const AstNode*) const override { return true; } }; -class AstNodeQuadop : public AstNodeMath { +class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath { // Quaternary math public: AstNodeQuadop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths, AstNode* fhs) @@ -2075,7 +2075,7 @@ public: virtual bool same(const AstNode*) const override { return true; } }; -class AstNodeBiCom : public AstNodeBiop { +class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop { // Binary math with commutative properties public: AstNodeBiCom(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs) @@ -2083,14 +2083,14 @@ public: ASTNODE_BASE_FUNCS(NodeBiCom) }; -class AstNodeBiComAsv : public AstNodeBiCom { +class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom { // Binary math with commutative & associative properties public: AstNodeBiComAsv(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs) : AstNodeBiCom{t, fl, lhs, rhs} {} ASTNODE_BASE_FUNCS(NodeBiComAsv) }; -class AstNodeCond : public AstNodeTriop { +class AstNodeCond VL_NOT_FINAL : public AstNodeTriop { public: AstNodeCond(AstType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : AstNodeTriop{t, fl, condp, expr1p, expr2p} { @@ -2121,7 +2121,7 @@ public: virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0; }; -class AstNodeBlock : public AstNode { +class AstNodeBlock VL_NOT_FINAL : public AstNode { // A Begin/fork block // Parents: statement // Children: statements @@ -2145,7 +2145,7 @@ public: bool unnamed() const { return m_unnamed; } }; -class AstNodePreSel : public AstNode { +class AstNodePreSel VL_NOT_FINAL : public AstNode { // Something that becomes an AstSel public: AstNodePreSel(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) @@ -2169,7 +2169,7 @@ public: virtual bool same(const AstNode*) const override { return true; } }; -class AstNodeProcedure : public AstNode { +class AstNodeProcedure VL_NOT_FINAL : public AstNode { // IEEE procedure: initial, final, always public: AstNodeProcedure(AstType t, FileLine* fl, AstNode* bodysp) @@ -2184,7 +2184,7 @@ public: bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } }; -class AstNodeStmt : public AstNode { +class AstNodeStmt VL_NOT_FINAL : public AstNode { // Statement -- anything that's directly under a function bool m_statement; // Really a statement (e.g. not a function with return) public: @@ -2202,7 +2202,7 @@ public: virtual void dump(std::ostream& str = std::cout) const override; }; -class AstNodeAssign : public AstNodeStmt { +class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt { public: AstNodeAssign(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeStmt{t, fl} { @@ -2227,7 +2227,7 @@ public: virtual bool brokeLhsMustBeLvalue() const = 0; }; -class AstNodeFor : public AstNodeStmt { +class AstNodeFor VL_NOT_FINAL : public AstNodeStmt { public: AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) @@ -2248,7 +2248,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstNodeIf : public AstNodeStmt { +class AstNodeIf VL_NOT_FINAL : public AstNodeStmt { private: VBranchPred m_branchPred; // Branch prediction as taken/untaken? public: @@ -2274,7 +2274,7 @@ public: VBranchPred branchPred() const { return m_branchPred; } }; -class AstNodeCase : public AstNodeStmt { +class AstNodeCase VL_NOT_FINAL : public AstNodeStmt { public: AstNodeCase(AstType t, FileLine* fl, AstNode* exprp, AstNode* casesp) : AstNodeStmt{t, fl} { @@ -2292,7 +2292,7 @@ public: void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } }; -class AstNodeVarRef : public AstNodeMath { +class AstNodeVarRef VL_NOT_FINAL : public AstNodeMath { // An AstVarRef or AstVarXRef private: VAccess m_access; // Left hand side assignment @@ -2344,7 +2344,7 @@ public: void iterateChildren(AstNVisitor& v) {} }; -class AstNodeText : public AstNode { +class AstNodeText VL_NOT_FINAL : public AstNode { private: string m_text; @@ -2364,7 +2364,7 @@ public: const string& text() const { return m_text; } }; -class AstNodeDType : public AstNode { +class AstNodeDType VL_NOT_FINAL : public AstNode { // Ideally width() would migrate to BasicDType as that's where it makes sense, // but it's currently so prevalent in the code we leave it here. // Note the below members are included in AstTypeTable::Key lookups @@ -2460,7 +2460,7 @@ private: CTypeRecursed cTypeRecurse(bool compound) const; }; -class AstNodeUOrStructDType : public AstNodeDType { +class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType { // A struct or union; common handling private: // TYPES @@ -2524,7 +2524,7 @@ public: VNumRange declRange() const { return VNumRange(msb(), lsb(), false); } }; -class AstNodeArrayDType : public AstNodeDType { +class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType { // Array data type, ie "some_dtype var_name [2:0]" // Children: DTYPE (moved to refDTypep() in V3Width) // Children: RANGE (array bounds) @@ -2587,7 +2587,7 @@ public: VNumRange declRange() const; }; -class AstNodeSel : public AstNodeBiop { +class AstNodeSel VL_NOT_FINAL : public AstNodeBiop { // Single bit range extraction, perhaps with non-constant selection or array selection public: AstNodeSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* bitp) @@ -2603,7 +2603,7 @@ public: virtual bool hasDType() const override { return true; } }; -class AstNodeStream : public AstNodeBiop { +class AstNodeStream VL_NOT_FINAL : public AstNodeBiop { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() public: AstNodeStream(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -2616,7 +2616,7 @@ public: //###################################################################### // Tasks/functions common handling -class AstNodeCCall : public AstNodeStmt { +class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt { // A call of a C++ function, perhaps a AstCFunc or perhaps globally named // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. AstCFunc* m_funcp; @@ -2664,7 +2664,7 @@ public: void addArgsp(AstNode* nodep) { addOp2p(nodep); } }; -class AstNodeFTask : public AstNode { +class AstNodeFTask VL_NOT_FINAL : public AstNode { private: string m_name; // Name of task string m_cname; // Name of task if DPI import @@ -2769,7 +2769,7 @@ public: VLifetime lifetime() const { return m_lifetime; } }; -class AstNodeFTaskRef : public AstNodeStmt { +class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt { // A reference to a task (or function) // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. private: @@ -2823,7 +2823,7 @@ public: void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } }; -class AstNodeModule : public AstNode { +class AstNodeModule VL_NOT_FINAL : public AstNode { // A module, package, program or interface declaration; // something that can live directly under the TOP, // excluding $unit package stuff @@ -2902,7 +2902,7 @@ public: VOptionBool unconnectedDrive() const { return m_unconnectedDrive; } }; -class AstNodeRange : public AstNode { +class AstNodeRange VL_NOT_FINAL : public AstNode { // A range, sized or unsized public: AstNodeRange(AstType t, FileLine* fl) diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 9ad9a58c1..3f5dfb2d9 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -553,7 +553,7 @@ string AstVar::mtasksString() const { return os.str(); } -class AstNodeDType::CTypeRecursed { +class AstNodeDType::CTypeRecursed final { public: string m_type; // The base type, e.g.: "Foo_t"s string m_dims; // Array dimensions, e.g.: "[3][2][1]" diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index f68c68120..c70763cc9 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -48,7 +48,7 @@ //=== Ast* : Specific types // Netlist interconnect -class AstConst : public AstNodeMath { +class AstConst final : public AstNodeMath { // A constant private: V3Number m_num; // Constant value @@ -175,7 +175,7 @@ public: static AstConst* parseParamLiteral(FileLine* fl, const string& literal); }; -class AstRange : public AstNodeRange { +class AstRange final : public AstNodeRange { // Range specification, for use under variables and cells private: bool m_littleEndian : 1; // Bit vector is little endian @@ -234,7 +234,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstBracketRange : public AstNodeRange { +class AstBracketRange final : public AstNodeRange { // Parser only concept "[lhsp]", a AstUnknownRange, QueueRange or Range, // unknown until lhsp type is determined public: @@ -253,7 +253,7 @@ public: AstNode* elementsp() const { return op1p(); } }; -class AstUnsizedRange : public AstNodeRange { +class AstUnsizedRange final : public AstNodeRange { // Unsized range specification, for open arrays public: explicit AstUnsizedRange(FileLine* fl) @@ -265,7 +265,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstGatePin : public AstNodeMath { +class AstGatePin final : public AstNodeMath { // Possibly expand a gate primitive input pin value to match the range of the gate primitive public: AstGatePin(FileLine* fl, AstNode* lhsp, AstRange* rangep) @@ -284,7 +284,7 @@ public: //###################################################################### // Classes -class AstClassPackage : public AstNodeModule { +class AstClassPackage final : public AstNodeModule { // The static information portion of a class (treated similarly to a package) AstClass* m_classp = nullptr; // Class package this is under (weak pointer, hard link is other way) @@ -298,7 +298,7 @@ public: void classp(AstClass* classp) { m_classp = classp; } }; -class AstClass : public AstNodeModule { +class AstClass final : public AstNodeModule { // TYPES typedef std::map MemberNameMap; // MEMBERS @@ -343,7 +343,7 @@ public: void isVirtual(bool flag) { m_virtual = flag; } }; -class AstClassExtends : public AstNode { +class AstClassExtends final : public AstNode { // Children: List of AstParseRef for packages/classes // during early parse, then moves to dtype public: @@ -364,7 +364,7 @@ public: //###################################################################### //==== Data Types -class AstParamTypeDType : public AstNodeDType { +class AstParamTypeDType final : public AstNodeDType { // Parents: MODULE // A parameter type statement; much like a var or typedef private: @@ -409,7 +409,7 @@ public: bool isGParam() const { return (varType() == AstVarType::GPARAM); } }; -class AstTypedef : public AstNode { +class AstTypedef final : public AstNode { private: string m_name; bool m_attrPublic; @@ -444,7 +444,7 @@ public: virtual string tag() const override { return m_tag; } }; -class AstTypedefFwd : public AstNode { +class AstTypedefFwd final : public AstNode { // Forward declaration of a type; stripped after netlist parsing is complete private: string m_name; @@ -459,7 +459,7 @@ public: virtual bool maybePointedTo() const override { return true; } }; -class AstDefImplicitDType : public AstNodeDType { +class AstDefImplicitDType final : public AstNodeDType { // For parsing enum/struct/unions that are declared with a variable rather than typedef // This allows "var enum {...} a,b" to share the enum definition for both variables // After link, these become typedefs @@ -509,7 +509,7 @@ public: virtual void name(const string& flag) override { m_name = flag; } }; -class AstAssocArrayDType : public AstNodeDType { +class AstAssocArrayDType final : public AstNodeDType { // Associative array data type, ie "[some_dtype]" // Children: DTYPE (moved to refDTypep() in V3Width) // Children: DTYPE (the key, which remains here as a pointer) @@ -580,7 +580,7 @@ public: virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; -class AstBracketArrayDType : public AstNodeDType { +class AstBracketArrayDType final : public AstNodeDType { // Associative/Queue/Normal array data type, ie "[dtype_or_expr]" // only for early parsing then becomes another data type // Children: DTYPE (moved to refDTypep() in V3Width) @@ -610,7 +610,7 @@ public: virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } }; -class AstDynArrayDType : public AstNodeDType { +class AstDynArrayDType final : public AstNodeDType { // Dynamic array data type, ie "[]" // Children: DTYPE (moved to refDTypep() in V3Width) private: @@ -669,7 +669,7 @@ public: virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; -class AstPackArrayDType : public AstNodeArrayDType { +class AstPackArrayDType final : public AstNodeArrayDType { // Packed array data type, ie "some_dtype [2:0] var_name" // Children: DTYPE (moved to refDTypep() in V3Width) // Children: RANGE (array bounds) @@ -695,7 +695,7 @@ public: virtual string prettyDTypeName() const override; }; -class AstUnpackArrayDType : public AstNodeArrayDType { +class AstUnpackArrayDType final : public AstNodeArrayDType { // Array data type, ie "some_dtype var_name [2:0]" // Children: DTYPE (moved to refDTypep() in V3Width) // Children: RANGE (array bounds) @@ -723,7 +723,7 @@ public: virtual string prettyDTypeName() const override; }; -class AstUnsizedArrayDType : public AstNodeDType { +class AstUnsizedArrayDType final : public AstNodeDType { // Unsized/open-range Array data type, ie "some_dtype var_name []" // Children: DTYPE (moved to refDTypep() in V3Width) private: @@ -775,7 +775,7 @@ public: virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; -class AstBasicDType : public AstNodeDType { +class AstBasicDType final : public AstNodeDType { // Builtin atomic/vectored data type // Children: RANGE (converted to constant in V3Width) private: @@ -932,7 +932,7 @@ public: } }; -class AstConstDType : public AstNodeDType { +class AstConstDType final : public AstNodeDType { // const data type, ie "const some_dtype var_name [2:0]" // ConstDType are removed in V3LinkLValue and become AstVar::isConst. // When more generic types are supported AstConstDType will be propagated further. @@ -984,7 +984,7 @@ public: virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; -class AstClassRefDType : public AstNodeDType { +class AstClassRefDType final : public AstNodeDType { // Reference to a class private: AstClass* m_classp; // data type pointed to, BELOW the AstTypedef @@ -1032,7 +1032,7 @@ public: void classp(AstClass* nodep) { m_classp = nodep; } }; -class AstIfaceRefDType : public AstNodeDType { +class AstIfaceRefDType final : public AstNodeDType { // Reference to an interface, either for a port, or inside parent cell private: FileLine* m_modportFileline; // Where modport token was @@ -1087,7 +1087,7 @@ public: bool isModport() { return !m_modportName.empty(); } }; -class AstQueueDType : public AstNodeDType { +class AstQueueDType final : public AstNodeDType { // Queue array data type, ie "[ $ ]" // Children: DTYPE (moved to refDTypep() in V3Width) private: @@ -1157,7 +1157,7 @@ public: virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; -class AstRefDType : public AstNodeDType { +class AstRefDType final : public AstNodeDType { private: // Pre-Width must reference the Typeref, not what it points to, as some child // types like AstBracketArrayType will disappear and can't lose the handle @@ -1258,7 +1258,7 @@ public: AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } }; -class AstStructDType : public AstNodeUOrStructDType { +class AstStructDType final : public AstNodeUOrStructDType { public: // VSigning below is mispurposed to indicate if packed or not AstStructDType(FileLine* fl, VSigning numericUnpack) @@ -1267,7 +1267,7 @@ public: virtual string verilogKwd() const override { return "struct"; } }; -class AstUnionDType : public AstNodeUOrStructDType { +class AstUnionDType final : public AstNodeUOrStructDType { public: // UNSUP: bool isTagged; // VSigning below is mispurposed to indicate if packed or not @@ -1277,7 +1277,7 @@ public: virtual string verilogKwd() const override { return "union"; } }; -class AstMemberDType : public AstNodeDType { +class AstMemberDType final : public AstNodeDType { // A member of a struct/union // PARENT: AstNodeUOrStructDType private: @@ -1340,7 +1340,7 @@ public: void lsb(int lsb) { m_lsb = lsb; } }; -class AstVoidDType : public AstNodeDType { +class AstVoidDType final : public AstNodeDType { // For e.g. a function returning void public: explicit AstVoidDType(FileLine* fl) @@ -1367,7 +1367,7 @@ public: virtual V3Hash sameHash() const override { return V3Hash(); } }; -class AstEnumItem : public AstNode { +class AstEnumItem final : public AstNode { private: string m_name; @@ -1390,7 +1390,7 @@ public: void valuep(AstNode* nodep) { addOp2p(nodep); } }; -class AstEnumItemRef : public AstNodeMath { +class AstEnumItemRef final : public AstNodeMath { private: AstEnumItem* m_itemp; // [AfterLink] Pointer to item AstNodeModule* m_packagep; // Package hierarchy @@ -1424,7 +1424,7 @@ public: void packagep(AstNodeModule* nodep) { m_packagep = nodep; } }; -class AstEnumDType : public AstNodeDType { +class AstEnumDType final : public AstNodeDType { // Parents: TYPEDEF/MODULE // Children: ENUMVALUEs private: @@ -1483,7 +1483,7 @@ public: virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; -class AstParseTypeDType : public AstNodeDType { +class AstParseTypeDType final : public AstNodeDType { // Parents: VAR // During parsing, this indicates the type of a parameter is a "parameter type" // e.g. the data type is a container of any data type @@ -1506,7 +1506,7 @@ public: //###################################################################### -class AstArraySel : public AstNodeSel { +class AstArraySel final : public AstNodeSel { // Parents: math|stmt // Children: varref|arraysel, math private: @@ -1552,7 +1552,7 @@ public: baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences? }; -class AstAssocSel : public AstNodeSel { +class AstAssocSel final : public AstNodeSel { // Parents: math|stmt // Children: varref|arraysel, math private: @@ -1591,7 +1591,7 @@ public: virtual int instrCount() const override { return widthInstrs(); } }; -class AstWordSel : public AstNodeSel { +class AstWordSel final : public AstNodeSel { // Select a single word from a multi-word wide value public: AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp) @@ -1618,7 +1618,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstSelLoopVars : public AstNode { +class AstSelLoopVars final : public AstNode { // Parser only concept "[id, id, id]" for a foreach statement // Unlike normal selects elements is a list public: @@ -1635,7 +1635,7 @@ public: AstNode* elementsp() const { return op2p(); } }; -class AstSelExtract : public AstNodePreSel { +class AstSelExtract final : public AstNodePreSel { // Range extraction, gets replaced with AstSel public: AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp) @@ -1645,7 +1645,7 @@ public: AstNode* lsbp() const { return thsp(); } }; -class AstSelBit : public AstNodePreSel { +class AstSelBit final : public AstNodePreSel { // Single bit range extraction, perhaps with non-constant selection or array selection // Gets replaced during link with AstArraySel or AstSel public: @@ -1658,7 +1658,7 @@ public: AstNode* bitp() const { return rhsp(); } }; -class AstSelPlus : public AstNodePreSel { +class AstSelPlus final : public AstNodePreSel { // +: range extraction, perhaps with non-constant selection // Gets replaced during link with AstSel public: @@ -1669,7 +1669,7 @@ public: AstNode* widthp() const { return thsp(); } }; -class AstSelMinus : public AstNodePreSel { +class AstSelMinus final : public AstNodePreSel { // -: range extraction, perhaps with non-constant selection // Gets replaced during link with AstSel public: @@ -1680,7 +1680,7 @@ public: AstNode* widthp() const { return thsp(); } }; -class AstSel : public AstNodeTriop { +class AstSel final : public AstNodeTriop { // Multiple bit range extraction // Parents: math|stmt // Children: varref|arraysel, math, constant math @@ -1740,7 +1740,7 @@ public: void declElWidth(int flag) { m_declElWidth = flag; } }; -class AstSliceSel : public AstNodeTriop { +class AstSliceSel final : public AstNodeTriop { // Multiple array element extraction // Parents: math|stmt // Children: varref|arraysel, math, constant math @@ -1778,7 +1778,7 @@ public: void declRange(const VNumRange& flag) { m_declRange = flag; } }; -class AstMethodCall : public AstNodeFTaskRef { +class AstMethodCall final : public AstNodeFTaskRef { // A reference to a member task (or function) // PARENTS: stmt/math // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. @@ -1812,7 +1812,7 @@ public: void fromp(AstNode* nodep) { setOp2p(nodep); } }; -class AstCMethodHard : public AstNodeStmt { +class AstCMethodHard final : public AstNodeStmt { // A reference to a "C" hardcoded member task (or function) // PARENTS: stmt/math // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. @@ -1857,7 +1857,7 @@ public: void addPinsp(AstNode* nodep) { addOp2p(nodep); } }; -class AstVar : public AstNode { +class AstVar final : public AstNode { // A variable (in/out/wire/reg/param) inside a module private: string m_name; // Name of variable @@ -2190,7 +2190,7 @@ public: string mtasksString() const; }; -class AstDefParam : public AstNode { +class AstDefParam final : public AstNode { // A defparam assignment // Parents: MODULE // Children: math @@ -2212,7 +2212,7 @@ public: string path() const { return m_path; } }; -class AstImplicit : public AstNode { +class AstImplicit final : public AstNode { // Create implicit wires and do nothing else, for gates that are ignored // Parents: MODULE public: @@ -2224,7 +2224,7 @@ public: AstNode* exprsp() const { return op1p(); } // op1 = Assign from }; -class AstScope : public AstNode { +class AstScope final : public AstNode { // A particular usage of a cell // Parents: MODULE // Children: NODEBLOCK @@ -2263,7 +2263,7 @@ public: bool isTop() const { return aboveScopep() == nullptr; } // At top of hierarchy }; -class AstTopScope : public AstNode { +class AstTopScope final : public AstNode { // In the top level netlist, a complete scope tree // There may be two of these, when we support "rare" and "usual" splitting // Parents: topMODULE @@ -2279,7 +2279,7 @@ public: AstScope* scopep() const { return VN_CAST(op2p(), Scope); } // op1 = AstVarScope's }; -class AstVarScope : public AstNode { +class AstVarScope final : public AstNode { // A particular scoped usage of a variable // That is, as a module is used under multiple cells, we get a different // varscope for each var in the module @@ -2327,7 +2327,7 @@ public: void trace(bool flag) { m_trace = flag; } }; -class AstVarRef : public AstNodeVarRef { +class AstVarRef final : public AstNodeVarRef { // A reference to a variable (lvalue or rvalue) public: AstVarRef(FileLine* fl, const string& name, const VAccess& access) @@ -2374,7 +2374,7 @@ public: virtual bool cleanOut() const override { return true; } }; -class AstVarXRef : public AstNodeVarRef { +class AstVarXRef final : public AstNodeVarRef { // A VarRef to something in another module before AstScope. // Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope private: @@ -2408,7 +2408,7 @@ public: } }; -class AstPin : public AstNode { +class AstPin final : public AstNode { // A pin on a cell private: int m_pinNum; // Pin number @@ -2462,7 +2462,7 @@ public: void svImplicit(bool flag) { m_svImplicit = flag; } }; -class AstArg : public AstNode { +class AstArg final : public AstNode { // An argument to a function/task private: string m_name; // Pin name, or "" for number based interconnect @@ -2482,7 +2482,7 @@ public: bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); } }; -class AstModule : public AstNodeModule { +class AstModule final : public AstNodeModule { // A module declaration private: bool m_isProgram; // Module represents a program @@ -2494,7 +2494,7 @@ public: virtual string verilogKwd() const override { return m_isProgram ? "program" : "module"; } }; -class AstNotFoundModule : public AstNodeModule { +class AstNotFoundModule final : public AstNodeModule { // A missing module declaration public: AstNotFoundModule(FileLine* fl, const string& name) @@ -2503,7 +2503,7 @@ public: virtual string verilogKwd() const override { return "/*not-found-*/ module"; } }; -class AstPackage : public AstNodeModule { +class AstPackage final : public AstNodeModule { // A package declaration public: AstPackage(FileLine* fl, const string& name) @@ -2514,7 +2514,7 @@ public: bool isDollarUnit() const { return name() == dollarUnitName(); } }; -class AstPrimitive : public AstNodeModule { +class AstPrimitive final : public AstNodeModule { // A primitive declaration public: AstPrimitive(FileLine* fl, const string& name) @@ -2523,7 +2523,7 @@ public: virtual string verilogKwd() const override { return "primitive"; } }; -class AstPackageExportStarStar : public AstNode { +class AstPackageExportStarStar final : public AstNode { // A package export *::* declaration public: // cppcheck-suppress noExplicitConstructor @@ -2532,7 +2532,7 @@ public: ASTNODE_NODE_FUNCS(PackageExportStarStar) }; -class AstPackageExport : public AstNode { +class AstPackageExport final : public AstNode { private: // A package export declaration string m_name; @@ -2556,7 +2556,7 @@ public: void packagep(AstPackage* nodep) { m_packagep = nodep; } }; -class AstPackageImport : public AstNode { +class AstPackageImport final : public AstNode { private: // A package import declaration string m_name; @@ -2580,7 +2580,7 @@ public: void packagep(AstPackage* nodep) { m_packagep = nodep; } }; -class AstIface : public AstNodeModule { +class AstIface final : public AstNodeModule { // A module declaration public: AstIface(FileLine* fl, const string& name) @@ -2588,7 +2588,7 @@ public: ASTNODE_NODE_FUNCS(Iface) }; -class AstMemberSel : public AstNodeMath { +class AstMemberSel final : public AstNodeMath { // Parents: math|stmt // Children: varref|arraysel, math private: @@ -2634,7 +2634,7 @@ public: void varp(AstVar* nodep) { m_varp = nodep; } }; -class AstModportFTaskRef : public AstNode { +class AstModportFTaskRef final : public AstNode { // An import/export referenced under a modport // The storage for the function itself is inside the // interface/instantiator, thus this is a reference @@ -2664,7 +2664,7 @@ public: void ftaskp(AstNodeFTask* ftaskp) { m_ftaskp = ftaskp; } }; -class AstModportVarRef : public AstNode { +class AstModportVarRef final : public AstNode { // A input/output/etc variable referenced under a modport // The storage for the variable itself is inside the interface, thus this is a reference // PARENT: AstModport @@ -2693,7 +2693,7 @@ public: void varp(AstVar* varp) { m_varp = varp; } }; -class AstModport : public AstNode { +class AstModport final : public AstNode { // A modport in an interface private: string m_name; // Name of the modport @@ -2709,7 +2709,7 @@ public: AstNode* varsp() const { return op1p(); } // op1 = List of Vars }; -class AstIntfRef : public AstNode { +class AstIntfRef final : public AstNode { // An interface reference private: string m_name; // Name of the reference @@ -2721,7 +2721,7 @@ public: ASTNODE_NODE_FUNCS(IntfRef) }; -class AstCell : public AstNode { +class AstCell final : public AstNode { // A instantiation cell or interface call (don't know which until link) private: FileLine* m_modNameFileline; // Where module the cell instances token was @@ -2783,7 +2783,7 @@ public: bool recursive() const { return m_recursive; } }; -class AstCellInline : public AstNode { +class AstCellInline final : public AstNode { // A instantiation cell that was removed by inlining // For communication between V3Inline and V3LinkDot, // except for VPI runs where it exists until the end. @@ -2817,7 +2817,7 @@ public: VTimescale timeunit() const { return m_timeunit; } }; -class AstCellRef : public AstNode { +class AstCellRef final : public AstNode { // As-of-yet unlinkable reference into a cell private: string m_name; // Cell name @@ -2835,7 +2835,7 @@ public: AstNode* exprp() const { return op2p(); } // op2 = Expression }; -class AstCellArrayRef : public AstNode { +class AstCellArrayRef final : public AstNode { // As-of-yet unlinkable reference into an array of cells private: string m_name; // Array name @@ -2851,7 +2851,7 @@ public: AstNode* selp() const { return op1p(); } // op1 = Select expression }; -class AstUnlinkedRef : public AstNode { +class AstUnlinkedRef final : public AstNode { // As-of-yet unlinkable Ref private: string m_name; // Var name @@ -2869,7 +2869,7 @@ public: AstNode* cellrefp() const { return op2p(); } // op2 = CellArrayRef or CellRef }; -class AstBind : public AstNode { +class AstBind final : public AstNode { // Parents: MODULE // Children: CELL private: @@ -2888,7 +2888,7 @@ public: AstNode* cellsp() const { return op1p(); } // op1 = cells }; -class AstPort : public AstNode { +class AstPort final : public AstNode { // A port (in/out/inout) on a module private: int m_pinNum; // Pin number @@ -2906,7 +2906,7 @@ public: //###################################################################### -class AstParseRef : public AstNode { +class AstParseRef final : public AstNode { // A reference to a variable, function or task // We don't know which at parse time due to bison constraints // The link stages will replace this with AstVarRef, or AstTaskRef, etc. @@ -2942,7 +2942,7 @@ public: void ftaskrefp(AstNodeFTaskRef* nodep) { setNOp2p(nodep); } // op2 = Function/task reference }; -class AstClassOrPackageRef : public AstNode { +class AstClassOrPackageRef final : public AstNode { private: string m_name; AstNode* m_classOrPackagep; // Package hierarchy @@ -2978,7 +2978,7 @@ public: AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } }; -class AstDot : public AstNode { +class AstDot final : public AstNode { // A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef // These are eliminated in the link stage bool m_colon; // Is a "::" instead of a "." (lhs must be package/class) @@ -3001,7 +3001,7 @@ public: bool colon() const { return m_colon; } }; -class AstUnbounded : public AstNodeMath { +class AstUnbounded final : public AstNodeMath { // A $ in the parser, used for unbounded and queues // Due to where is used, treated as Signed32 public: @@ -3017,7 +3017,7 @@ public: //###################################################################### -class AstTask : public AstNodeFTask { +class AstTask final : public AstNodeFTask { // A task inside a module public: AstTask(FileLine* fl, const string& name, AstNode* stmtp) @@ -3025,7 +3025,7 @@ public: ASTNODE_NODE_FUNCS(Task) }; -class AstFunc : public AstNodeFTask { +class AstFunc final : public AstNodeFTask { // A function inside a module public: AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp) @@ -3036,7 +3036,7 @@ public: virtual bool hasDType() const override { return true; } }; -class AstTaskRef : public AstNodeFTaskRef { +class AstTaskRef final : public AstNodeFTaskRef { // A reference to a task public: AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) @@ -3048,7 +3048,7 @@ public: ASTNODE_NODE_FUNCS(TaskRef) }; -class AstFuncRef : public AstNodeFTaskRef { +class AstFuncRef final : public AstNodeFTaskRef { // A reference to a function public: AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) @@ -3059,7 +3059,7 @@ public: virtual bool hasDType() const override { return true; } }; -class AstDpiExport : public AstNode { +class AstDpiExport final : public AstNode { // We could put an AstNodeFTaskRef instead of the verilog function name, // however we're not *calling* it, so that seems somehow wrong. // (Probably AstNodeFTaskRef should be renamed AstNodeFTaskCall and have-a AstNodeFTaskRef) @@ -3078,7 +3078,7 @@ public: void cname(const string& cname) { m_cname = cname; } }; -class AstWithParse : public AstNodeStmt { +class AstWithParse final : public AstNodeStmt { // In early parse, FUNC(index) WITH equation-using-index // Replaced with AstWith // Parents: math|stmt @@ -3098,7 +3098,7 @@ public: AstNode* exprp() const { return op2p(); } }; -class AstLambdaArgRef : public AstNodeMath { +class AstLambdaArgRef final : public AstNodeMath { // Lambda argument usage // These are not AstVarRefs because we need to be able to delete/clone lambdas during // optimizations and AstVar's are painful to remove. @@ -3121,7 +3121,7 @@ public: virtual void name(const string& name) override { m_name = name; } }; -class AstWith : public AstNodeStmt { +class AstWith final : public AstNodeStmt { // Used as argument to method, then to AstCMethodHard // dtypep() contains the with lambda's return dtype // Parents: funcref (similar to AstArg) @@ -3148,7 +3148,7 @@ public: //###################################################################### -class AstSenItem : public AstNode { +class AstSenItem final : public AstNode { // Parents: SENTREE // Children: (optional) VARREF private: @@ -3204,7 +3204,7 @@ public: bool hasVar() const { return !(isCombo() || isInitial() || isSettle() || isNever()); } }; -class AstSenTree : public AstNode { +class AstSenTree final : public AstNode { // A list of senitems // Parents: MODULE | SBLOCK // Children: SENITEM list @@ -3231,21 +3231,21 @@ public: bool hasCombo() const; // Includes a COMBO SenItem }; -class AstFinal : public AstNodeProcedure { +class AstFinal final : public AstNodeProcedure { public: AstFinal(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER(fl, bodysp) {} ASTNODE_NODE_FUNCS(Final) }; -class AstInitial : public AstNodeProcedure { +class AstInitial final : public AstNodeProcedure { public: AstInitial(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER(fl, bodysp) {} ASTNODE_NODE_FUNCS(Initial) }; -class AstAlways : public AstNodeProcedure { +class AstAlways final : public AstNodeProcedure { VAlwaysKwd m_keyword; public: @@ -3262,7 +3262,7 @@ public: VAlwaysKwd keyword() const { return m_keyword; } }; -class AstAlwaysPublic : public AstNodeStmt { +class AstAlwaysPublic final : public AstNodeStmt { // "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/ // Body statements are just AstVarRefs to the public signals public: @@ -3282,7 +3282,7 @@ public: bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } }; -class AstAlwaysPost : public AstNode { +class AstAlwaysPost final : public AstNode { // Like always but post assignments for memory assignment IFs public: AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) @@ -3296,7 +3296,7 @@ public: void addBodysp(AstNode* newp) { addOp2p(newp); } }; -class AstAssign : public AstNodeAssign { +class AstAssign final : public AstNodeAssign { public: AstAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -3309,7 +3309,7 @@ public: virtual bool brokeLhsMustBeLvalue() const override { return true; } }; -class AstAssignAlias : public AstNodeAssign { +class AstAssignAlias final : public AstNodeAssign { // Like AstAssignW, but a true bidirect interconnection alias // If both sides are wires, there's no LHS vs RHS, public: @@ -3322,7 +3322,7 @@ public: virtual bool brokeLhsMustBeLvalue() const override { return false; } }; -class AstAssignDly : public AstNodeAssign { +class AstAssignDly final : public AstNodeAssign { public: AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} @@ -3335,7 +3335,7 @@ public: virtual bool brokeLhsMustBeLvalue() const override { return true; } }; -class AstAssignW : public AstNodeAssign { +class AstAssignW final : public AstNodeAssign { // Like assign, but wire/assign's in verilog, the only setting of the specified variable public: AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -3355,7 +3355,7 @@ public: } }; -class AstAssignVarScope : public AstNodeAssign { +class AstAssignVarScope final : public AstNodeAssign { // Assign two VarScopes to each other public: AstAssignVarScope(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -3369,7 +3369,7 @@ public: virtual bool brokeLhsMustBeLvalue() const override { return false; } }; -class AstPull : public AstNode { +class AstPull final : public AstNode { private: bool m_direction; @@ -3388,7 +3388,7 @@ public: uint32_t direction() const { return (uint32_t)m_direction; } }; -class AstAssignPre : public AstNodeAssign { +class AstAssignPre final : public AstNodeAssign { // Like Assign, but predelayed assignment requiring special order handling public: AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -3400,7 +3400,7 @@ public: virtual bool brokeLhsMustBeLvalue() const override { return true; } }; -class AstAssignPost : public AstNodeAssign { +class AstAssignPost final : public AstNodeAssign { // Like Assign, but predelayed assignment requiring special order handling public: AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -3412,7 +3412,7 @@ public: virtual bool brokeLhsMustBeLvalue() const override { return true; } }; -class AstComment : public AstNodeStmt { +class AstComment final : public AstNodeStmt { // Some comment to put into the output stream // Parents: {statement list} // Children: none @@ -3433,7 +3433,7 @@ public: virtual bool showAt() const { return m_showAt; } }; -class AstCond : public AstNodeCond { +class AstCond final : public AstNodeCond { // Conditional ?: statement // Parents: MATH // Children: MATH @@ -3446,7 +3446,7 @@ public: } }; -class AstCondBound : public AstNodeCond { +class AstCondBound final : public AstNodeCond { // Conditional ?: statement, specially made for safety checking of array bounds // Parents: MATH // Children: MATH @@ -3459,7 +3459,7 @@ public: } }; -class AstCoverDecl : public AstNodeStmt { +class AstCoverDecl final : public AstNodeStmt { // Coverage analysis point declaration // Parents: {statement list} // Children: none @@ -3520,7 +3520,7 @@ public: AstCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; } }; -class AstCoverInc : public AstNodeStmt { +class AstCoverInc final : public AstNodeStmt { // Coverage analysis point; increment coverage count // Parents: {statement list} // Children: none @@ -3551,7 +3551,7 @@ public: AstCoverDecl* declp() const { return m_declp; } // Where defined }; -class AstCoverToggle : public AstNodeStmt { +class AstCoverToggle final : public AstNodeStmt { // Toggle analysis of given signal // Parents: MODULE // Children: AstCoverInc, orig var, change det var @@ -3578,7 +3578,7 @@ public: AstNode* changep() const { return op3p(); } }; -class AstDelay : public AstNodeStmt { +class AstDelay final : public AstNodeStmt { // Delay statement public: AstDelay(FileLine* fl, AstNode* lhsp) @@ -3593,7 +3593,7 @@ public: void lhsp(AstNode* nodep) { setOp1p(nodep); } }; -class AstGenCase : public AstNodeCase { +class AstGenCase final : public AstNodeCase { // Generate Case statement // Parents: {statement list} // exprp Children: MATHs @@ -3604,7 +3604,7 @@ public: ASTNODE_NODE_FUNCS(GenCase) }; -class AstCase : public AstNodeCase { +class AstCase final : public AstNodeCase { // Case statement // Parents: {statement list} // exprp Children: MATHs @@ -3644,7 +3644,7 @@ public: void priorityPragma(bool flag) { m_priorityPragma = flag; } }; -class AstCaseItem : public AstNode { +class AstCaseItem final : public AstNode { // Single item of a case statement // Parents: CASE // condsp Children: MATH (Null condition used for default block) @@ -3668,7 +3668,7 @@ public: void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; } }; -class AstSFormatF : public AstNode { +class AstSFormatF final : public AstNode { // Convert format to string, generally under an AstDisplay or AstSFormat // Also used as "real" function for /*verilator sformat*/ functions string m_text; @@ -3726,7 +3726,7 @@ public: VTimescale timeunit() const { return m_timeunit; } }; -class AstDisplay : public AstNodeStmt { +class AstDisplay final : public AstNodeStmt { // Parents: stmtlist // Children: file which must be a varref // Children: SFORMATF to generate print string @@ -3780,7 +3780,7 @@ public: void filep(AstNodeVarRef* nodep) { setNOp3p(nodep); } }; -class AstDumpCtl : public AstNodeStmt { +class AstDumpCtl final : public AstNodeStmt { // $dumpon etc // Parents: expr // Child: expr based on type of control statement @@ -3805,7 +3805,7 @@ public: void exprp(AstNode* nodep) { setOp1p(nodep); } }; -class AstElabDisplay : public AstNode { +class AstElabDisplay final : public AstNode { // Parents: stmtlist // Children: SFORMATF to generate print string private: @@ -3843,7 +3843,7 @@ public: AstSFormatF* fmtp() const { return VN_CAST(op1p(), SFormatF); } }; -class AstSFormat : public AstNodeStmt { +class AstSFormat final : public AstNodeStmt { // Parents: statement container // Children: string to load // Children: SFORMATF to generate print string @@ -3879,7 +3879,7 @@ public: void lhsp(AstNode* nodep) { setOp3p(nodep); } }; -class AstSysFuncAsTask : public AstNodeStmt { +class AstSysFuncAsTask final : public AstNodeStmt { // Call what is normally a system function (with a return) in a non-return context // Parents: stmtlist // Children: a system function @@ -3901,7 +3901,7 @@ public: void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval }; -class AstSysIgnore : public AstNodeStmt { +class AstSysIgnore final : public AstNodeStmt { // Parents: stmtlist // Children: varrefs or exprs public: @@ -3922,7 +3922,7 @@ public: void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output }; -class AstFClose : public AstNodeStmt { +class AstFClose final : public AstNodeStmt { // Parents: stmtlist // Children: file which must be a varref public: @@ -3943,7 +3943,7 @@ public: void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; -class AstFOpen : public AstNodeStmt { +class AstFOpen final : public AstNodeStmt { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) public: AstFOpen(FileLine* fl, AstNode* filep, AstNode* filenamep, AstNode* modep) @@ -3967,7 +3967,7 @@ public: AstNode* modep() const { return op3p(); } }; -class AstFOpenMcd : public AstNodeStmt { +class AstFOpenMcd final : public AstNodeStmt { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) public: AstFOpenMcd(FileLine* fl, AstNode* filep, AstNode* filenamep) @@ -3989,7 +3989,7 @@ public: AstNode* filenamep() const { return op2p(); } }; -class AstFFlush : public AstNodeStmt { +class AstFFlush final : public AstNodeStmt { // Parents: stmtlist // Children: file which must be a varref public: @@ -4010,7 +4010,7 @@ public: void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; -class AstFRead : public AstNodeMath { +class AstFRead final : public AstNodeMath { // Parents: expr // Children: varrefs to load // Children: file which must be a varref @@ -4045,7 +4045,7 @@ public: void countp(AstNode* nodep) { setNOp4p(nodep); } }; -class AstFRewind : public AstNodeMath { +class AstFRewind final : public AstNodeMath { // Parents: stmtlist // Children: file which must be a varref public: @@ -4069,7 +4069,7 @@ public: void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; -class AstFTell : public AstNodeMath { +class AstFTell final : public AstNodeMath { // Parents: stmtlist // Children: file which must be a varref public: @@ -4093,7 +4093,7 @@ public: void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; -class AstFSeek : public AstNodeMath { +class AstFSeek final : public AstNodeMath { // Parents: expr // Children: file which must be a varref // Children: offset @@ -4124,7 +4124,7 @@ public: void operation(AstNode* nodep) { setNOp4p(nodep); } }; -class AstFScanF : public AstNodeMath { +class AstFScanF final : public AstNodeMath { // Parents: expr // Children: file which must be a varref // Children: varrefs to load @@ -4160,7 +4160,7 @@ public: void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; -class AstSScanF : public AstNodeMath { +class AstSScanF final : public AstNodeMath { // Parents: expr // Children: file which must be a varref // Children: varrefs to load @@ -4196,7 +4196,7 @@ public: void fromp(AstNode* nodep) { setOp2p(nodep); } }; -class AstNodeReadWriteMem : public AstNodeStmt { +class AstNodeReadWriteMem VL_NOT_FINAL : public AstNodeStmt { private: bool m_isHex; // readmemh, not readmemb public: @@ -4227,7 +4227,7 @@ public: virtual const char* cFuncPrefixp() const = 0; }; -class AstReadMem : public AstNodeReadWriteMem { +class AstReadMem final : public AstNodeReadWriteMem { public: AstReadMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) @@ -4237,7 +4237,7 @@ public: virtual const char* cFuncPrefixp() const override { return "VL_READMEM_"; } }; -class AstWriteMem : public AstNodeReadWriteMem { +class AstWriteMem final : public AstNodeReadWriteMem { public: AstWriteMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) @@ -4247,7 +4247,7 @@ public: virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } }; -class AstSystemT : public AstNodeStmt { +class AstSystemT final : public AstNodeStmt { // $system used as task public: AstSystemT(FileLine* fl, AstNode* lhsp) @@ -4266,7 +4266,7 @@ public: AstNode* lhsp() const { return op1p(); } }; -class AstSystemF : public AstNodeMath { +class AstSystemF final : public AstNodeMath { // $system used as function public: AstSystemF(FileLine* fl, AstNode* lhsp) @@ -4288,7 +4288,7 @@ public: AstNode* lhsp() const { return op1p(); } }; -class AstValuePlusArgs : public AstNodeMath { +class AstValuePlusArgs final : public AstNodeMath { // Parents: expr // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs public: @@ -4313,7 +4313,7 @@ public: void outp(AstNode* nodep) { setOp2p(nodep); } }; -class AstTestPlusArgs : public AstNodeMath { +class AstTestPlusArgs final : public AstNodeMath { // Parents: expr // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs private: @@ -4339,14 +4339,14 @@ public: void text(const string& text) { m_text = text; } }; -class AstGenFor : public AstNodeFor { +class AstGenFor final : public AstNodeFor { public: AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) : ASTGEN_SUPER(fl, initsp, condp, incsp, bodysp) {} ASTNODE_NODE_FUNCS(GenFor) }; -class AstForeach : public AstNodeStmt { +class AstForeach final : public AstNodeStmt { public: AstForeach(FileLine* fl, AstNode* arrayp, AstNode* bodysp) : ASTGEN_SUPER(fl) { @@ -4362,7 +4362,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstRepeat : public AstNodeStmt { +class AstRepeat final : public AstNodeStmt { public: AstRepeat(FileLine* fl, AstNode* countp, AstNode* bodysp) : ASTGEN_SUPER(fl) { @@ -4380,7 +4380,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstWait : public AstNodeStmt { +class AstWait final : public AstNodeStmt { public: AstWait(FileLine* fl, AstNode* condp, AstNode* bodysp) : ASTGEN_SUPER(fl) { @@ -4391,7 +4391,7 @@ public: AstNode* bodysp() const { return op3p(); } // op3 = body of loop }; -class AstWhile : public AstNodeStmt { +class AstWhile final : public AstNodeStmt { public: AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp, AstNode* incsp = nullptr) : ASTGEN_SUPER(fl) { @@ -4418,7 +4418,7 @@ public: virtual void addNextStmt(AstNode* newp, AstNode* belowp) override; }; -class AstBreak : public AstNodeStmt { +class AstBreak final : public AstNodeStmt { public: explicit AstBreak(FileLine* fl) : ASTGEN_SUPER(fl) {} @@ -4430,7 +4430,7 @@ public: } }; -class AstContinue : public AstNodeStmt { +class AstContinue final : public AstNodeStmt { public: explicit AstContinue(FileLine* fl) : ASTGEN_SUPER(fl) {} @@ -4442,7 +4442,7 @@ public: } }; -class AstDisable : public AstNodeStmt { +class AstDisable final : public AstNodeStmt { private: string m_name; // Name of block public: @@ -4457,7 +4457,7 @@ public: } }; -class AstDisableFork : public AstNodeStmt { +class AstDisableFork final : public AstNodeStmt { // A "disable fork" statement public: AstDisableFork(FileLine* fl) @@ -4465,7 +4465,7 @@ public: ASTNODE_NODE_FUNCS(DisableFork) }; -class AstWaitFork : public AstNodeStmt { +class AstWaitFork final : public AstNodeStmt { // A "wait fork" statement public: AstWaitFork(FileLine* fl) @@ -4473,7 +4473,7 @@ public: ASTNODE_NODE_FUNCS(WaitFork) }; -class AstReturn : public AstNodeStmt { +class AstReturn final : public AstNodeStmt { public: explicit AstReturn(FileLine* fl, AstNode* lhsp = nullptr) : ASTGEN_SUPER(fl) { @@ -4488,14 +4488,14 @@ public: } }; -class AstGenIf : public AstNodeIf { +class AstGenIf final : public AstNodeIf { public: AstGenIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) : ASTGEN_SUPER(fl, condp, ifsp, elsesp) {} ASTNODE_NODE_FUNCS(GenIf) }; -class AstIf : public AstNodeIf { +class AstIf final : public AstNodeIf { private: bool m_uniquePragma; // unique case bool m_unique0Pragma; // unique0 case @@ -4516,7 +4516,7 @@ public: void priorityPragma(bool flag) { m_priorityPragma = flag; } }; -class AstJumpBlock : public AstNodeStmt { +class AstJumpBlock final : public AstNodeStmt { // Block of code including a JumpGo and JumpLabel // Parents: {statement list} // Children: {statement list, with JumpGo and JumpLabel below} @@ -4547,7 +4547,7 @@ public: void labelp(AstJumpLabel* labelp) { m_labelp = labelp; } }; -class AstJumpLabel : public AstNodeStmt { +class AstJumpLabel final : public AstNodeStmt { // Jump point declaration // Parents: {statement list with JumpBlock above} // Children: none @@ -4576,7 +4576,7 @@ public: AstJumpBlock* blockp() const { return m_blockp; } }; -class AstJumpGo : public AstNodeStmt { +class AstJumpGo final : public AstNodeStmt { // Jump point; branch down to a JumpLabel // No support for backward jumps at present // Parents: {statement list with JumpBlock above} @@ -4608,7 +4608,7 @@ public: AstJumpLabel* labelp() const { return m_labelp; } }; -class AstChangeXor : public AstNodeBiComAsv { +class AstChangeXor final : public AstNodeBiComAsv { // A comparison to determine change detection, common & must be fast. // Returns 32-bit or 64-bit value where 0 indicates no change. // Parents: OR or LOGOR @@ -4636,7 +4636,7 @@ public: virtual int instrCount() const override { return widthInstrs(); } }; -class AstChangeDet : public AstNodeStmt { +class AstChangeDet final : public AstNodeStmt { // A comparison to determine change detection, common & must be fast. private: bool m_clockReq; // Type of detection @@ -4659,7 +4659,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstConsAssoc : public AstNodeMath { +class AstConsAssoc final : public AstNodeMath { // Construct an assoc array and return object, '{} // Parents: math // Children: expression (elements or other queues) @@ -4678,7 +4678,7 @@ public: virtual V3Hash sameHash() const override { return V3Hash(); } virtual bool same(const AstNode* samep) const override { return true; } }; -class AstSetAssoc : public AstNodeMath { +class AstSetAssoc final : public AstNodeMath { // Set an assoc array element and return object, '{} // Parents: math // Children: expression (elements or other queues) @@ -4702,7 +4702,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstConsDynArray : public AstNodeMath { +class AstConsDynArray final : public AstNodeMath { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} // Parents: math // Children: expression (elements or other queues) @@ -4724,7 +4724,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstConsQueue : public AstNodeMath { +class AstConsQueue final : public AstNodeMath { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} // Parents: math // Children: expression (elements or other queues) @@ -4746,7 +4746,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstBegin : public AstNodeBlock { +class AstBegin final : public AstNodeBlock { // A Begin/end named block, only exists shortly after parsing until linking // Parents: statement // Children: statements @@ -4771,7 +4771,7 @@ public: bool implied() const { return m_implied; } }; -class AstFork : public AstNodeBlock { +class AstFork final : public AstNodeBlock { // A fork named block // Parents: statement // Children: statements @@ -4787,7 +4787,7 @@ public: void joinType(const VJoinType& flag) { m_joinType = flag; } }; -class AstInside : public AstNodeMath { +class AstInside final : public AstNodeMath { public: AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp) : ASTGEN_SUPER(fl) { @@ -4804,7 +4804,7 @@ public: virtual bool cleanOut() const override { return false; } // NA }; -class AstInsideRange : public AstNodeMath { +class AstInsideRange final : public AstNodeMath { public: AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl) { @@ -4821,7 +4821,7 @@ public: AstNode* newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp); }; -class AstInitItem : public AstNode { +class AstInitItem final : public AstNode { // Container for a item in an init array // This container is present so that the value underneath may get replaced with a new nodep // and the upper AstInitArray's map will remain correct (pointing to this InitItem) @@ -4839,7 +4839,7 @@ public: void valuep(AstNode* nodep) { addOp1p(nodep); } }; -class AstInitArray : public AstNode { +class AstInitArray final : public AstNode { // Set a var to a map of values // The list of initsp() is not relevant // If default is specified, the vector may be sparse, and not provide each value. @@ -4912,7 +4912,7 @@ public: } }; -class AstNew : public AstNodeFTaskRef { +class AstNew final : public AstNodeFTaskRef { // New as constructor // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it // Parents: math|stmt @@ -4928,7 +4928,7 @@ public: virtual int instrCount() const override { return widthInstrs(); } }; -class AstNewCopy : public AstNodeMath { +class AstNewCopy final : public AstNodeMath { // New as shallow copy // Parents: math|stmt // Children: varref|arraysel, math @@ -4948,7 +4948,7 @@ public: AstNode* rhsp() const { return op1p(); } }; -class AstNewDynamic : public AstNodeMath { +class AstNewDynamic final : public AstNodeMath { // New for dynamic array // Parents: math|stmt // Children: varref|arraysel, math @@ -4970,7 +4970,7 @@ public: AstNode* rhsp() const { return op2p(); } }; -class AstPragma : public AstNode { +class AstPragma final : public AstNode { private: AstPragmaType m_pragType; // Type of pragma public: @@ -4988,7 +4988,7 @@ public: } }; -class AstPrintTimeScale : public AstNodeStmt { +class AstPrintTimeScale final : public AstNodeStmt { // Parents: stmtlist string m_name; // Parent module name VTimescale m_timeunit; // Parent module time unit @@ -5010,7 +5010,7 @@ public: VTimescale timeunit() const { return m_timeunit; } }; -class AstStop : public AstNodeStmt { +class AstStop final : public AstNodeStmt { public: AstStop(FileLine* fl, bool maybe) : ASTGEN_SUPER(fl) {} @@ -5029,7 +5029,7 @@ public: } }; -class AstFinish : public AstNodeStmt { +class AstFinish final : public AstNodeStmt { public: explicit AstFinish(FileLine* fl) : ASTGEN_SUPER(fl) {} @@ -5048,7 +5048,7 @@ public: } }; -class AstNullCheck : public AstNodeUniop { +class AstNullCheck final : public AstNodeUniop { // Return LHS after checking that LHS is non-null // Children: VarRef or something returning pointer public: @@ -5071,7 +5071,7 @@ public: } }; -class AstTimingControl : public AstNodeStmt { +class AstTimingControl final : public AstNodeStmt { // Parents: stmtlist public: AstTimingControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp) @@ -5091,7 +5091,7 @@ public: AstNode* stmtsp() const { return op2p(); } }; -class AstTimeFormat : public AstNodeStmt { +class AstTimeFormat final : public AstNodeStmt { // Parents: stmtlist public: AstTimeFormat(FileLine* fl, AstNode* unitsp, AstNode* precisionp, AstNode* suffixp, @@ -5116,7 +5116,7 @@ public: AstNode* widthp() const { return op4p(); } }; -class AstTraceDecl : public AstNodeStmt { +class AstTraceDecl final : public AstNodeStmt { // Trace point declaration // Separate from AstTraceInc; as a declaration can't be deleted // Parents: {statement list} @@ -5170,7 +5170,7 @@ public: AstNode* valuep() const { return op1p(); } }; -class AstTraceInc : public AstNodeStmt { +class AstTraceInc final : public AstNodeStmt { // Trace point dump // Parents: {statement list} // Children: op1: things to emit before this node, @@ -5214,7 +5214,7 @@ public: bool full() const { return m_full; } }; -class AstActive : public AstNode { +class AstActive final : public AstNode { // Block of code with sensitivity activation // Parents: MODULE | CFUNC // Children: SENTREE, statements @@ -5257,7 +5257,7 @@ public: bool hasClocked() const { return m_sensesp->hasClocked(); } }; -class AstAttrOf : public AstNode { +class AstAttrOf final : public AstNode { private: // Return a value of a attribute, for example a LSB or array LSB of a signal AstAttrType m_attrType; // What sort of extraction @@ -5277,7 +5277,7 @@ public: virtual void dump(std::ostream& str = std::cout) const override; }; -class AstScopeName : public AstNodeMath { +class AstScopeName final : public AstNodeMath { // For display %m and DPI context imports // Parents: DISPLAY // Children: TEXT @@ -5319,7 +5319,7 @@ public: void dpiExport(bool flag) { m_dpiExport = flag; } }; -class AstUdpTable : public AstNode { +class AstUdpTable final : public AstNode { public: AstUdpTable(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER(fl) { @@ -5330,7 +5330,7 @@ public: AstUdpTableLine* bodysp() const { return VN_CAST(op1p(), UdpTableLine); } }; -class AstUdpTableLine : public AstNode { +class AstUdpTableLine final : public AstNode { string m_text; public: @@ -5345,7 +5345,7 @@ public: //====================================================================== // non-ary ops -class AstRand : public AstNodeTermop { +class AstRand final : public AstNodeTermop { // Return a random number, based upon width() private: bool m_reset = false; // Random reset, versus always random @@ -5370,7 +5370,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstURandom : public AstNodeTermop { +class AstURandom final : public AstNodeTermop { // $urandom public: explicit AstURandom(FileLine* fl) @@ -5388,7 +5388,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstURandomRange : public AstNodeBiop { +class AstURandomRange final : public AstNodeBiop { // $urandom_range public: explicit AstURandomRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -5414,7 +5414,7 @@ public: virtual int instrCount() const override { return instrCountPli(); } }; -class AstTime : public AstNodeTermop { +class AstTime final : public AstNodeTermop { VTimescale m_timeunit; // Parent module time unit public: AstTime(FileLine* fl, const VTimescale& timeunit) @@ -5436,7 +5436,7 @@ public: VTimescale timeunit() const { return m_timeunit; } }; -class AstTimeD : public AstNodeTermop { +class AstTimeD final : public AstNodeTermop { VTimescale m_timeunit; // Parent module time unit public: AstTimeD(FileLine* fl, const VTimescale& timeunit) @@ -5458,7 +5458,7 @@ public: VTimescale timeunit() const { return m_timeunit; } }; -class AstUCFunc : public AstNodeMath { +class AstUCFunc final : public AstNodeMath { // User's $c function // Perhaps this should be an AstNodeListop; but there's only one list math right now public: @@ -5484,7 +5484,7 @@ public: //====================================================================== // Unary ops -class AstNegate : public AstNodeUniop { +class AstNegate final : public AstNodeUniop { public: AstNegate(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5499,7 +5499,7 @@ public: virtual bool cleanLhs() const override { return false; } virtual bool sizeMattersLhs() const override { return true; } }; -class AstNegateD : public AstNodeUniop { +class AstNegateD final : public AstNodeUniop { public: AstNegateD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5516,7 +5516,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstRedAnd : public AstNodeUniop { +class AstRedAnd final : public AstNodeUniop { public: AstRedAnd(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5530,7 +5530,7 @@ public: virtual bool cleanLhs() const override { return true; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstRedOr : public AstNodeUniop { +class AstRedOr final : public AstNodeUniop { public: AstRedOr(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5544,7 +5544,7 @@ public: virtual bool cleanLhs() const override { return true; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstRedXor : public AstNodeUniop { +class AstRedXor final : public AstNodeUniop { public: AstRedXor(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5562,7 +5562,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } }; -class AstRedXnor : public AstNodeUniop { +class AstRedXnor final : public AstNodeUniop { // AstRedXnors are replaced with AstRedXors in V3Const. public: AstRedXnor(FileLine* fl, AstNode* lhsp) @@ -5582,7 +5582,7 @@ public: virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } }; -class AstLenN : public AstNodeUniop { +class AstLenN final : public AstNodeUniop { // Length of a string public: AstLenN(FileLine* fl, AstNode* lhsp) @@ -5597,7 +5597,7 @@ public: virtual bool cleanLhs() const override { return true; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstLogNot : public AstNodeUniop { +class AstLogNot final : public AstNodeUniop { public: AstLogNot(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5612,7 +5612,7 @@ public: virtual bool cleanLhs() const override { return true; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstNot : public AstNodeUniop { +class AstNot final : public AstNodeUniop { public: AstNot(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5627,7 +5627,7 @@ public: virtual bool cleanLhs() const override { return false; } virtual bool sizeMattersLhs() const override { return true; } }; -class AstExtend : public AstNodeUniop { +class AstExtend final : public AstNodeUniop { // Expand a value into a wider entity by 0 extension. Width is implied from nodep->width() public: AstExtend(FileLine* fl, AstNode* lhsp) @@ -5647,7 +5647,7 @@ public: } virtual int instrCount() const override { return 0; } }; -class AstExtendS : public AstNodeUniop { +class AstExtendS final : public AstNodeUniop { // Expand a value into a wider entity by sign extension. Width is implied from nodep->width() public: AstExtendS(FileLine* fl, AstNode* lhsp) @@ -5671,7 +5671,7 @@ public: virtual int instrCount() const override { return 0; } virtual bool signedFlavor() const override { return true; } }; -class AstSigned : public AstNodeUniop { +class AstSigned final : public AstNodeUniop { // $signed(lhs) public: AstSigned(FileLine* fl, AstNode* lhsp) @@ -5691,7 +5691,7 @@ public: virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters virtual int instrCount() const override { return 0; } }; -class AstUnsigned : public AstNodeUniop { +class AstUnsigned final : public AstNodeUniop { // $unsigned(lhs) public: AstUnsigned(FileLine* fl, AstNode* lhsp) @@ -5711,7 +5711,7 @@ public: virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters virtual int instrCount() const override { return 0; } }; -class AstRToIS : public AstNodeUniop { +class AstRToIS final : public AstNodeUniop { // $rtoi(lhs) public: AstRToIS(FileLine* fl, AstNode* lhsp) @@ -5727,7 +5727,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters virtual int instrCount() const override { return instrCountDouble(); } }; -class AstRToIRoundS : public AstNodeUniop { +class AstRToIRoundS final : public AstNodeUniop { // Convert real to integer, with arbitrary sized output (not just "integer" format) public: AstRToIRoundS(FileLine* fl, AstNode* lhsp) @@ -5745,7 +5745,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return instrCountDouble(); } }; -class AstIToRD : public AstNodeUniop { +class AstIToRD final : public AstNodeUniop { // $itor where lhs is unsigned public: AstIToRD(FileLine* fl, AstNode* lhsp) @@ -5761,7 +5761,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return instrCountDouble(); } }; -class AstISToRD : public AstNodeUniop { +class AstISToRD final : public AstNodeUniop { // $itor where lhs is signed public: AstISToRD(FileLine* fl, AstNode* lhsp) @@ -5778,7 +5778,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return instrCountDouble(); } }; -class AstRealToBits : public AstNodeUniop { +class AstRealToBits final : public AstNodeUniop { public: AstRealToBits(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5795,7 +5795,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters virtual int instrCount() const override { return instrCountDouble(); } }; -class AstBitsToRealD : public AstNodeUniop { +class AstBitsToRealD final : public AstNodeUniop { public: AstBitsToRealD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5813,7 +5813,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } }; -class AstCLog2 : public AstNodeUniop { +class AstCLog2 final : public AstNodeUniop { public: AstCLog2(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -5826,7 +5826,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 16; } }; -class AstCountBits : public AstNodeQuadop { +class AstCountBits final : public AstNodeQuadop { // Number of bits set in vector public: AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p) @@ -5853,7 +5853,7 @@ public: virtual bool sizeMattersFhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 16; } }; -class AstCountOnes : public AstNodeUniop { +class AstCountOnes final : public AstNodeUniop { // Number of bits set in vector public: AstCountOnes(FileLine* fl, AstNode* lhsp) @@ -5869,7 +5869,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 16; } }; -class AstIsUnknown : public AstNodeUniop { +class AstIsUnknown final : public AstNodeUniop { // True if any unknown bits public: AstIsUnknown(FileLine* fl, AstNode* lhsp) @@ -5886,7 +5886,7 @@ public: virtual bool cleanLhs() const override { return false; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstIsUnbounded : public AstNodeUniop { +class AstIsUnbounded final : public AstNodeUniop { // True if is unmbounded ($) public: AstIsUnbounded(FileLine* fl, AstNode* lhsp) @@ -5904,7 +5904,7 @@ public: virtual bool cleanLhs() const override { return false; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstOneHot : public AstNodeUniop { +class AstOneHot final : public AstNodeUniop { // True if only single bit set in vector public: AstOneHot(FileLine* fl, AstNode* lhsp) @@ -5920,7 +5920,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 4; } }; -class AstOneHot0 : public AstNodeUniop { +class AstOneHot0 final : public AstNodeUniop { // True if only single bit, or no bits set in vector public: AstOneHot0(FileLine* fl, AstNode* lhsp) @@ -5937,7 +5937,7 @@ public: virtual int instrCount() const override { return widthInstrs() * 3; } }; -class AstCast : public AstNode { +class AstCast final : public AstNode { // Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc public: AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp) @@ -5959,7 +5959,7 @@ public: virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } }; -class AstCastDynamic : public AstNodeBiop { +class AstCastDynamic final : public AstNodeBiop { // Verilog $cast used as a function // Task usage of $cast is converted during parse to assert($cast(...)) // Parents: MATH @@ -5986,7 +5986,7 @@ public: virtual bool isPure() const override { return true; } }; -class AstCastParse : public AstNode { +class AstCastParse final : public AstNode { // Cast to appropriate type, where we haven't determined yet what the data type is public: AstCastParse(FileLine* fl, AstNode* lhsp, AstNode* dtp) @@ -6004,7 +6004,7 @@ public: AstNode* dtp() const { return op2p(); } }; -class AstCastSize : public AstNode { +class AstCastSize final : public AstNode { // Cast to specific size; signed/twostate inherited from lower element per IEEE public: AstCastSize(FileLine* fl, AstNode* lhsp, AstConst* rhsp) @@ -6022,7 +6022,7 @@ public: AstNode* rhsp() const { return op2p(); } }; -class AstCCast : public AstNodeUniop { +class AstCCast final : public AstNodeUniop { // Cast to C-based data type private: int m_size; @@ -6057,7 +6057,7 @@ public: int size() const { return m_size; } }; -class AstCvtPackString : public AstNodeUniop { +class AstCvtPackString final : public AstNodeUniop { // Convert to Verilator Packed String (aka verilog "string") public: AstCvtPackString(FileLine* fl, AstNode* lhsp) @@ -6075,7 +6075,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstFEof : public AstNodeUniop { +class AstFEof final : public AstNodeUniop { public: AstFEof(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6093,7 +6093,7 @@ public: AstNode* filep() const { return lhsp(); } }; -class AstFError : public AstNodeMath { +class AstFError final : public AstNodeMath { public: AstFError(FileLine* fl, AstNode* filep, AstNode* strp) : ASTGEN_SUPER(fl) { @@ -6118,7 +6118,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstFGetC : public AstNodeUniop { +class AstFGetC final : public AstNodeUniop { public: AstFGetC(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6137,7 +6137,7 @@ public: AstNode* filep() const { return lhsp(); } }; -class AstFUngetC : public AstNodeBiop { +class AstFUngetC final : public AstNodeBiop { public: AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} @@ -6166,7 +6166,7 @@ public: AstNode* charp() const { return rhsp(); } }; -class AstNodeSystemUniop : public AstNodeUniop { +class AstNodeSystemUniop VL_NOT_FINAL : public AstNodeUniop { public: AstNodeSystemUniop(AstType t, FileLine* fl, AstNode* lhsp) : AstNodeUniop(t, fl, lhsp) { @@ -6180,7 +6180,7 @@ public: virtual bool doubleFlavor() const override { return true; } }; -class AstLogD : public AstNodeSystemUniop { +class AstLogD final : public AstNodeSystemUniop { public: AstLogD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6191,7 +6191,7 @@ public: virtual string emitVerilog() override { return "%f$ln(%l)"; } virtual string emitC() override { return "log(%li)"; } }; -class AstLog10D : public AstNodeSystemUniop { +class AstLog10D final : public AstNodeSystemUniop { public: AstLog10D(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6203,7 +6203,7 @@ public: virtual string emitC() override { return "log10(%li)"; } }; -class AstExpD : public AstNodeSystemUniop { +class AstExpD final : public AstNodeSystemUniop { public: AstExpD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6215,7 +6215,7 @@ public: virtual string emitC() override { return "exp(%li)"; } }; -class AstSqrtD : public AstNodeSystemUniop { +class AstSqrtD final : public AstNodeSystemUniop { public: AstSqrtD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6227,7 +6227,7 @@ public: virtual string emitC() override { return "sqrt(%li)"; } }; -class AstFloorD : public AstNodeSystemUniop { +class AstFloorD final : public AstNodeSystemUniop { public: AstFloorD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6239,7 +6239,7 @@ public: virtual string emitC() override { return "floor(%li)"; } }; -class AstCeilD : public AstNodeSystemUniop { +class AstCeilD final : public AstNodeSystemUniop { public: AstCeilD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6251,7 +6251,7 @@ public: virtual string emitC() override { return "ceil(%li)"; } }; -class AstSinD : public AstNodeSystemUniop { +class AstSinD final : public AstNodeSystemUniop { public: AstSinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6263,7 +6263,7 @@ public: virtual string emitC() override { return "sin(%li)"; } }; -class AstCosD : public AstNodeSystemUniop { +class AstCosD final : public AstNodeSystemUniop { public: AstCosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6275,7 +6275,7 @@ public: virtual string emitC() override { return "cos(%li)"; } }; -class AstTanD : public AstNodeSystemUniop { +class AstTanD final : public AstNodeSystemUniop { public: AstTanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6287,7 +6287,7 @@ public: virtual string emitC() override { return "tan(%li)"; } }; -class AstAsinD : public AstNodeSystemUniop { +class AstAsinD final : public AstNodeSystemUniop { public: AstAsinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6299,7 +6299,7 @@ public: virtual string emitC() override { return "asin(%li)"; } }; -class AstAcosD : public AstNodeSystemUniop { +class AstAcosD final : public AstNodeSystemUniop { public: AstAcosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6311,7 +6311,7 @@ public: virtual string emitC() override { return "acos(%li)"; } }; -class AstAtanD : public AstNodeSystemUniop { +class AstAtanD final : public AstNodeSystemUniop { public: AstAtanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6323,7 +6323,7 @@ public: virtual string emitC() override { return "atan(%li)"; } }; -class AstSinhD : public AstNodeSystemUniop { +class AstSinhD final : public AstNodeSystemUniop { public: AstSinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6335,7 +6335,7 @@ public: virtual string emitC() override { return "sinh(%li)"; } }; -class AstCoshD : public AstNodeSystemUniop { +class AstCoshD final : public AstNodeSystemUniop { public: AstCoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6347,7 +6347,7 @@ public: virtual string emitC() override { return "cosh(%li)"; } }; -class AstTanhD : public AstNodeSystemUniop { +class AstTanhD final : public AstNodeSystemUniop { public: AstTanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6359,7 +6359,7 @@ public: virtual string emitC() override { return "tanh(%li)"; } }; -class AstAsinhD : public AstNodeSystemUniop { +class AstAsinhD final : public AstNodeSystemUniop { public: AstAsinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6371,7 +6371,7 @@ public: virtual string emitC() override { return "asinh(%li)"; } }; -class AstAcoshD : public AstNodeSystemUniop { +class AstAcoshD final : public AstNodeSystemUniop { public: AstAcoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6383,7 +6383,7 @@ public: virtual string emitC() override { return "acosh(%li)"; } }; -class AstAtanhD : public AstNodeSystemUniop { +class AstAtanhD final : public AstNodeSystemUniop { public: AstAtanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} @@ -6394,7 +6394,7 @@ public: virtual string emitVerilog() override { return "%f$atanh(%l)"; } virtual string emitC() override { return "atanh(%li)"; } }; -class AstToLowerN : public AstNodeUniop { +class AstToLowerN final : public AstNodeUniop { // string.tolower() public: AstToLowerN(FileLine* fl, AstNode* lhsp) @@ -6411,7 +6411,7 @@ public: virtual bool cleanLhs() const override { return true; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstToUpperN : public AstNodeUniop { +class AstToUpperN final : public AstNodeUniop { // string.toupper() public: AstToUpperN(FileLine* fl, AstNode* lhsp) @@ -6428,7 +6428,7 @@ public: virtual bool cleanLhs() const override { return true; } virtual bool sizeMattersLhs() const override { return false; } }; -class AstTimeImport : public AstNodeUniop { +class AstTimeImport final : public AstNodeUniop { // Take a constant that represents a time and needs conversion based on time units VTimescale m_timeunit; // Parent module time unit public: @@ -6446,7 +6446,7 @@ public: VTimescale timeunit() const { return m_timeunit; } }; -class AstAtoN : public AstNodeUniop { +class AstAtoN final : public AstNodeUniop { // string.atoi(), atobin(), atohex(), atooct(), atoireal() public: enum FmtType { ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1 }; @@ -6494,7 +6494,7 @@ public: //====================================================================== // Binary ops -class AstLogOr : public AstNodeBiop { +class AstLogOr final : public AstNodeBiop { public: AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6517,7 +6517,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; -class AstLogAnd : public AstNodeBiop { +class AstLogAnd final : public AstNodeBiop { public: AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6540,7 +6540,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; -class AstLogEq : public AstNodeBiCom { +class AstLogEq final : public AstNodeBiCom { public: AstLogEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6563,7 +6563,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; -class AstLogIf : public AstNodeBiop { +class AstLogIf final : public AstNodeBiop { public: AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6586,7 +6586,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; -class AstOr : public AstNodeBiComAsv { +class AstOr final : public AstNodeBiComAsv { public: AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6608,7 +6608,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstAnd : public AstNodeBiComAsv { +class AstAnd final : public AstNodeBiComAsv { public: AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6630,7 +6630,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstXor : public AstNodeBiComAsv { +class AstXor final : public AstNodeBiComAsv { public: AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6652,7 +6652,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstXnor : public AstNodeBiComAsv { +class AstXnor final : public AstNodeBiComAsv { public: AstXnor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6674,7 +6674,7 @@ public: virtual bool sizeMattersLhs() const override { return true; } virtual bool sizeMattersRhs() const override { return true; } }; -class AstEq : public AstNodeBiCom { +class AstEq final : public AstNodeBiCom { public: AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6698,7 +6698,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstEqD : public AstNodeBiCom { +class AstEqD final : public AstNodeBiCom { public: AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6722,7 +6722,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstEqN : public AstNodeBiCom { +class AstEqN final : public AstNodeBiCom { public: AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6746,7 +6746,7 @@ public: virtual int instrCount() const override { return instrCountString(); } virtual bool stringFlavor() const override { return true; } }; -class AstNeq : public AstNodeBiCom { +class AstNeq final : public AstNodeBiCom { public: AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6768,7 +6768,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstNeqD : public AstNodeBiCom { +class AstNeqD final : public AstNodeBiCom { public: AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6792,7 +6792,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstNeqN : public AstNodeBiCom { +class AstNeqN final : public AstNodeBiCom { public: AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6816,7 +6816,7 @@ public: virtual int instrCount() const override { return instrCountString(); } virtual bool stringFlavor() const override { return true; } }; -class AstLt : public AstNodeBiop { +class AstLt final : public AstNodeBiop { public: AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6838,7 +6838,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstLtD : public AstNodeBiop { +class AstLtD final : public AstNodeBiop { public: AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6862,7 +6862,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstLtS : public AstNodeBiop { +class AstLtS final : public AstNodeBiop { public: AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6885,7 +6885,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual bool signedFlavor() const override { return true; } }; -class AstLtN : public AstNodeBiop { +class AstLtN final : public AstNodeBiop { public: AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6909,7 +6909,7 @@ public: virtual int instrCount() const override { return instrCountString(); } virtual bool stringFlavor() const override { return true; } }; -class AstGt : public AstNodeBiop { +class AstGt final : public AstNodeBiop { public: AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6931,7 +6931,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstGtD : public AstNodeBiop { +class AstGtD final : public AstNodeBiop { public: AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6955,7 +6955,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstGtS : public AstNodeBiop { +class AstGtS final : public AstNodeBiop { public: AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -6978,7 +6978,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual bool signedFlavor() const override { return true; } }; -class AstGtN : public AstNodeBiop { +class AstGtN final : public AstNodeBiop { public: AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7002,7 +7002,7 @@ public: virtual int instrCount() const override { return instrCountString(); } virtual bool stringFlavor() const override { return true; } }; -class AstGte : public AstNodeBiop { +class AstGte final : public AstNodeBiop { public: AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7026,7 +7026,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstGteD : public AstNodeBiop { +class AstGteD final : public AstNodeBiop { public: AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7050,7 +7050,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstGteS : public AstNodeBiop { +class AstGteS final : public AstNodeBiop { public: AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7073,7 +7073,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual bool signedFlavor() const override { return true; } }; -class AstGteN : public AstNodeBiop { +class AstGteN final : public AstNodeBiop { public: AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7097,7 +7097,7 @@ public: virtual int instrCount() const override { return instrCountString(); } virtual bool stringFlavor() const override { return true; } }; -class AstLte : public AstNodeBiop { +class AstLte final : public AstNodeBiop { public: AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7121,7 +7121,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstLteD : public AstNodeBiop { +class AstLteD final : public AstNodeBiop { public: AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7145,7 +7145,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstLteS : public AstNodeBiop { +class AstLteS final : public AstNodeBiop { public: AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7168,7 +7168,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual bool signedFlavor() const override { return true; } }; -class AstLteN : public AstNodeBiop { +class AstLteN final : public AstNodeBiop { public: AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7192,7 +7192,7 @@ public: virtual int instrCount() const override { return instrCountString(); } virtual bool stringFlavor() const override { return true; } }; -class AstShiftL : public AstNodeBiop { +class AstShiftL final : public AstNodeBiop { public: AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7214,7 +7214,7 @@ public: virtual bool sizeMattersLhs() const override { return true; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstShiftR : public AstNodeBiop { +class AstShiftR final : public AstNodeBiop { public: AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7237,7 +7237,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstShiftRS : public AstNodeBiop { +class AstShiftRS final : public AstNodeBiop { // Shift right with sign extension, >>> operator // Output data type's width determines which bit is used for sign extension public: @@ -7263,7 +7263,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual bool signedFlavor() const override { return true; } }; -class AstAdd : public AstNodeBiComAsv { +class AstAdd final : public AstNodeBiComAsv { public: AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7285,7 +7285,7 @@ public: virtual bool sizeMattersLhs() const override { return true; } virtual bool sizeMattersRhs() const override { return true; } }; -class AstAddD : public AstNodeBiComAsv { +class AstAddD final : public AstNodeBiComAsv { public: AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7309,7 +7309,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstSub : public AstNodeBiop { +class AstSub final : public AstNodeBiop { public: AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7331,7 +7331,7 @@ public: virtual bool sizeMattersLhs() const override { return true; } virtual bool sizeMattersRhs() const override { return true; } }; -class AstSubD : public AstNodeBiop { +class AstSubD final : public AstNodeBiop { public: AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7355,7 +7355,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstMul : public AstNodeBiComAsv { +class AstMul final : public AstNodeBiComAsv { public: AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7378,7 +7378,7 @@ public: virtual bool sizeMattersRhs() const override { return true; } virtual int instrCount() const override { return widthInstrs() * instrCountMul(); } }; -class AstMulD : public AstNodeBiComAsv { +class AstMulD final : public AstNodeBiComAsv { public: AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7402,7 +7402,7 @@ public: virtual int instrCount() const override { return instrCountDouble(); } virtual bool doubleFlavor() const override { return true; } }; -class AstMulS : public AstNodeBiComAsv { +class AstMulS final : public AstNodeBiComAsv { public: AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7427,7 +7427,7 @@ public: virtual int instrCount() const override { return widthInstrs() * instrCountMul(); } virtual bool signedFlavor() const override { return true; } }; -class AstDiv : public AstNodeBiop { +class AstDiv final : public AstNodeBiop { public: AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7449,7 +7449,7 @@ public: virtual bool sizeMattersRhs() const override { return true; } virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } }; -class AstDivD : public AstNodeBiop { +class AstDivD final : public AstNodeBiop { public: AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7473,7 +7473,7 @@ public: virtual int instrCount() const override { return instrCountDoubleDiv(); } virtual bool doubleFlavor() const override { return true; } }; -class AstDivS : public AstNodeBiop { +class AstDivS final : public AstNodeBiop { public: AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7496,7 +7496,7 @@ public: virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } virtual bool signedFlavor() const override { return true; } }; -class AstModDiv : public AstNodeBiop { +class AstModDiv final : public AstNodeBiop { public: AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7518,7 +7518,7 @@ public: virtual bool sizeMattersRhs() const override { return true; } virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } }; -class AstModDivS : public AstNodeBiop { +class AstModDivS final : public AstNodeBiop { public: AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7541,7 +7541,7 @@ public: virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } virtual bool signedFlavor() const override { return true; } }; -class AstPow : public AstNodeBiop { +class AstPow final : public AstNodeBiop { public: AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7564,7 +7564,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } }; -class AstPowD : public AstNodeBiop { +class AstPowD final : public AstNodeBiop { public: AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7587,7 +7587,7 @@ public: virtual int instrCount() const override { return instrCountDoubleDiv() * 5; } virtual bool doubleFlavor() const override { return true; } }; -class AstPowSU : public AstNodeBiop { +class AstPowSU final : public AstNodeBiop { public: AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7613,7 +7613,7 @@ public: virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } virtual bool signedFlavor() const override { return true; } }; -class AstPowSS : public AstNodeBiop { +class AstPowSS final : public AstNodeBiop { public: AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7639,7 +7639,7 @@ public: virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } virtual bool signedFlavor() const override { return true; } }; -class AstPowUS : public AstNodeBiop { +class AstPowUS final : public AstNodeBiop { public: AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7665,7 +7665,7 @@ public: virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } virtual bool signedFlavor() const override { return true; } }; -class AstPreAdd : public AstNodeTriop { +class AstPreAdd final : public AstNodeTriop { // Pre-increment/add // Parents: MATH // Children: lhsp: AstConst (1) as currently support only ++ not += @@ -7690,7 +7690,7 @@ public: virtual bool sizeMattersRhs() const override { return true; } virtual bool sizeMattersThs() const override { return true; } }; -class AstPreSub : public AstNodeTriop { +class AstPreSub final : public AstNodeTriop { // Pre-decrement/subtract // Parents: MATH // Children: lhsp: AstConst (1) as currently support only -- not -= @@ -7715,7 +7715,7 @@ public: virtual bool sizeMattersRhs() const override { return true; } virtual bool sizeMattersThs() const override { return true; } }; -class AstPostAdd : public AstNodeTriop { +class AstPostAdd final : public AstNodeTriop { // Post-increment/add // Parents: MATH // Children: lhsp: AstConst (1) as currently support only ++ not += @@ -7740,7 +7740,7 @@ public: virtual bool sizeMattersRhs() const override { return true; } virtual bool sizeMattersThs() const override { return true; } }; -class AstPostSub : public AstNodeTriop { +class AstPostSub final : public AstNodeTriop { // Post-decrement/subtract // Parents: MATH // Children: lhsp: AstConst (1) as currently support only -- not -= @@ -7765,7 +7765,7 @@ public: virtual bool sizeMattersRhs() const override { return true; } virtual bool sizeMattersThs() const override { return true; } }; -class AstEqCase : public AstNodeBiCom { +class AstEqCase final : public AstNodeBiCom { public: AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7787,7 +7787,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstNeqCase : public AstNodeBiCom { +class AstNeqCase final : public AstNodeBiCom { public: AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7809,7 +7809,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstEqWild : public AstNodeBiop { +class AstEqWild final : public AstNodeBiop { // Note wildcard operator rhs differs from lhs public: AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -7834,7 +7834,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstNeqWild : public AstNodeBiop { +class AstNeqWild final : public AstNodeBiop { public: AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { @@ -7856,7 +7856,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstConcat : public AstNodeBiop { +class AstConcat final : public AstNodeBiop { // If you're looking for {#{}}, see AstReplicate public: AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -7882,7 +7882,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 2; } }; -class AstConcatN : public AstNodeBiop { +class AstConcatN final : public AstNodeBiop { // String concatenate public: AstConcatN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -7906,7 +7906,7 @@ public: virtual int instrCount() const override { return instrCountString(); } virtual bool stringFlavor() const override { return true; } }; -class AstReplicate : public AstNodeBiop { +class AstReplicate final : public AstNodeBiop { // Also used as a "Uniop" flavor of Concat, e.g. "{a}" // Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp() public: @@ -7936,7 +7936,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 2; } }; -class AstReplicateN : public AstNodeBiop { +class AstReplicateN final : public AstNodeBiop { // String replicate public: AstReplicateN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -7962,7 +7962,7 @@ public: virtual int instrCount() const override { return widthInstrs() * 2; } virtual bool stringFlavor() const override { return true; } }; -class AstStreamL : public AstNodeStream { +class AstStreamL final : public AstNodeStream { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() public: AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -7983,7 +7983,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 2; } }; -class AstStreamR : public AstNodeStream { +class AstStreamR final : public AstNodeStream { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() public: AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -8004,7 +8004,7 @@ public: virtual bool sizeMattersRhs() const override { return false; } virtual int instrCount() const override { return widthInstrs() * 2; } }; -class AstBufIf1 : public AstNodeBiop { +class AstBufIf1 final : public AstNodeBiop { // lhs is enable, rhs is data to drive // Note unlike the Verilog bufif1() UDP, this allows any width; each lhsp // bit enables respective rhsp bit @@ -8029,7 +8029,7 @@ public: virtual bool sizeMattersLhs() const override { return false; } virtual bool sizeMattersRhs() const override { return false; } }; -class AstFGetS : public AstNodeBiop { +class AstFGetS final : public AstNodeBiop { public: AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} @@ -8055,7 +8055,7 @@ public: AstNode* filep() const { return rhsp(); } }; -class AstNodeSystemBiop : public AstNodeBiop { +class AstNodeSystemBiop VL_NOT_FINAL : public AstNodeBiop { public: AstNodeSystemBiop(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(t, fl, lhsp, rhsp) { @@ -8070,7 +8070,7 @@ public: virtual bool doubleFlavor() const override { return true; } }; -class AstAtan2D : public AstNodeSystemBiop { +class AstAtan2D final : public AstNodeSystemBiop { public: AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} @@ -8085,7 +8085,7 @@ public: virtual string emitC() override { return "atan2(%li,%ri)"; } }; -class AstHypotD : public AstNodeSystemBiop { +class AstHypotD final : public AstNodeSystemBiop { public: AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} @@ -8100,7 +8100,7 @@ public: virtual string emitC() override { return "hypot(%li,%ri)"; } }; -class AstPutcN : public AstNodeTriop { +class AstPutcN final : public AstNodeTriop { // Verilog string.putc() public: AstPutcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) @@ -8126,7 +8126,7 @@ public: virtual bool isHeavy() const override { return true; } }; -class AstGetcN : public AstNodeBiop { +class AstGetcN final : public AstNodeBiop { // Verilog string.getc() public: AstGetcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) @@ -8152,7 +8152,7 @@ public: virtual bool isHeavy() const override { return true; } }; -class AstGetcRefN : public AstNodeBiop { +class AstGetcRefN final : public AstNodeBiop { // Verilog string[#] on the left-hand-side of assignment // Spec says is of type byte (not string of single character) public: @@ -8178,7 +8178,7 @@ public: virtual bool isHeavy() const override { return true; } }; -class AstSubstrN : public AstNodeTriop { +class AstSubstrN final : public AstNodeTriop { // Verilog string.substr() public: AstSubstrN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) @@ -8204,7 +8204,7 @@ public: virtual bool isHeavy() const override { return true; } }; -class AstCompareNN : public AstNodeBiop { +class AstCompareNN final : public AstNodeBiop { // Verilog str.compare() and str.icompare() private: bool m_ignoreCase; // True for str.icompare() @@ -8237,7 +8237,7 @@ public: virtual bool isHeavy() const override { return true; } }; -class AstFell : public AstNodeMath { +class AstFell final : public AstNodeMath { // Verilog $fell // Parents: math // Children: expression @@ -8259,7 +8259,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstPast : public AstNodeMath { +class AstPast final : public AstNodeMath { // Verilog $past // Parents: math // Children: expression @@ -8283,7 +8283,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstRose : public AstNodeMath { +class AstRose final : public AstNodeMath { // Verilog $rose // Parents: math // Children: expression @@ -8305,7 +8305,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstSampled : public AstNodeMath { +class AstSampled final : public AstNodeMath { // Verilog $sampled // Parents: math // Children: expression @@ -8325,7 +8325,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstStable : public AstNodeMath { +class AstStable final : public AstNodeMath { // Verilog $stable // Parents: math // Children: expression @@ -8347,7 +8347,7 @@ public: virtual bool same(const AstNode* samep) const override { return true; } }; -class AstPattern : public AstNodeMath { +class AstPattern final : public AstNodeMath { // Verilog '{a,b,c,d...} // Parents: AstNodeAssign, AstPattern, ... // Children: expression, AstPattern, AstPatReplicate @@ -8369,7 +8369,7 @@ public: void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNode* itemsp() const { return op2p(); } // op2 = AstPatReplicate, AstPatMember, etc }; -class AstPatMember : public AstNodeMath { +class AstPatMember final : public AstNodeMath { // Verilog '{a} or '{a{b}} // Parents: AstPattern // Children: expression, AstPattern, replication count @@ -8396,7 +8396,7 @@ public: void isDefault(bool flag) { m_default = flag; } }; -class AstImplication : public AstNodeMath { +class AstImplication final : public AstNodeMath { // Verilog |-> |=> // Parents: math // Children: expression @@ -8425,7 +8425,7 @@ public: //====================================================================== // Assertions -class AstClocking : public AstNode { +class AstClocking final : public AstNode { // Set default clock region // Parents: MODULE // Children: Assertions @@ -8444,7 +8444,7 @@ public: //====================================================================== // PSL -class AstPropClocked : public AstNode { +class AstPropClocked final : public AstNode { // A clocked property // Parents: ASSERT|COVER (property) // Children: SENITEM, Properties @@ -8464,7 +8464,7 @@ public: AstNode* propp() const { return op3p(); } // op3 = property }; -class AstNodeCoverOrAssert : public AstNodeStmt { +class AstNodeCoverOrAssert VL_NOT_FINAL : public AstNodeStmt { // Cover or Assert // Parents: {statement list} // Children: expression, report string @@ -8493,7 +8493,7 @@ public: bool immediate() const { return m_immediate; } }; -class AstAssert : public AstNodeCoverOrAssert { +class AstAssert final : public AstNodeCoverOrAssert { public: ASTNODE_NODE_FUNCS(Assert) AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, @@ -8504,7 +8504,7 @@ public: AstNode* failsp() const { return op3p(); } // op3 = if assertion fails }; -class AstCover : public AstNodeCoverOrAssert { +class AstCover final : public AstNodeCoverOrAssert { public: ASTNODE_NODE_FUNCS(Cover) AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, bool immediate, @@ -8515,7 +8515,7 @@ public: virtual bool immediate() const { return false; } }; -class AstRestrict : public AstNodeCoverOrAssert { +class AstRestrict final : public AstNodeCoverOrAssert { public: ASTNODE_NODE_FUNCS(Restrict) AstRestrict(FileLine* fl, AstNode* propp) @@ -8525,7 +8525,7 @@ public: //====================================================================== // Text based nodes -class AstNodeSimpleText : public AstNodeText { +class AstNodeSimpleText VL_NOT_FINAL : public AstNodeText { private: bool m_tracking; // When emit, it's ok to parse the string to do indentation public: @@ -8537,14 +8537,14 @@ public: bool tracking() const { return m_tracking; } }; -class AstText : public AstNodeSimpleText { +class AstText final : public AstNodeSimpleText { public: AstText(FileLine* fl, const string& textp, bool tracking = false) : ASTGEN_SUPER(fl, textp, tracking) {} ASTNODE_NODE_FUNCS(Text) }; -class AstTextBlock : public AstNodeSimpleText { +class AstTextBlock final : public AstNodeSimpleText { private: bool m_commas; // Comma separate emitted children public: @@ -8562,7 +8562,7 @@ public: } }; -class AstScCtor : public AstNodeText { +class AstScCtor final : public AstNodeText { public: AstScCtor(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} @@ -8571,7 +8571,7 @@ public: virtual bool isOutputter() const override { return true; } }; -class AstScDtor : public AstNodeText { +class AstScDtor final : public AstNodeText { public: AstScDtor(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} @@ -8580,7 +8580,7 @@ public: virtual bool isOutputter() const override { return true; } }; -class AstScHdr : public AstNodeText { +class AstScHdr final : public AstNodeText { public: AstScHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} @@ -8589,7 +8589,7 @@ public: virtual bool isOutputter() const override { return true; } }; -class AstScImp : public AstNodeText { +class AstScImp final : public AstNodeText { public: AstScImp(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} @@ -8598,7 +8598,7 @@ public: virtual bool isOutputter() const override { return true; } }; -class AstScImpHdr : public AstNodeText { +class AstScImpHdr final : public AstNodeText { public: AstScImpHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} @@ -8607,7 +8607,7 @@ public: virtual bool isOutputter() const override { return true; } }; -class AstScInt : public AstNodeText { +class AstScInt final : public AstNodeText { public: AstScInt(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} @@ -8616,7 +8616,7 @@ public: virtual bool isOutputter() const override { return true; } }; -class AstUCStmt : public AstNodeStmt { +class AstUCStmt final : public AstNodeStmt { // User $c statement public: AstUCStmt(FileLine* fl, AstNode* exprsp) @@ -8636,7 +8636,7 @@ public: //====================================================================== // Emitted file nodes -class AstNodeFile : public AstNode { +class AstNodeFile VL_NOT_FINAL : public AstNode { // Emitted Otput file // Parents: NETLIST // Children: AstTextBlock @@ -8659,7 +8659,7 @@ public: //====================================================================== // Emit V nodes -class AstVFile : public AstNodeFile { +class AstVFile final : public AstNodeFile { // Verilog output file // Parents: NETLIST public: @@ -8672,7 +8672,7 @@ public: //====================================================================== // Emit C nodes -class AstCFile : public AstNodeFile { +class AstCFile final : public AstNodeFile { // C++ output file // Parents: NETLIST private: @@ -8695,7 +8695,7 @@ public: void support(bool flag) { m_support = flag; } }; -class AstCFunc : public AstNode { +class AstCFunc final : public AstNode { // C++ function // Parents: MODULE/SCOPE // Children: VAR/statements @@ -8847,7 +8847,7 @@ public: } }; -class AstCCall : public AstNodeCCall { +class AstCCall final : public AstNodeCCall { // C++ function call // Parents: Anything above a statement // Children: Args to the function @@ -8861,7 +8861,7 @@ public: ASTNODE_NODE_FUNCS(CCall) }; -class AstCMethodCall : public AstNodeCCall { +class AstCMethodCall final : public AstNodeCCall { // C++ method call // Parents: Anything above a statement // Children: Args to the function @@ -8882,7 +8882,7 @@ public: void fromp(AstNode* nodep) { setOp1p(nodep); } }; -class AstCNew : public AstNodeCCall { +class AstCNew final : public AstNodeCCall { // C++ new() call // Parents: Anything above an expression // Children: Args to the function @@ -8899,7 +8899,7 @@ public: ASTNODE_NODE_FUNCS(CNew) }; -class AstCReturn : public AstNodeStmt { +class AstCReturn final : public AstNodeStmt { // C++ return from a function // Parents: CFUNC/statement // Children: Math @@ -8916,7 +8916,7 @@ public: AstNode* lhsp() const { return op1p(); } }; -class AstCMath : public AstNodeMath { +class AstCMath final : public AstNodeMath { private: bool m_cleanOut; bool m_pure; // Pure optimizable @@ -8950,7 +8950,7 @@ public: void pure(bool flag) { m_pure = flag; } }; -class AstCReset : public AstNodeStmt { +class AstCReset final : public AstNodeStmt { // Reset variable at startup public: AstCReset(FileLine* fl, AstNode* exprsp) @@ -8965,7 +8965,7 @@ public: AstVarRef* varrefp() const { return VN_CAST(op1p(), VarRef); } // op1 = varref to reset }; -class AstCStmt : public AstNodeStmt { +class AstCStmt final : public AstNodeStmt { // Emit C statement public: AstCStmt(FileLine* fl, AstNode* exprsp) @@ -8985,7 +8985,7 @@ public: AstNode* bodysp() const { return op1p(); } // op1 = expressions to print }; -class AstCUse : public AstNode { +class AstCUse final : public AstNode { // C++ use of a class or #include; indicates need of forward declaration // Parents: NODEMODULE private: @@ -9004,7 +9004,7 @@ public: void useType(VUseType useType) { m_useType = useType; } }; -class AstMTaskBody : public AstNode { +class AstMTaskBody final : public AstNode { // Hold statements for each MTask private: ExecMTask* m_execMTaskp = nullptr; @@ -9024,7 +9024,7 @@ public: virtual void dump(std::ostream& str = std::cout) const override; }; -class AstExecGraph : public AstNode { +class AstExecGraph final : public AstNode { // For parallel execution, this node contains a dependency graph. Each // node in the graph is an ExecMTask, which contains a body for the // mtask, which contains a set of AstActive's, each of which calls a @@ -9048,7 +9048,7 @@ public: void addMTaskBody(AstMTaskBody* bodyp) { addOp1p(bodyp); } }; -class AstSplitPlaceholder : public AstNode { +class AstSplitPlaceholder final : public AstNode { public: // Dummy node used within V3Split; never exists outside of V3Split. explicit AstSplitPlaceholder(FileLine* fl) @@ -9059,7 +9059,7 @@ public: //###################################################################### // Right below top -class AstTypeTable : public AstNode { +class AstTypeTable final : public AstNode { // Container for hash of standard data types // Children: NODEDTYPEs AstVoidDType* m_voidp = nullptr; @@ -9093,7 +9093,7 @@ public: //###################################################################### // Top -class AstNetlist : public AstNode { +class AstNetlist final : public AstNode { // All modules are under this single top node. // Parents: none // Children: MODULEs & CFILEs diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 31190eca8..3f92f8081 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -36,7 +36,7 @@ //###################################################################### -class BeginState { +class BeginState final { private: // NODE STATE // Entire netlist: @@ -56,7 +56,7 @@ public: //###################################################################### -class BeginVisitor : public AstNVisitor { +class BeginVisitor final : public AstNVisitor { private: // STATE BeginState* m_statep; // Current global state @@ -247,7 +247,7 @@ public: //###################################################################### -class BeginRelinkVisitor : public AstNVisitor { +class BeginRelinkVisitor final : public AstNVisitor { // Replace tasks with new pointer private: // NODE STATE diff --git a/src/V3Begin.h b/src/V3Begin.h index 9b360c35c..fcd0a33f9 100644 --- a/src/V3Begin.h +++ b/src/V3Begin.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Begin { +class V3Begin final { public: static void debeginAll(AstNetlist* nodep); }; diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp index 325ba2900..34901d20e 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -35,7 +35,7 @@ //###################################################################### // Branch state, as a visitor of each AstNode -class BranchVisitor : public AstNVisitor { +class BranchVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3Branch.h b/src/V3Branch.h index 9a82514a7..d8ebed0f5 100644 --- a/src/V3Branch.h +++ b/src/V3Branch.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Branch { +class V3Branch final { public: // CONSTRUCTORS static void branchAll(AstNetlist* nodep); diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index d76a9241c..fe3c481c9 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -36,7 +36,7 @@ //###################################################################### -class BrokenTable : public AstNVisitor { +class BrokenTable final : public AstNVisitor { // Table of brokenExists node pointers private: // MEMBERS @@ -211,7 +211,7 @@ bool AstNode::brokeExistsBelow() const { //###################################################################### -class BrokenMarkVisitor : public AstNVisitor { +class BrokenMarkVisitor final : public AstNVisitor { // Mark every node in the tree private: // NODE STATE @@ -237,7 +237,7 @@ public: //###################################################################### // Broken state, as a visitor of each AstNode -class BrokenCheckVisitor : public AstNVisitor { +class BrokenCheckVisitor final : public AstNVisitor { bool m_inScope = false; // Under AstScope private: diff --git a/src/V3Broken.h b/src/V3Broken.h index 104765f03..ee7d718f6 100644 --- a/src/V3Broken.h +++ b/src/V3Broken.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Broken { +class V3Broken final { public: static void brokenAll(AstNetlist* nodep); static void addNewed(AstNode* nodep); diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index eb3a88d5d..1dc6b9b04 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -34,7 +34,7 @@ #include #include -class V3CCtorsVisitor { +class V3CCtorsVisitor final { private: string m_basename; string m_argsp; diff --git a/src/V3CCtors.h b/src/V3CCtors.h index 1592d19c9..533a0e819 100644 --- a/src/V3CCtors.h +++ b/src/V3CCtors.h @@ -25,7 +25,7 @@ //============================================================================ -class V3CCtors { +class V3CCtors final { public: static void cctorsAll(); diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index 86f97dd74..3bf389464 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -36,7 +36,7 @@ //###################################################################### -class CUseState { +class CUseState final { private: // MEMBERS AstNodeModule* m_modInsertp; // Current module to insert AstCUse under @@ -75,7 +75,7 @@ public: // Visit within a module all nodes and data types they reference, finding // any classes so we can make sure they are defined when Verilated code // compiles -class CUseDTypeVisitor : public AstNVisitor { +class CUseDTypeVisitor final : public AstNVisitor { // MEMBERS CUseState& m_stater; // State for inserter bool m_impOnly = false; // In details needed only for implementation @@ -113,7 +113,7 @@ public: VL_UNCOPYABLE(CUseDTypeVisitor); }; -class CUseVisitor : public AstNVisitor { +class CUseVisitor final : public AstNVisitor { // MEMBERS CUseState m_state; // Inserter state diff --git a/src/V3CUse.h b/src/V3CUse.h index ffae09a46..d3d0a44af 100644 --- a/src/V3CUse.h +++ b/src/V3CUse.h @@ -25,7 +25,7 @@ //============================================================================ -class V3CUse { +class V3CUse final { public: static void cUseAll(); }; diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 31c0bfeec..3b36aa6ba 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -50,7 +50,7 @@ //###################################################################### -class CaseLintVisitor : public AstNVisitor { +class CaseLintVisitor final : public AstNVisitor { private: AstNodeCase* m_caseExprp = nullptr; // Under a CASE value node, if so the relevant case statement @@ -117,7 +117,7 @@ public: //###################################################################### // Case state, as a visitor of each AstNode -class CaseVisitor : public AstNVisitor { +class CaseVisitor final : public AstNVisitor { private: // NODE STATE // Cleared each Case diff --git a/src/V3Case.h b/src/V3Case.h index 1e4d916b6..35d4abbf7 100644 --- a/src/V3Case.h +++ b/src/V3Case.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Case { +class V3Case final { public: static void caseAll(AstNetlist* nodep); static void caseLint(AstNodeCase* nodep); diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index e2fe21ccb..355516acb 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -49,7 +49,7 @@ //###################################################################### // Cast state, as a visitor of each AstNode -class CastVisitor : public AstNVisitor { +class CastVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3Cast.h b/src/V3Cast.h index d18fc641b..ab9ad4dc0 100644 --- a/src/V3Cast.h +++ b/src/V3Cast.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Cast { +class V3Cast final { public: static void castAll(AstNetlist* nodep); }; diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 65e69ed04..dfb70a833 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -41,7 +41,7 @@ constexpr int CDC_WEIGHT_ASYNC = 0x1000; // Weight for edges that feed async lo //###################################################################### -class CdcBaseVisitor : public AstNVisitor { +class CdcBaseVisitor VL_NOT_FINAL : public AstNVisitor { public: VL_DEBUG_FUNC; // Declare debug() }; @@ -49,7 +49,7 @@ public: //###################################################################### // Graph support classes -class CdcEitherVertex : public V3GraphVertex { +class CdcEitherVertex VL_NOT_FINAL : public V3GraphVertex { AstScope* m_scopep; AstNode* m_nodep; AstSenTree* m_srcDomainp = nullptr; @@ -83,7 +83,7 @@ public: void asyncPath(bool flag) { m_asyncPath = flag; } }; -class CdcVarVertex : public CdcEitherVertex { +class CdcVarVertex final : public CdcEitherVertex { AstVarScope* m_varScp; int m_cntAsyncRst = 0; bool m_fromFlop = false; @@ -105,7 +105,7 @@ public: void fromFlop(bool flag) { m_fromFlop = flag; } }; -class CdcLogicVertex : public CdcEitherVertex { +class CdcLogicVertex final : public CdcEitherVertex { bool m_hazard : 1; bool m_isFlop : 1; @@ -135,7 +135,7 @@ public: //###################################################################### -class CdcDumpVisitor : public CdcBaseVisitor { +class CdcDumpVisitor final : public CdcBaseVisitor { private: // NODE STATE // Entire netlist: @@ -175,7 +175,7 @@ public: //###################################################################### -class CdcWidthVisitor : public CdcBaseVisitor { +class CdcWidthVisitor final : public CdcBaseVisitor { private: int m_maxLineno = 0; size_t m_maxFilenameLen = 0; @@ -209,7 +209,7 @@ public: //###################################################################### // Cdc class functions -class CdcVisitor : public CdcBaseVisitor { +class CdcVisitor final : public CdcBaseVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3Cdc.h b/src/V3Cdc.h index cd6b33f30..9d59849f1 100644 --- a/src/V3Cdc.h +++ b/src/V3Cdc.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Cdc { +class V3Cdc final { public: static void cdcAll(AstNetlist* nodep); }; diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 7cf53bdfa..dbe1905b7 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -38,7 +38,7 @@ //###################################################################### -class ChangedState { +class ChangedState final { public: // STATE AstNodeModule* m_topModp = nullptr; // Top module @@ -94,7 +94,7 @@ public: //###################################################################### // Utility visitor to find elements to be compared -class ChangedInsertVisitor : public AstNVisitor { +class ChangedInsertVisitor final : public AstNVisitor { private: // STATE ChangedState* m_statep; // Shared state across visitors @@ -214,7 +214,7 @@ public: //###################################################################### // Changed state, as a visitor of each AstNode -class ChangedVisitor : public AstNVisitor { +class ChangedVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3Changed.h b/src/V3Changed.h index 311a0c371..79c56cb27 100644 --- a/src/V3Changed.h +++ b/src/V3Changed.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Changed { +class V3Changed final { public: static void changedAll(AstNetlist* nodep); }; diff --git a/src/V3Class.cpp b/src/V3Class.cpp index ebde82354..69c25783c 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -29,7 +29,7 @@ //###################################################################### -class ClassVisitor : public AstNVisitor { +class ClassVisitor final : public AstNVisitor { private: // MEMBERS AstUser1InUse m_inuser1; diff --git a/src/V3Class.h b/src/V3Class.h index f93be9a71..a436bd9ed 100644 --- a/src/V3Class.h +++ b/src/V3Class.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Class { +class V3Class final { public: static void classAll(AstNetlist* nodep); }; diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index e1ebe1fa0..458e366fe 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -35,7 +35,7 @@ //###################################################################### // Clean state, as a visitor of each AstNode -class CleanVisitor : public AstNVisitor { +class CleanVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3Clean.h b/src/V3Clean.h index 76b212a80..76223d2ee 100644 --- a/src/V3Clean.h +++ b/src/V3Clean.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Clean { +class V3Clean final { public: static void cleanAll(AstNetlist* nodep); }; diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 77a7d6ff7..ecb1f939b 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -40,7 +40,7 @@ //###################################################################### // Clock state, as a visitor of each AstNode -class ClockVisitor : public AstNVisitor { +class ClockVisitor final : public AstNVisitor { private: // NODE STATE // Cleared each Module: diff --git a/src/V3Clock.h b/src/V3Clock.h index c2301a8e3..de0ae9f2f 100644 --- a/src/V3Clock.h +++ b/src/V3Clock.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Clock { +class V3Clock final { public: static void clockAll(AstNetlist* nodep); }; diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index 70fcd589d..795f1a8b1 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -51,7 +51,7 @@ constexpr int COMBINE_MIN_STATEMENTS = 50; // Min # of statements to be worth m //###################################################################### -class CombBaseVisitor : public AstNVisitor { +class CombBaseVisitor VL_NOT_FINAL : public AstNVisitor { protected: // STATE @@ -63,7 +63,7 @@ protected: //###################################################################### // Combine replacement function -class CombCallVisitor : CombBaseVisitor { +class CombCallVisitor final : CombBaseVisitor { // Find all CCALLS of each CFUNC, so that we can later rename them private: // NODE STATE @@ -139,7 +139,7 @@ public: //###################################################################### // Combine marking function -class CombMarkVisitor : CombBaseVisitor { +class CombMarkVisitor final : CombBaseVisitor { // Mark all nodes under specified one. private: // OUTPUT: @@ -159,7 +159,7 @@ public: //###################################################################### // Combine state, as a visitor of each AstNode -class CombineVisitor : CombBaseVisitor { +class CombineVisitor final : CombBaseVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3Combine.h b/src/V3Combine.h index 39a223fe8..aee53c2ae 100644 --- a/src/V3Combine.h +++ b/src/V3Combine.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Combine { +class V3Combine final { public: static void combineAll(AstNetlist* nodep); }; diff --git a/src/V3Config.cpp b/src/V3Config.cpp index e37421159..3498e66fb 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -82,7 +82,7 @@ public: }; // Only public_flat_rw has the sensitity tree -class V3ConfigVarAttr { +class V3ConfigVarAttr final { public: AstAttrType m_type; // Type of attribute AstSenTree* m_sentreep; // Sensitivity tree for public_flat_rw @@ -92,7 +92,7 @@ public: }; // Overload vector with the required update function and to apply all entries -class V3ConfigVar : public std::vector { +class V3ConfigVar final : public std::vector { public: // Update from other by copying all attributes void update(const V3ConfigVar& node) { @@ -116,7 +116,7 @@ typedef V3ConfigWildcardResolver V3ConfigVarResolver; //###################################################################### // Function or task: Have variables and properties -class V3ConfigFTask { +class V3ConfigFTask final { V3ConfigVarResolver m_vars; // Variables in function/task bool m_isolate = false; // Isolate function return bool m_noinline = false; // Don't inline function/task @@ -153,7 +153,7 @@ typedef V3ConfigWildcardResolver V3ConfigFTaskResolver; //###################################################################### // Modules have tasks, variables, named blocks and properties -class V3ConfigModule { +class V3ConfigModule final { typedef std::unordered_set StringSet; typedef std::set PragmaSet; @@ -224,7 +224,7 @@ typedef V3ConfigWildcardResolver V3ConfigModuleResolver; // - Line attributes: Attributes attached to lines // lint/coverage/tracing on/off -class V3ConfigIgnoresLine { +class V3ConfigIgnoresLine final { public: int m_lineno; // Line number to make change at V3ErrorCode m_code; // Error code @@ -253,7 +253,7 @@ std::ostream& operator<<(std::ostream& os, const V3ConfigIgnoresLine& rhs) { typedef std::bitset V3ConfigLineAttribute; // File entity -class V3ConfigFile { +class V3ConfigFile final { typedef std::map LineAttrMap; // Map line->bitset of attributes typedef std::multiset IgnLines; // list of {line,code,on} typedef std::pair WaiverSetting; // Waive code if string matches @@ -347,7 +347,7 @@ typedef V3ConfigWildcardResolver V3ConfigFileResolver; //###################################################################### // Resolve modules and files in the design -class V3ConfigResolver { +class V3ConfigResolver final { V3ConfigModuleResolver m_modules; // Access to module names (with wildcards) V3ConfigFileResolver m_files; // Access to file names (with wildcards) diff --git a/src/V3Config.h b/src/V3Config.h index cc3a3a42f..dcf01427f 100644 --- a/src/V3Config.h +++ b/src/V3Config.h @@ -26,7 +26,7 @@ //###################################################################### -class V3Config { +class V3Config final { public: static void addCaseFull(const string& file, int lineno); static void addCaseParallel(const string& file, int lineno); diff --git a/src/V3Const.cpp b/src/V3Const.cpp index b34485311..6ec823740 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -36,7 +36,7 @@ //###################################################################### // Utilities -class ConstVarMarkVisitor : public AstNVisitor { +class ConstVarMarkVisitor final : public AstNVisitor { // NODE STATE // AstVar::user4p -> bool, Var marked, 0=not set yet private: @@ -55,7 +55,7 @@ public: virtual ~ConstVarMarkVisitor() override = default; }; -class ConstVarFindVisitor : public AstNVisitor { +class ConstVarFindVisitor final : public AstNVisitor { // NODE STATE // AstVar::user4p -> bool, input from ConstVarMarkVisitor // MEMBERS @@ -79,7 +79,7 @@ public: //###################################################################### // Const state, as a visitor of each AstNode -class ConstVisitor : public AstNVisitor { +class ConstVisitor final : public AstNVisitor { private: // NODE STATE // ** only when m_warn/m_doExpensive is set. If state is needed other times, diff --git a/src/V3Const.h b/src/V3Const.h index a7a45aca6..f5b8732f3 100644 --- a/src/V3Const.h +++ b/src/V3Const.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Const { +class V3Const final { public: static AstNode* constifyParamsEdit(AstNode* nodep); static AstNode* constifyGenerateParamsEdit(AstNode* nodep); diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 4019953e8..3a4c2f3d9 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -37,7 +37,7 @@ //###################################################################### // Coverage state, as a visitor of each AstNode -class CoverageVisitor : public AstNVisitor { +class CoverageVisitor final : public AstNVisitor { private: // TYPES typedef std::unordered_map VarNameMap; diff --git a/src/V3Coverage.h b/src/V3Coverage.h index b24b25ee8..37ebbacd5 100644 --- a/src/V3Coverage.h +++ b/src/V3Coverage.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Coverage { +class V3Coverage final { public: // CONSTRUCTORS static void coverage(AstNetlist* rootp); diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index 94da008d7..aebcc1f7f 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -30,7 +30,7 @@ //###################################################################### // CoverageJoin state, as a visitor of each AstNode -class CoverageJoinVisitor : public AstNVisitor { +class CoverageJoinVisitor final : public AstNVisitor { private: // NODE STATE // V3Hashed diff --git a/src/V3CoverageJoin.h b/src/V3CoverageJoin.h index 1983db564..cdf2447e5 100644 --- a/src/V3CoverageJoin.h +++ b/src/V3CoverageJoin.h @@ -25,7 +25,7 @@ //============================================================================ -class V3CoverageJoin { +class V3CoverageJoin final { public: // CONSTRUCTORS static void coverageJoin(AstNetlist* rootp); diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 718131703..648d4d641 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -46,7 +46,7 @@ //###################################################################### -class DeadModVisitor : public AstNVisitor { +class DeadModVisitor final : public AstNVisitor { // In a module that is dead, cleanup the in-use counts of the modules private: // NODE STATE @@ -69,7 +69,7 @@ public: //###################################################################### // Dead state, as a visitor of each AstNode -class DeadVisitor : public AstNVisitor { +class DeadVisitor final : public AstNVisitor { private: // NODE STATE // Entire Netlist: diff --git a/src/V3Dead.h b/src/V3Dead.h index 6ef94b8d6..45da1943c 100644 --- a/src/V3Dead.h +++ b/src/V3Dead.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Dead { +class V3Dead final { public: // Modules, no vars/dtypes static void deadifyModules(AstNetlist* nodep); diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index e37f1d7f1..c03478ad1 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -63,7 +63,7 @@ //###################################################################### // Delayed state, as a visitor of each AstNode -class DelayedVisitor : public AstNVisitor { +class DelayedVisitor final : public AstNVisitor { private: // NODE STATE // Cleared each module: diff --git a/src/V3Delayed.h b/src/V3Delayed.h index cdacae1ff..eaa1e2650 100644 --- a/src/V3Delayed.h +++ b/src/V3Delayed.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Delayed { +class V3Delayed final { public: static void delayedAll(AstNetlist* nodep); }; diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index 158bf4f85..6cc0bc5d7 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -34,7 +34,7 @@ //###################################################################### -class DepthVisitor : public AstNVisitor { +class DepthVisitor final : public AstNVisitor { private: // NODE STATE diff --git a/src/V3Depth.h b/src/V3Depth.h index 6527afab8..9e1e4834f 100644 --- a/src/V3Depth.h +++ b/src/V3Depth.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Depth { +class V3Depth final { public: static void depthAll(AstNetlist* nodep); }; diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index a95592ab8..19a3a0604 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -32,7 +32,7 @@ //###################################################################### -class DepthBlockVisitor : public AstNVisitor { +class DepthBlockVisitor final : public AstNVisitor { private: // NODE STATE diff --git a/src/V3DepthBlock.h b/src/V3DepthBlock.h index 2ba04b280..7233cd320 100644 --- a/src/V3DepthBlock.h +++ b/src/V3DepthBlock.h @@ -25,7 +25,7 @@ //============================================================================ -class V3DepthBlock { +class V3DepthBlock final { public: static void depthBlockAll(AstNetlist* nodep); }; diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index fb864118d..b59e900ca 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -34,7 +34,7 @@ //###################################################################### -class DescopeVisitor : public AstNVisitor { +class DescopeVisitor final : public AstNVisitor { private: // NODE STATE // Cleared entire netlist diff --git a/src/V3Descope.h b/src/V3Descope.h index f808a5a8d..04093afd6 100644 --- a/src/V3Descope.h +++ b/src/V3Descope.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Descope { +class V3Descope final { public: static void descopeAll(AstNetlist* nodep); }; diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 4dabe5e7c..0345ceb44 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -39,7 +39,7 @@ constexpr int EMITC_NUM_CONSTW //###################################################################### // Emit statements and math operators -class EmitCStmts : public EmitCBaseVisitor { +class EmitCStmts VL_NOT_FINAL : public EmitCBaseVisitor { private: typedef std::vector VarVec; typedef std::map VarSortMap; // Map size class to VarVec @@ -1264,7 +1264,7 @@ public: //###################################################################### // Establish mtask variable sort order in mtasks mode -class EmitVarTspSorter : public V3TSP::TspStateBase { +class EmitVarTspSorter final : public V3TSP::TspStateBase { private: // MEMBERS const MTaskIdSet& m_mtaskIds; // Mtask we're ordering @@ -1306,7 +1306,7 @@ unsigned EmitVarTspSorter::m_serialNext = 0; //###################################################################### // Internal EmitC implementation -class EmitCImp : EmitCStmts { +class EmitCImp final : EmitCStmts { // MEMBERS AstNodeModule* m_modp = nullptr; std::vector m_blkChangeDetVec; // All encountered changes in block @@ -3401,7 +3401,7 @@ void EmitCImp::mainImp(AstNodeModule* modp, bool slow) { //###################################################################### // Tracing routines -class EmitCTrace : EmitCStmts { +class EmitCTrace final : EmitCStmts { // NODE STATE/TYPES // Cleared on netlist // AstNode::user1() -> int. Enum number diff --git a/src/V3EmitC.h b/src/V3EmitC.h index 0bd5ec642..e89b8f89a 100644 --- a/src/V3EmitC.h +++ b/src/V3EmitC.h @@ -25,7 +25,7 @@ //============================================================================ -class V3EmitC { +class V3EmitC final { public: static void emitc(); static void emitcInlines(); diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 87bdb58bc..731b8356e 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -30,7 +30,7 @@ //###################################################################### // Base Visitor class -- holds output file pointer -class EmitCBaseVisitor : public AstNVisitor { +class EmitCBaseVisitor VL_NOT_FINAL : public AstNVisitor { public: // STATE V3OutCFile* m_ofp = nullptr; @@ -113,7 +113,7 @@ public: //###################################################################### // Count operations under the given node, as a visitor of each AstNode -class EmitCBaseCounterVisitor : public AstNVisitor { +class EmitCBaseCounterVisitor final : public AstNVisitor { private: // MEMBERS int m_count = 0; // Number of statements diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp index eb91000d0..df7d20c88 100644 --- a/src/V3EmitCInlines.cpp +++ b/src/V3EmitCInlines.cpp @@ -26,7 +26,7 @@ //###################################################################### -class EmitCInlines : EmitCBaseVisitor { +class EmitCInlines final : EmitCBaseVisitor { // STATE // METHODS diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp index 3d066bc1b..f23cc7668 100644 --- a/src/V3EmitCMain.cpp +++ b/src/V3EmitCMain.cpp @@ -26,7 +26,7 @@ //###################################################################### -class EmitCMain : EmitCBaseVisitor { +class EmitCMain final : EmitCBaseVisitor { // METHODS // VISITORS diff --git a/src/V3EmitCMain.h b/src/V3EmitCMain.h index 04df088a2..c17449f50 100644 --- a/src/V3EmitCMain.h +++ b/src/V3EmitCMain.h @@ -22,7 +22,7 @@ //============================================================================ -class V3EmitCMain { +class V3EmitCMain final { public: static void emit(); }; diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index ce830611e..4844f5ad6 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -28,7 +28,7 @@ //###################################################################### // Emit statements -class CMakeEmitter { +class CMakeEmitter final { // METHODS VL_DEBUG_FUNC; // Declare debug() diff --git a/src/V3EmitCMake.h b/src/V3EmitCMake.h index 9cfe9275a..144a22925 100644 --- a/src/V3EmitCMake.h +++ b/src/V3EmitCMake.h @@ -22,7 +22,7 @@ //============================================================================ -class V3EmitCMake { +class V3EmitCMake final { public: static void emit(); }; diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index eb88e4cdb..fe2ef52f8 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -29,7 +29,7 @@ //###################################################################### // Symbol table emitting -class EmitCSyms : EmitCBaseVisitor { +class EmitCSyms final : EmitCBaseVisitor { // NODE STATE // Cleared on Netlist // AstNodeModule::user1() -> bool. Set true __Vconfigure called diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 1c9f11cba..cf50f1ea2 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -26,7 +26,7 @@ //###################################################################### // Emit statements and math operators -class EmitMk { +class EmitMk final { public: // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -289,7 +289,7 @@ public: }; //###################################################################### -class EmitMkHierVerilation { +class EmitMkHierVerilation final { const V3HierBlockPlan* const m_planp; const string m_makefile; // path of this makefile void emitCommonOpts(V3OutMkFile& of) const { diff --git a/src/V3EmitMk.h b/src/V3EmitMk.h index 4e30f598c..bb329c3bd 100644 --- a/src/V3EmitMk.h +++ b/src/V3EmitMk.h @@ -24,7 +24,7 @@ class V3HierBlockPlan; //============================================================================ -class V3EmitMk { +class V3EmitMk final { public: static void emitmk(); static void emitHierVerilation(const V3HierBlockPlan* planp); diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index fb3974f7f..53565a87e 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -28,7 +28,7 @@ //###################################################################### // Emit statements and math operators -class EmitVBaseVisitor : public EmitCBaseVisitor { +class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { // MEMBERS bool m_suppressSemi = false; bool m_suppressUnknown = false; @@ -673,7 +673,7 @@ public: //###################################################################### // Emit to an output file -class EmitVFileVisitor : public EmitVBaseVisitor { +class EmitVFileVisitor final : public EmitVBaseVisitor { // MEMBERS V3OutFile* m_ofp; // METHODS @@ -699,7 +699,7 @@ public: //###################################################################### // Emit to a stream (perhaps stringstream) -class EmitVStreamVisitor : public EmitVBaseVisitor { +class EmitVStreamVisitor final : public EmitVBaseVisitor { // MEMBERS std::ostream& m_os; // METHODS @@ -721,7 +721,7 @@ public: //###################################################################### // Emit to a stream (perhaps stringstream) -class EmitVPrefixedFormatter : public V3OutFormatter { +class EmitVPrefixedFormatter final : public V3OutFormatter { std::ostream& m_os; string m_prefix; // What to print at beginning of each line int m_flWidth; // Padding of fileline @@ -763,7 +763,7 @@ public: } }; -class EmitVPrefixedVisitor : public EmitVBaseVisitor { +class EmitVPrefixedVisitor final : public EmitVBaseVisitor { // MEMBERS EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the // inheritance is another unused V3OutFormatter) diff --git a/src/V3EmitV.h b/src/V3EmitV.h index 4a4900895..98f8b3cbb 100644 --- a/src/V3EmitV.h +++ b/src/V3EmitV.h @@ -25,7 +25,7 @@ //============================================================================ -class V3EmitV { +class V3EmitV final { public: static void verilogForTree(AstNode* nodep, std::ostream& os = std::cout); static void verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix, diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index e607a8db8..b39a30f43 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -28,7 +28,7 @@ //###################################################################### // Emit statements and math operators -class EmitXmlFileVisitor : public AstNVisitor { +class EmitXmlFileVisitor final : public AstNVisitor { // NODE STATE // Entire netlist: // AstNode::user1 -> uint64_t, number to connect crossrefs @@ -256,7 +256,7 @@ public: //###################################################################### // List of module files xml visitor -class ModuleFilesXmlVisitor : public AstNVisitor { +class ModuleFilesXmlVisitor final : public AstNVisitor { private: // MEMBERS std::ostream& m_os; @@ -304,7 +304,7 @@ public: //###################################################################### // Hierarchy of Cells visitor -class HierCellsXmlVisitor : public AstNVisitor { +class HierCellsXmlVisitor final : public AstNVisitor { private: // MEMBERS std::ostream& m_os; diff --git a/src/V3EmitXml.h b/src/V3EmitXml.h index 14d1a3e9e..18555891f 100644 --- a/src/V3EmitXml.h +++ b/src/V3EmitXml.h @@ -25,7 +25,7 @@ //============================================================================ -class V3EmitXml { +class V3EmitXml final { public: static void emitxml(); }; diff --git a/src/V3Error.h b/src/V3Error.h index a895a9cdb..fcf166a75 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -33,7 +33,7 @@ //###################################################################### -class V3ErrorCode { +class V3ErrorCode final { public: // clang-format off enum en: uint8_t { @@ -217,7 +217,7 @@ inline std::ostream& operator<<(std::ostream& os, const V3ErrorCode& rhs) { //###################################################################### -class V3Error { +class V3Error final { // Base class for any object that wants debugging and error reporting typedef std::set MessagesSet; diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 3bb2d2451..f594434b2 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -37,7 +37,7 @@ //###################################################################### // Expand state, as a visitor of each AstNode -class ExpandVisitor : public AstNVisitor { +class ExpandVisitor final : public AstNVisitor { private: // NODE STATE // AstNode::user1() -> bool. Processed diff --git a/src/V3Expand.h b/src/V3Expand.h index f0eb83608..7080ecbcd 100644 --- a/src/V3Expand.h +++ b/src/V3Expand.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Expand { +class V3Expand final { public: static void expandAll(AstNetlist* nodep); }; diff --git a/src/V3File.cpp b/src/V3File.cpp index 0d1fc5986..66f82abbb 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -62,9 +62,9 @@ constexpr int INFILTER_CACHE_MAX = (64 * 1024); // Maximum bytes to cache if sa //###################################################################### // V3File Internal state -class V3FileDependImp { +class V3FileDependImp final { // TYPES - class DependFile { + class DependFile final { // A single file bool m_target; // True if write, else read bool m_exists = true; @@ -327,7 +327,7 @@ void V3File::createMakeDir() { //###################################################################### // VInFilterImp -class VInFilterImp { +class VInFilterImp final { typedef std::map FileContentsMap; typedef VInFilter::StrList StrList; @@ -949,7 +949,7 @@ void V3OutCFile::putsGuard() { //###################################################################### // VIdProtect -class VIdProtectImp { +class VIdProtectImp final { // MEMBERS typedef std::map IdMap; IdMap m_nameMap; // Map of old name into new name diff --git a/src/V3File.h b/src/V3File.h index 5b841fe59..c4a176150 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -31,7 +31,7 @@ //============================================================================ // V3File: Create streams, recording dependency information -class V3File { +class V3File final { public: static std::ifstream* new_ifstream(const string& filename) { addSrcDepend(filename); @@ -76,7 +76,7 @@ public: class VInFilterImp; -class VInFilter { +class VInFilter final { public: // TYPES typedef std::list StrList; @@ -99,7 +99,7 @@ public: //============================================================================ // V3OutFormatter: A class for automatic indentation of C++ or Verilog code. -class V3OutFormatter { +class V3OutFormatter VL_NOT_FINAL { // TYPES static constexpr int MAXSPACE = 80; // After this indent, stop indenting more public: @@ -176,7 +176,7 @@ public: //============================================================================ // V3OutFile: A class for printing to a file, with automatic indentation of C++ code. -class V3OutFile : public V3OutFormatter { +class V3OutFile VL_NOT_FINAL : public V3OutFormatter { // MEMBERS FILE* m_fp; @@ -190,7 +190,7 @@ private: virtual void putcOutput(char chr) override { fputc(chr, m_fp); } }; -class V3OutCFile : public V3OutFile { +class V3OutCFile VL_NOT_FINAL : public V3OutFile { int m_guard = false; // Created header guard int m_private; // 1 = Most recently emitted private:, 2 = public: public: @@ -218,7 +218,7 @@ public: } }; -class V3OutScFile : public V3OutCFile { +class V3OutScFile final : public V3OutCFile { public: explicit V3OutScFile(const string& filename) : V3OutCFile{filename} {} @@ -231,7 +231,7 @@ public: } }; -class V3OutVFile : public V3OutFile { +class V3OutVFile final : public V3OutFile { public: explicit V3OutVFile(const string& filename) : V3OutFile{filename, V3OutFormatter::LA_VERILOG} {} @@ -239,7 +239,7 @@ public: virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); } }; -class V3OutXmlFile : public V3OutFile { +class V3OutXmlFile final : public V3OutFile { public: explicit V3OutXmlFile(const string& filename) : V3OutFile{filename, V3OutFormatter::LA_XML} { @@ -249,7 +249,7 @@ public: virtual void putsHeader() { puts("\n"); } }; -class V3OutMkFile : public V3OutFile { +class V3OutMkFile final : public V3OutFile { public: explicit V3OutMkFile(const string& filename) : V3OutFile{filename, V3OutFormatter::LA_MK} {} @@ -265,7 +265,7 @@ public: class VIdProtectImp; -class VIdProtect { +class VIdProtect final { public: // METHODS // Rename to a new encoded string (unless earlier passthru'ed) diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 64adea8d4..0e992d311 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -37,7 +37,7 @@ class FileLine; //! This singleton class contains tables of data that are unchanging in each //! source file (each with its own unique filename number). -class FileLineSingleton { +class FileLineSingleton final { // TYPES typedef std::map FileNameNumMap; // MEMBERS @@ -64,7 +64,7 @@ protected: }; //! All source lines from a file/stream, to enable errors to show sources -class VFileContent { +class VFileContent final { // MEMBERS int m_id; // Content ID number std::deque m_lines; // Source text lines @@ -87,7 +87,7 @@ std::ostream& operator<<(std::ostream& os, VFileContent* contentp); //! This class is instantiated for every source code line (potentially //! millions). To save space, per-file information (e.g. filename, source //! language is held in tables in the FileLineSingleton class. -class FileLine { +class FileLine final { // CONSTANTS static constexpr unsigned SHOW_SOURCE_MAX_LENGTH = 400; // Don't show source lines > this long diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 25b45e040..72aca1174 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -43,7 +43,7 @@ constexpr int GATE_DEDUP_MAX_DEPTH = 20; //###################################################################### -class GateBaseVisitor : public AstNVisitor { +class GateBaseVisitor VL_NOT_FINAL : public AstNVisitor { public: VL_DEBUG_FUNC; // Declare debug() }; @@ -52,7 +52,7 @@ public: class GateLogicVertex; class GateVarVertex; -class GateGraphBaseVisitor { +class GateGraphBaseVisitor VL_NOT_FINAL { public: V3Graph* m_graphp; // Graph this class is visiting explicit GateGraphBaseVisitor(V3Graph* graphp) @@ -66,7 +66,7 @@ public: //###################################################################### // Support classes -class GateEitherVertex : public V3GraphVertex { +class GateEitherVertex VL_NOT_FINAL : public V3GraphVertex { AstScope* m_scopep; // Scope vertex refers to bool m_reducible = true; // True if this node should be able to be eliminated bool m_dedupable = true; // True if this node should be able to be deduped @@ -123,7 +123,7 @@ public: } }; -class GateVarVertex : public GateEitherVertex { +class GateVarVertex final : public GateEitherVertex { AstVarScope* m_varScp; bool m_isTop = false; bool m_isClock = false; @@ -163,7 +163,7 @@ public: } }; -class GateLogicVertex : public GateEitherVertex { +class GateLogicVertex final : public GateEitherVertex { AstNode* m_nodep; AstActive* m_activep; // Under what active; nullptr is ok (under cfunc or such) bool m_slow; // In slow block @@ -192,7 +192,7 @@ public: //###################################################################### // Is this a simple math expression with a single input and single output? -class GateOkVisitor : public GateBaseVisitor { +class GateOkVisitor final : public GateBaseVisitor { private: // RETURN STATE bool m_isSimple = true; // Set false when we know it isn't simple @@ -301,7 +301,7 @@ public: //###################################################################### // Gate class functions -class GateVisitor : public GateBaseVisitor { +class GateVisitor final : public GateBaseVisitor { private: // NODE STATE // Entire netlist: @@ -826,7 +826,7 @@ void GateVisitor::warnSignals() { class GateDedupeVarVisitor; -class GateElimVisitor : public GateBaseVisitor { +class GateElimVisitor final : public GateBaseVisitor { private: // NODE STATE // STATE @@ -903,7 +903,7 @@ void GateVisitor::optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode* //###################################################################### // Auxiliary hash class for GateDedupeVarVisitor -class GateDedupeHash : public V3HashedUserSame { +class GateDedupeHash final : public V3HashedUserSame { public: // TYPES typedef std::set NodeSet; @@ -1021,7 +1021,7 @@ public: //###################################################################### // Have we seen the rhs of this assign before? -class GateDedupeVarVisitor : public GateBaseVisitor { +class GateDedupeVarVisitor final : public GateBaseVisitor { // Given a node, it is visited to try to find the AstNodeAssign under // it that can used for dedupe. // Right now, only the following node trees are supported for dedupe. @@ -1121,7 +1121,7 @@ void GateElimVisitor::hashReplace(AstNode* oldp, AstNode* newp) { //###################################################################### // Recurse through the graph, looking for duplicate expressions on the rhs of an assign -class GateDedupeGraphVisitor : public GateGraphBaseVisitor { +class GateDedupeGraphVisitor final : public GateGraphBaseVisitor { private: // NODE STATE // AstVarScope::user2p -> bool: already visited @@ -1248,7 +1248,7 @@ void GateVisitor::dedupe() { //###################################################################### // Recurse through the graph, try to merge assigns -class GateMergeAssignsGraphVisitor : public GateGraphBaseVisitor { +class GateMergeAssignsGraphVisitor final : public GateGraphBaseVisitor { private: // NODE STATE AstNodeAssign* m_assignp = nullptr; @@ -1378,7 +1378,7 @@ void GateVisitor::mergeAssigns() { //###################################################################### // Find a var's offset in a concatenation -class GateConcatVisitor : public GateBaseVisitor { +class GateConcatVisitor final : public GateBaseVisitor { private: // STATE AstVarScope* m_vscp = nullptr; // Varscope we're trying to find @@ -1429,7 +1429,7 @@ public: //###################################################################### // Recurse through the graph, looking for clock vectors to bypass -class GateClkDecompState { +class GateClkDecompState final { public: int m_offset; AstVarScope* m_last_vsp; @@ -1439,7 +1439,7 @@ public: virtual ~GateClkDecompState() = default; }; -class GateClkDecompGraphVisitor : public GateGraphBaseVisitor { +class GateClkDecompGraphVisitor final : public GateGraphBaseVisitor { private: // NODE STATE // AstVarScope::user2p -> bool: already visited @@ -1571,7 +1571,7 @@ void GateVisitor::decomposeClkVectors() { //###################################################################### // Convert VARSCOPE(ASSIGN(default, VARREF)) to just VARSCOPE(default) -class GateDeassignVisitor : public GateBaseVisitor { +class GateDeassignVisitor final : public GateBaseVisitor { private: // VISITORS virtual void visit(AstVarScope* nodep) override { diff --git a/src/V3Gate.h b/src/V3Gate.h index 4248ce6f8..18ab97f16 100644 --- a/src/V3Gate.h +++ b/src/V3Gate.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Gate { +class V3Gate final { public: static void gateAll(AstNetlist* nodep); }; diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index 60ebff081..b8acc7430 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -29,7 +29,7 @@ //###################################################################### // GenClk state, as a visitor of each AstNode -class GenClkBaseVisitor : public AstNVisitor { +class GenClkBaseVisitor VL_NOT_FINAL : public AstNVisitor { protected: VL_DEBUG_FUNC; // Declare debug() }; @@ -37,7 +37,7 @@ protected: //###################################################################### // GenClk Read -class GenClkRenameVisitor : public GenClkBaseVisitor { +class GenClkRenameVisitor final : public GenClkBaseVisitor { private: // NODE STATE // Cleared on top scope @@ -127,7 +127,7 @@ public: //###################################################################### // GenClk Read -class GenClkReadVisitor : public GenClkBaseVisitor { +class GenClkReadVisitor final : public GenClkBaseVisitor { private: // NODE STATE // Cleared on top scope diff --git a/src/V3GenClk.h b/src/V3GenClk.h index 38d4c7ec6..850f0cec0 100644 --- a/src/V3GenClk.h +++ b/src/V3GenClk.h @@ -25,7 +25,7 @@ //============================================================================ -class V3GenClk { +class V3GenClk final { public: static void genClkAll(AstNetlist* nodep); }; diff --git a/src/V3Global.h b/src/V3Global.h index 41afa569d..3075092c4 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -61,7 +61,7 @@ public: //###################################################################### -class VWidthMinUsage { +class VWidthMinUsage final { public: enum en : uint8_t { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH }; enum en m_e; @@ -87,7 +87,7 @@ inline bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) { //###################################################################### // V3Global - The top level class for the entire program -class V3Global { +class V3Global final { // Globals AstNetlist* m_rootp; // Root of entire netlist V3HierBlockPlan* m_hierPlanp; // Hierarchical verilation plan, nullptr unless hier_block diff --git a/src/V3Graph.h b/src/V3Graph.h index d4dbab874..4ac788646 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -45,7 +45,7 @@ typedef bool (*V3EdgeFuncP)(const V3GraphEdge* edgep); // it's useful to have algorithms that can walk in either direction, hence // some methods take GraphWay to programmatically select the direction. -class GraphWay { +class GraphWay final { public: enum en : uint8_t { FORWARD = 0, @@ -77,7 +77,7 @@ inline bool operator==(GraphWay::en lhs, const GraphWay& rhs) { return lhs == rh //============================================================================ -class V3Graph { +class V3Graph VL_NOT_FINAL { private: // MEMBERS V3List m_vertices; // All vertices @@ -185,7 +185,7 @@ public: //============================================================================ -class V3GraphVertex { +class V3GraphVertex VL_NOT_FINAL { // Vertices may be a 'gate'/wire statement OR a variable protected: friend class V3Graph; @@ -273,7 +273,7 @@ std::ostream& operator<<(std::ostream& os, V3GraphVertex* vertexp); //============================================================================ -class V3GraphEdge { +class V3GraphEdge VL_NOT_FINAL { // Wires/variables aren't edges. Edges have only a single to/from vertex public: // ENUMS diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index dce97d011..5b38813c1 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -29,7 +29,7 @@ // Algorithms - acyclic // Break the minimal number of backward edges to make the graph acyclic -class GraphAcycVertex : public V3GraphVertex { +class GraphAcycVertex final : public V3GraphVertex { // user() is used for various sub-algorithm pieces V3GraphVertex* m_origVertexp; // Pointer to first vertex this represents protected: @@ -53,7 +53,7 @@ public: //-------------------------------------------------------------------- -class GraphAcycEdge : public V3GraphEdge { +class GraphAcycEdge final : public V3GraphEdge { // userp() is always used to point to the head original graph edge private: typedef std::list OrigEdgeList; // List of orig edges, see also GraphAcyc's decl @@ -87,7 +87,7 @@ struct GraphAcycEdgeCmp { //-------------------------------------------------------------------- // CLASSES -class GraphAcyc { +class GraphAcyc final { private: typedef std::list OrigEdgeList; // List of orig edges, see also GraphAcycEdge's decl diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index 218d050a3..929dbdcd9 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -69,7 +69,7 @@ void V3Graph::deleteCutableOnlyEdges() { //###################################################################### // Algorithms - weakly connected components -class GraphRemoveRedundant : GraphAlg<> { +class GraphRemoveRedundant final : GraphAlg<> { bool m_sumWeights; ///< Sum, rather then maximize weights private: void main() { @@ -137,7 +137,7 @@ void V3Graph::removeRedundantEdgesSum(V3EdgeFuncP edgeFuncp) { //###################################################################### // Algorithms - remove transitive -class GraphAlgRemoveTransitiveEdges : GraphAlg<> { +class GraphAlgRemoveTransitiveEdges final : GraphAlg<> { public: explicit GraphAlgRemoveTransitiveEdges(V3Graph* graphp) : GraphAlg<>(graphp, nullptr) {} @@ -168,7 +168,7 @@ void V3Graph::removeTransitiveEdges() { GraphAlgRemoveTransitiveEdges(this).go() //###################################################################### // Algorithms - weakly connected components -class GraphAlgWeakly : GraphAlg<> { +class GraphAlgWeakly final : GraphAlg<> { private: void main() { // Initialize state @@ -209,7 +209,7 @@ void V3Graph::weaklyConnected(V3EdgeFuncP edgeFuncp) { GraphAlgWeakly(this, edge //###################################################################### // Algorithms - strongly connected components -class GraphAlgStrongly : GraphAlg<> { +class GraphAlgStrongly final : GraphAlg<> { private: uint32_t m_currentDfs; // DFS count std::vector m_callTrace; // List of everything we hit processing so far @@ -297,7 +297,7 @@ void V3Graph::stronglyConnected(V3EdgeFuncP edgeFuncp) { GraphAlgStrongly(this, //###################################################################### // Algorithms - ranking -class GraphAlgRank : GraphAlg<> { +class GraphAlgRank final : GraphAlg<> { private: void main() { // Rank each vertex, ignoring cutable edges @@ -350,7 +350,7 @@ void V3Graph::rank(V3EdgeFuncP edgeFuncp) { GraphAlgRank(this, edgeFuncp); } //###################################################################### // Algorithms - ranking -class GraphAlgRLoops : GraphAlg<> { +class GraphAlgRLoops final : GraphAlg<> { private: std::vector m_callTrace; // List of everything we hit processing so far bool m_done; // Exit algorithm @@ -404,7 +404,7 @@ void V3Graph::reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) { //###################################################################### // Algorithms - subtrees -class GraphAlgSubtrees : GraphAlg<> { +class GraphAlgSubtrees final : GraphAlg<> { private: V3Graph* m_loopGraphp; diff --git a/src/V3GraphAlg.h b/src/V3GraphAlg.h index 408e99c46..b25b785f8 100644 --- a/src/V3GraphAlg.h +++ b/src/V3GraphAlg.h @@ -28,7 +28,7 @@ // For internal use, most graph algorithms use this as a base class template // Or sometimes const V3Graph -class GraphAlg { +class GraphAlg VL_NOT_FINAL { protected: T_Graph* m_graphp; // Graph we're operating upon V3EdgeFuncP m_edgeFuncp; // Function that says we follow this edge diff --git a/src/V3GraphDfa.cpp b/src/V3GraphDfa.cpp index c114f8632..7669fa619 100644 --- a/src/V3GraphDfa.cpp +++ b/src/V3GraphDfa.cpp @@ -51,7 +51,7 @@ DfaVertex* DfaGraph::findStart() { // Algorithms - convert NFA to a DFA // Uses the Subset Construction Algorithm -class GraphNfaToDfa : GraphAlg<> { +class GraphNfaToDfa final : GraphAlg<> { // We have two types of nodes in one graph, NFA and DFA nodes. // Edges from NFA to NFA come from the user, and indicate input or epsilon transitions // Edges from DFA to NFA indicate the NFA from which that DFA was formed. @@ -379,7 +379,7 @@ void DfaGraph::nfaToDfa() { GraphNfaToDfa(this, &V3GraphEdge::followAlwaysTrue); // // Scan the DFA, cleaning up trailing states. -class DfaGraphReduce : GraphAlg<> { +class DfaGraphReduce final : GraphAlg<> { private: // METHODS #ifdef VL_CPPCHECK @@ -527,7 +527,7 @@ void DfaGraph::dfaReduce() { DfaGraphReduce(this, &V3GraphEdge::followAlwaysTrue // The user's old accept is now the new accept. This is important as // we want the virtual type of it to be intact. -class DfaGraphComplement : GraphAlg<> { +class DfaGraphComplement final : GraphAlg<> { private: // MEMBERS DfaVertex* m_tempNewerReject; diff --git a/src/V3GraphDfa.h b/src/V3GraphDfa.h index 027724506..3c726995d 100644 --- a/src/V3GraphDfa.h +++ b/src/V3GraphDfa.h @@ -58,7 +58,7 @@ class DfaEdge; /// | ^\----[epsilon]<-------/ | /// \->[epsilon]-----------------------------------------/ -class DfaGraph : public V3Graph { +class DfaGraph final : public V3Graph { public: // CONSTRUCTORS DfaGraph() = default; @@ -77,7 +77,7 @@ public: //============================================================================= // Vertex -class DfaVertex : public V3GraphVertex { +class DfaVertex VL_NOT_FINAL : public V3GraphVertex { // Each DFA state is captured in this vertex. // Start and accepting are members, rather than the more intuitive // subclasses, as subclassing them would make it harder to inherit from here. @@ -113,7 +113,7 @@ typedef VNUser DfaInput; //============================================================================ // Edge types -class DfaEdge : public V3GraphEdge { +class DfaEdge final : public V3GraphEdge { DfaInput m_input; bool m_complement; // Invert value when doing compare public: diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h index b32e360c1..104aa719d 100644 --- a/src/V3GraphPathChecker.h +++ b/src/V3GraphPathChecker.h @@ -29,7 +29,7 @@ /// /// The graph (or at least, the subset the algorithm sees through /// edgeFuncp) must not change during the lifetime of the checker. -class GraphPathChecker : GraphAlg { +class GraphPathChecker final : GraphAlg { // Count "generations" which increases on operations that scan through // the graph. Each node is marked with the last generation that scanned // it, to enable asserting there are no cycles, and to avoid recursing diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index d8a44a472..cc53b9e9d 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -40,7 +40,7 @@ template class GraphStream { private: // TYPES - class VxHolder { + class VxHolder final { public: // MEMBERS const V3GraphVertex* m_vxp; // [mtask] Vertex @@ -62,7 +62,7 @@ private: } }; - class VxHolderCmp { + class VxHolderCmp final { public: // MEMBERS T_Compare m_lessThan; // Sorting functor diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index ba12e0284..67340c5ec 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -25,7 +25,7 @@ //###################################################################### // Test class -class V3GraphTest { +class V3GraphTest VL_NOT_FINAL { protected: // MEMBERS DfaGraph m_graph; @@ -50,7 +50,7 @@ public: //###################################################################### // Vertices and nodes -class V3GraphTestVertex : public V3GraphVertex { +class V3GraphTestVertex VL_NOT_FINAL : public V3GraphVertex { string m_name; public: @@ -62,7 +62,7 @@ public: virtual string name() const override { return m_name; } }; -class V3GraphTestVarVertex : public V3GraphTestVertex { +class V3GraphTestVarVertex final : public V3GraphTestVertex { public: V3GraphTestVarVertex(V3Graph* graphp, const string& name) : V3GraphTestVertex{graphp, name} {} @@ -75,7 +75,7 @@ public: //###################################################################### // Test vertices and nodes -class V3GraphTestStrong : public V3GraphTest { +class V3GraphTestStrong final : public V3GraphTest { public: virtual string name() override { return "strong"; } virtual void runTest() override { @@ -113,7 +113,7 @@ public: } }; -class V3GraphTestAcyc : public V3GraphTest { +class V3GraphTestAcyc final : public V3GraphTest { public: virtual string name() override { return "acyc"; } virtual void runTest() override { @@ -141,7 +141,7 @@ public: } }; -class V3GraphTestVars : public V3GraphTest { +class V3GraphTestVars final : public V3GraphTest { public: virtual string name() override { return "vars"; } virtual void runTest() override { @@ -260,7 +260,7 @@ public: //====================================================================== -class DfaTestVertex : public DfaVertex { +class DfaTestVertex final : public DfaVertex { string m_name; public: @@ -272,7 +272,7 @@ public: virtual string name() const override { return m_name; } }; -class V3GraphTestDfa : public V3GraphTest { +class V3GraphTestDfa final : public V3GraphTest { public: virtual string name() override { return "dfa"; } @@ -321,7 +321,7 @@ public: //====================================================================== -class V3GraphTestImport : public V3GraphTest { +class V3GraphTestImport final : public V3GraphTest { #ifdef GRAPH_IMPORT void dotImport(); diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index a9600f699..459bed724 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -37,7 +37,7 @@ //###################################################################### // Hashed state, as a visitor of each AstNode -class HashedVisitor : public AstNVisitor { +class HashedVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3Hashed.h b/src/V3Hashed.h index 0f8afbac1..e8d7b6fdc 100644 --- a/src/V3Hashed.h +++ b/src/V3Hashed.h @@ -24,7 +24,7 @@ //============================================================================ -class VHashedBase { +class VHashedBase VL_NOT_FINAL { public: // CONSTRUCTORS VHashedBase() = default; @@ -43,7 +43,7 @@ struct V3HashedUserSame { virtual ~V3HashedUserSame() = default; }; -class V3Hashed : public VHashedBase { +class V3Hashed final : public VHashedBase { // NODE STATE // AstNode::user4() -> V3Hash. Hash value of this node (hash of 0 is illegal) AstUser4InUse m_inuser4; diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index 198877007..be21161e2 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -234,7 +234,7 @@ string V3HierBlock::commandArgsFileName(bool forCMake) const { //###################################################################### // Collect how hierarchical blocks are used -class HierBlockUsageCollectVisitor : public AstNVisitor { +class HierBlockUsageCollectVisitor final : public AstNVisitor { // NODE STATE // AstNode::user1() -> bool. Processed AstUser1InUse m_inuser1; diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h index 81e0603ae..e5409d1fd 100644 --- a/src/V3HierBlock.h +++ b/src/V3HierBlock.h @@ -37,7 +37,7 @@ class AstVar; //###################################################################### -class V3HierBlock { +class V3HierBlock final { public: typedef std::vector GParams; typedef std::set HierBlockSet; @@ -95,7 +95,7 @@ public: //###################################################################### // Holds relashonship between AstNodeModule and V3HierBlock -class V3HierBlockPlan { +class V3HierBlockPlan final { typedef std::map HierMap; HierMap m_blocks; diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index f66f2a0f8..681d123ef 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -44,7 +44,7 @@ static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can //###################################################################### // Inline state, as a visitor of each AstNode -class InlineMarkVisitor : public AstNVisitor { +class InlineMarkVisitor final : public AstNVisitor { private: // NODE STATE // Output @@ -233,7 +233,7 @@ public: // Using clonep(), find cell cross references. // clone() must not be called inside this visitor -class InlineCollectVisitor : public AstNVisitor { +class InlineCollectVisitor final : public AstNVisitor { private: // NODE STATE // Output: @@ -260,7 +260,7 @@ public: //###################################################################### // After cell is cloned, relink the new module's contents -class InlineRelinkVisitor : public AstNVisitor { +class InlineRelinkVisitor final : public AstNVisitor { private: typedef std::unordered_set StringSet; @@ -480,7 +480,7 @@ public: //###################################################################### // Inline state, as a visitor of each AstNode -class InlineVisitor : public AstNVisitor { +class InlineVisitor final : public AstNVisitor { private: // NODE STATE // Cleared entire netlist @@ -621,7 +621,7 @@ public: //###################################################################### // Track interface references under the Cell they reference -class InlineIntfRefVisitor : public AstNVisitor { +class InlineIntfRefVisitor final : public AstNVisitor { private: // NODE STATE // AstVar::user1p() // AstCell which this Var points to diff --git a/src/V3Inline.h b/src/V3Inline.h index a45cfbe1a..dd5b591f7 100644 --- a/src/V3Inline.h +++ b/src/V3Inline.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Inline { +class V3Inline final { public: static void inlineAll(AstNetlist* nodep); }; diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 022388977..4ef17a730 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -34,7 +34,7 @@ //###################################################################### // Inst state, as a visitor of each AstNode -class InstVisitor : public AstNVisitor { +class InstVisitor final : public AstNVisitor { private: // NODE STATE // Cleared each Cell: @@ -137,7 +137,7 @@ public: //###################################################################### -class InstDeModVarVisitor : public AstNVisitor { +class InstDeModVarVisitor final : public AstNVisitor { // Expand all module variables, and save names for later reference private: // STATE @@ -189,7 +189,7 @@ public: //###################################################################### -class InstDeVisitor : public AstNVisitor { +class InstDeVisitor final : public AstNVisitor { // Find all cells with arrays, and convert to non-arrayed private: // STATE @@ -472,7 +472,7 @@ public: //###################################################################### // Inst static function -class InstStatic { +class InstStatic final { private: VL_DEBUG_FUNC; // Declare debug() InstStatic() = default; // Static class diff --git a/src/V3Inst.h b/src/V3Inst.h index 7fa389256..5b68d0a31 100644 --- a/src/V3Inst.h +++ b/src/V3Inst.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Inst { +class V3Inst final { public: static void instAll(AstNetlist* nodep); static void dearrayAll(AstNetlist* nodep); diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 894aceba4..5da14c211 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -29,7 +29,7 @@ /// we'll count instructions from either the 'if' or the 'else' branch, /// whichever is larger. We know we won't run both. -class InstrCountVisitor : public AstNVisitor { +class InstrCountVisitor final : public AstNVisitor { private: // NODE STATE // AstNode::user4() -> int. Path cost + 1, 0 means don't dump @@ -46,7 +46,7 @@ private: // TYPES // Little class to cleanly call startVisitBase/endVisitBase - class VisitBase { + class VisitBase final { private: // MEMBERS uint32_t m_savedCount; @@ -258,7 +258,7 @@ private: }; // Iterate the graph printing the critical path marked by previous visitation -class InstrCountDumpVisitor : public AstNVisitor { +class InstrCountDumpVisitor final : public AstNVisitor { private: // NODE STATE // AstNode::user4() -> int. Path cost, 0 means don't dump diff --git a/src/V3InstrCount.h b/src/V3InstrCount.h index 697a69cb6..8e3d109f1 100644 --- a/src/V3InstrCount.h +++ b/src/V3InstrCount.h @@ -23,7 +23,7 @@ class AstNode; -class V3InstrCount { +class V3InstrCount final { public: // Return the estimate count of instructions we'd incur while running // code in and under nodep. diff --git a/src/V3LangCode.h b/src/V3LangCode.h index e9eb7ae4e..cdb68b03e 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -28,7 +28,7 @@ //! Class for the different languages supported. //! A separate file, since used both in V3Options (globally) and FileLine 9per //! file). -class V3LangCode { +class V3LangCode final { public: enum en : uint8_t { L_ERROR, // Must be first. diff --git a/src/V3LanguageWords.h b/src/V3LanguageWords.h index 3764f2dce..37cc5bee9 100644 --- a/src/V3LanguageWords.h +++ b/src/V3LanguageWords.h @@ -24,7 +24,7 @@ //============================================================================ -class V3LanguageWords { +class V3LanguageWords final { // List of common reserved keywords private: typedef std::map KeywordMap; diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 7663ca404..fc4708235 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -38,7 +38,7 @@ //###################################################################### // Structure for global state -class LifeState { +class LifeState final { // NODE STATE // See below AstUser1InUse m_inuser1; @@ -66,7 +66,7 @@ public: //###################################################################### // Structure for each variable encountered -class LifeVarEntry { +class LifeVarEntry final { // Last assignment to this varscope, nullptr if no longer relevant AstNodeAssign* m_assignp = nullptr; AstConst* m_constp = nullptr; // Known constant value @@ -116,7 +116,7 @@ public: //###################################################################### // Structure for all variables under a given meta-basic block -class LifeBlock { +class LifeBlock final { // NODE STATE // Cleared each AstIf: // AstVarScope::user1() -> int. Used in combining to detect duplicates @@ -268,7 +268,7 @@ public: //###################################################################### // Life state, as a visitor of each AstNode -class LifeVisitor : public AstNVisitor { +class LifeVisitor final : public AstNVisitor { private: // STATE LifeState* m_statep; // Current state @@ -450,7 +450,7 @@ public: //###################################################################### -class LifeTopVisitor : public AstNVisitor { +class LifeTopVisitor final : public AstNVisitor { // Visit all top nodes searching for functions that are entry points we want to start // finding code within. private: diff --git a/src/V3Life.h b/src/V3Life.h index 44a44f020..7e8141329 100644 --- a/src/V3Life.h +++ b/src/V3Life.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Life { +class V3Life final { public: static void lifeAll(AstNetlist* nodep); }; diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index a633af7ce..b3bc39795 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -40,7 +40,7 @@ //###################################################################### // LifePost class functions -class LifePostElimVisitor : public AstNVisitor { +class LifePostElimVisitor final : public AstNVisitor { private: bool m_tracingCall = false; // Iterating into a CCall to a CFunc @@ -128,7 +128,7 @@ struct LifePostLocation { //###################################################################### // LifePost delay elimination -class LifePostDlyVisitor : public AstNVisitor { +class LifePostDlyVisitor final : public AstNVisitor { private: // NODE STATE // Cleared on entire tree diff --git a/src/V3LifePost.h b/src/V3LifePost.h index 1aa9fae02..426270a70 100644 --- a/src/V3LifePost.h +++ b/src/V3LifePost.h @@ -25,7 +25,7 @@ //============================================================================ -class V3LifePost { +class V3LifePost final { public: static void lifepostAll(AstNetlist* nodep); }; diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index a5f8e78c7..b4dec71fa 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -41,14 +41,14 @@ //###################################################################### // Graph subclasses -class LinkCellsGraph : public V3Graph { +class LinkCellsGraph final : public V3Graph { public: LinkCellsGraph() = default; virtual ~LinkCellsGraph() override = default; virtual void loopsMessageCb(V3GraphVertex* vertexp) override; }; -class LinkCellsVertex : public V3GraphVertex { +class LinkCellsVertex final : public V3GraphVertex { AstNodeModule* m_modp; public: @@ -65,7 +65,7 @@ public: } }; -class LibraryVertex : public V3GraphVertex { +class LibraryVertex final : public V3GraphVertex { public: explicit LibraryVertex(V3Graph* graphp) : V3GraphVertex{graphp} {} @@ -91,7 +91,7 @@ void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) { //###################################################################### // Link state, as a visitor of each AstNode -class LinkCellsVisitor : public AstNVisitor { +class LinkCellsVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist: diff --git a/src/V3LinkCells.h b/src/V3LinkCells.h index b79b94a01..c1cd4b817 100644 --- a/src/V3LinkCells.h +++ b/src/V3LinkCells.h @@ -28,7 +28,7 @@ class V3ParseSym; //============================================================================ -class V3LinkCells { +class V3LinkCells final { public: static void link(AstNetlist* nodep, VInFilter* filterp, V3ParseSym* parseSymp); }; diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index df155c683..d84b344db 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -78,25 +78,25 @@ //###################################################################### // Matcher classes (for suggestion matching) -class LinkNodeMatcherClass : public VNodeMatcher { +class LinkNodeMatcherClass final : public VNodeMatcher { public: virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); } }; -class LinkNodeMatcherFTask : public VNodeMatcher { +class LinkNodeMatcherFTask final : public VNodeMatcher { public: virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); } }; -class LinkNodeMatcherModport : public VNodeMatcher { +class LinkNodeMatcherModport final : public VNodeMatcher { public: virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Modport); } }; -class LinkNodeMatcherVar : public VNodeMatcher { +class LinkNodeMatcherVar final : public VNodeMatcher { public: virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Var) || VN_IS(nodep, LambdaArgRef); } }; -class LinkNodeMatcherVarIO : public VNodeMatcher { +class LinkNodeMatcherVarIO final : public VNodeMatcher { public: virtual bool nodeMatch(const AstNode* nodep) const override { const AstVar* varp = VN_CAST_CONST(nodep, Var); @@ -104,7 +104,7 @@ public: return varp->isIO(); } }; -class LinkNodeMatcherVarParam : public VNodeMatcher { +class LinkNodeMatcherVarParam final : public VNodeMatcher { public: virtual bool nodeMatch(const AstNode* nodep) const override { const AstVar* varp = VN_CAST_CONST(nodep, Var); @@ -116,7 +116,7 @@ public: //###################################################################### // LinkDot state, as a visitor of each AstNode -class LinkDotState { +class LinkDotState final { private: // NODE STATE // Cleared on Netlist @@ -705,7 +705,7 @@ LinkDotState* LinkDotState::s_errorThisp = nullptr; //====================================================================== -class LinkDotFindVisitor : public AstNVisitor { +class LinkDotFindVisitor final : public AstNVisitor { // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table AstNodeModule* m_packagep = nullptr; // Current package @@ -1319,7 +1319,7 @@ public: //====================================================================== -class LinkDotParamVisitor : public AstNVisitor { +class LinkDotParamVisitor final : public AstNVisitor { private: // NODE STATE // Cleared on global @@ -1484,7 +1484,7 @@ public: //====================================================================== -class LinkDotScopeVisitor : public AstNVisitor { +class LinkDotScopeVisitor final : public AstNVisitor { // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table @@ -1643,7 +1643,7 @@ public: //====================================================================== // Iterate an interface to resolve modports -class LinkDotIfaceVisitor : public AstNVisitor { +class LinkDotIfaceVisitor final : public AstNVisitor { // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert @@ -1736,7 +1736,7 @@ void LinkDotState::computeIfaceModSyms() { //====================================================================== -class LinkDotResolveVisitor : public AstNVisitor { +class LinkDotResolveVisitor final : public AstNVisitor { private: // NODE STATE // Cleared on global diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h index e0d829a01..026ba0e2b 100644 --- a/src/V3LinkDot.h +++ b/src/V3LinkDot.h @@ -27,7 +27,7 @@ enum VLinkDotStep : uint8_t { LDS_PRIMARY, LDS_PARAMED, LDS_ARRAYED, LDS_SCOPED }; -class V3LinkDot { +class V3LinkDot final { private: static int debug(); static void linkDotGuts(AstNetlist* rootp, VLinkDotStep step); diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index db1f00fa1..89ea48649 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -47,7 +47,7 @@ //###################################################################### -class LinkIncVisitor : public AstNVisitor { +class LinkIncVisitor final : public AstNVisitor { private: // TYPES enum InsertMode : uint8_t { diff --git a/src/V3LinkInc.h b/src/V3LinkInc.h index a1679e6d3..ebb9194e7 100644 --- a/src/V3LinkInc.h +++ b/src/V3LinkInc.h @@ -25,7 +25,7 @@ //============================================================================ -class V3LinkInc { +class V3LinkInc final { public: static void linkIncrements(AstNetlist* nodep); diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index a83387885..e4bbc3c0e 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -41,7 +41,7 @@ //###################################################################### -class LinkJumpVisitor : public AstNVisitor { +class LinkJumpVisitor final : public AstNVisitor { private: // TYPES typedef std::vector BlockStack; diff --git a/src/V3LinkJump.h b/src/V3LinkJump.h index fba121e9c..af1e88ba0 100644 --- a/src/V3LinkJump.h +++ b/src/V3LinkJump.h @@ -25,7 +25,7 @@ //============================================================================ -class V3LinkJump { +class V3LinkJump final { public: static void linkJump(AstNetlist* nodep); }; diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 999950d8e..b1e365f10 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -30,7 +30,7 @@ //###################################################################### // Link state, as a visitor of each AstNode -class LinkLValueVisitor : public AstNVisitor { +class LinkLValueVisitor final : public AstNVisitor { private: // NODE STATE diff --git a/src/V3LinkLValue.h b/src/V3LinkLValue.h index 101e06514..1a534d649 100644 --- a/src/V3LinkLValue.h +++ b/src/V3LinkLValue.h @@ -25,7 +25,7 @@ //============================================================================ -class V3LinkLValue { +class V3LinkLValue final { public: static void linkLValue(AstNetlist* nodep); static void linkLValueSet(AstNode* nodep); diff --git a/src/V3LinkLevel.h b/src/V3LinkLevel.h index 4143efa4e..ca9a51a26 100644 --- a/src/V3LinkLevel.h +++ b/src/V3LinkLevel.h @@ -25,7 +25,7 @@ //============================================================================ -class V3LinkLevel { +class V3LinkLevel final { private: typedef std::vector ModVec; diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 19c065d24..2dce23b64 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -34,7 +34,7 @@ //###################################################################### // Link state, as a visitor of each AstNode -class LinkParseVisitor : public AstNVisitor { +class LinkParseVisitor final : public AstNVisitor { private: // NODE STATE // Cleared on netlist diff --git a/src/V3LinkParse.h b/src/V3LinkParse.h index 10425842c..bd600daab 100644 --- a/src/V3LinkParse.h +++ b/src/V3LinkParse.h @@ -25,7 +25,7 @@ //============================================================================ -class V3LinkParse { +class V3LinkParse final { public: static void linkParse(AstNetlist* rootp); }; diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index eccb7318a..8734e2532 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -38,7 +38,7 @@ //###################################################################### // Link state, as a visitor of each AstNode -class LinkResolveVisitor : public AstNVisitor { +class LinkResolveVisitor final : public AstNVisitor { private: // NODE STATE // Entire netlist: @@ -525,7 +525,7 @@ public: // Recurses cells backwards, so we can pick up those things that propagate // from child cells up to the top module. -class LinkBotupVisitor : public AstNVisitor { +class LinkBotupVisitor final : public AstNVisitor { private: // STATE AstNodeModule* m_modp = nullptr; // Current module diff --git a/src/V3LinkResolve.h b/src/V3LinkResolve.h index f33ff91d7..a998c0500 100644 --- a/src/V3LinkResolve.h +++ b/src/V3LinkResolve.h @@ -25,7 +25,7 @@ //============================================================================ -class V3LinkResolve { +class V3LinkResolve final { public: static void linkResolve(AstNetlist* rootp); }; diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 6ac5830f1..565bddae5 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -35,7 +35,7 @@ //###################################################################### // Localize base class -class LocalizeBaseVisitor : public AstNVisitor { +class LocalizeBaseVisitor VL_NOT_FINAL : public AstNVisitor { protected: // NODE STATE // Cleared on entire tree @@ -66,7 +66,7 @@ protected: //###################################################################### // Localize class functions -class LocalizeDehierVisitor : public LocalizeBaseVisitor { +class LocalizeDehierVisitor final : public LocalizeBaseVisitor { private: // NODE STATE/TYPES // See above @@ -91,7 +91,7 @@ public: //###################################################################### // Localize class functions -class LocalizeVisitor : public LocalizeBaseVisitor { +class LocalizeVisitor final : public LocalizeBaseVisitor { private: // NODE STATE/TYPES // See above diff --git a/src/V3Localize.h b/src/V3Localize.h index 8fdf5fe5c..3db73dec4 100644 --- a/src/V3Localize.h +++ b/src/V3Localize.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Localize { +class V3Localize final { public: static void localizeAll(AstNetlist* nodep); }; diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index 967c715d3..73742a3be 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -52,7 +52,7 @@ //###################################################################### -class CheckMergeableVisitor : public AstNVisitor { +class CheckMergeableVisitor final : public AstNVisitor { private: // STATE bool m_mergeable @@ -98,7 +98,7 @@ public: } }; -class MarkVarsVisitor : public AstNVisitor { +class MarkVarsVisitor final : public AstNVisitor { private: // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -115,7 +115,7 @@ public: void mark(AstNode* node) { iterate(node); } }; -class MergeCondVisitor : public AstNVisitor { +class MergeCondVisitor final : public AstNVisitor { private: // NODE STATE // AstVar::user1 -> Flag set for variables referenced by m_mgCondp diff --git a/src/V3MergeCond.h b/src/V3MergeCond.h index 52232bd0b..3366963e7 100644 --- a/src/V3MergeCond.h +++ b/src/V3MergeCond.h @@ -25,7 +25,7 @@ //============================================================================ -class V3MergeCond { +class V3MergeCond final { public: static void mergeAll(AstNetlist* nodep); }; diff --git a/src/V3Name.cpp b/src/V3Name.cpp index 1ac76a283..9c3c745dc 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -30,7 +30,7 @@ //###################################################################### // Name state, as a visitor of each AstNode -class NameVisitor : public AstNVisitor { +class NameVisitor final : public AstNVisitor { private: // NODE STATE // Cleared on Netlist diff --git a/src/V3Name.h b/src/V3Name.h index e998b5eb7..526858787 100644 --- a/src/V3Name.h +++ b/src/V3Name.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Name { +class V3Name final { public: static void nameAll(AstNetlist* nodep); }; diff --git a/src/V3Number.h b/src/V3Number.h index e19f4a767..4433bae29 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -37,7 +37,7 @@ inline bool v3EpsilonEqual(double a, double b) { class AstNode; -class V3Number { +class V3Number final { // Large 4-state number handling int m_width; // Width as specified/calculated. bool m_sized : 1; // True if the user specified the width, else we track it. diff --git a/src/V3Options.cpp b/src/V3Options.cpp index b388d8394..d0bae2ff4 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -50,7 +50,7 @@ //###################################################################### // V3 Internal state -class V3OptionsImp { +class V3OptionsImp final { public: // TYPES typedef std::map> DirMap; // Directory listing diff --git a/src/V3Options.h b/src/V3Options.h index da8bc0eb2..1c5b05ad5 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -33,7 +33,7 @@ class FileLine; //###################################################################### -class VOptionBool { +class VOptionBool final { // Class to track options that are either not specified (and default // true/false), versus user setting the option to true or false public: @@ -69,7 +69,7 @@ inline std::ostream& operator<<(std::ostream& os, const VOptionBool& rhs) { //###################################################################### -class VTimescale { +class VTimescale final { public: enum en : uint8_t { // clang-format off @@ -167,7 +167,7 @@ inline std::ostream& operator<<(std::ostream& os, const VTimescale& rhs) { //###################################################################### -class TraceFormat { +class TraceFormat final { public: enum en : uint8_t { VCD = 0, FST } m_e; // cppcheck-suppress noExplicitConstructor @@ -198,7 +198,7 @@ typedef std::set V3StringSet; //###################################################################### // Information given by --hierarchical-block option -class V3HierarchicalBlockOption { +class V3HierarchicalBlockOption final { public: // key:parameter name, value:value (as string) typedef std::map ParamStrMap; @@ -223,7 +223,7 @@ typedef std::map V3HierBlockOptSet; //###################################################################### // V3Options - Command line options -class V3Options { +class V3Options final { public: private: // TYPES diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 7653e7054..6d734e123 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -126,7 +126,7 @@ void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) { //###################################################################### -class OrderMoveDomScope { +class OrderMoveDomScope final { // Information stored for each unique loop, domain & scope trifecta public: V3ListEnt m_readyDomScopeE; // List of next ready dom scope @@ -186,7 +186,7 @@ inline std::ostream& operator<<(std::ostream& lhs, const OrderMoveDomScope& rhs) // Types of vertex we can create enum WhichVertex : uint8_t { WV_STD, WV_PRE, WV_PORD, WV_POST, WV_SETL, WV_MAX }; -class OrderUser { +class OrderUser final { // Stored in AstVarScope::user1p, a list of all the various vertices // that can exist for one given variable private: @@ -252,7 +252,7 @@ struct OrderVarFanoutCmp { // In addition it also check whether clock and data signals are mixed, and // produce a CLKDATA warning if so. // -class OrderClkMarkVisitor : public AstNVisitor { +class OrderClkMarkVisitor final : public AstNVisitor { private: bool m_hasClk = false; // flag indicating whether there is clock signal on rhs bool m_inClocked = false; // Currently inside a sequential block @@ -372,7 +372,7 @@ public: //###################################################################### // The class checks if the assignment generates a clock. -class OrderClkAssVisitor : public AstNVisitor { +class OrderClkAssVisitor final : public AstNVisitor { private: bool m_clkAss = false; // There is signals marked as clocker in the assignment // METHODS @@ -429,7 +429,7 @@ template class ProcessMoveBuildGraph { typedef std::unordered_map Logic2Move; public: - class MoveVertexMaker { + class MoveVertexMaker VL_NOT_FINAL { public: // Clients of ProcessMoveBuildGraph must supply MoveVertexMaker // which creates new T_MoveVertex's. Each new vertex wraps lvertexp @@ -551,7 +551,7 @@ private: //###################################################################### // OrderMoveVertexMaker and related -class OrderMoveVertexMaker : public ProcessMoveBuildGraph::MoveVertexMaker { +class OrderMoveVertexMaker final : public ProcessMoveBuildGraph::MoveVertexMaker { // MEMBERS V3Graph* m_pomGraphp; V3List* m_pomWaitingp; @@ -579,7 +579,8 @@ private: VL_UNCOPYABLE(OrderMoveVertexMaker); }; -class OrderMTaskMoveVertexMaker : public ProcessMoveBuildGraph::MoveVertexMaker { +class OrderMTaskMoveVertexMaker final + : public ProcessMoveBuildGraph::MoveVertexMaker { V3Graph* m_pomGraphp; public: @@ -602,7 +603,7 @@ private: VL_UNCOPYABLE(OrderMTaskMoveVertexMaker); }; -class OrderVerticesByDomainThenScope { +class OrderVerticesByDomainThenScope final { PartPtrIdMap m_ids; public: @@ -619,7 +620,7 @@ public: } }; -class MTaskVxIdLessThan { +class MTaskVxIdLessThan final { public: MTaskVxIdLessThan() = default; virtual ~MTaskVxIdLessThan() = default; @@ -636,7 +637,7 @@ public: //###################################################################### // Order class functions -class OrderVisitor : public AstNVisitor { +class OrderVisitor final : public AstNVisitor { private: // NODE STATE // Forming graph: diff --git a/src/V3Order.h b/src/V3Order.h index 92be224f0..35c04cc57 100644 --- a/src/V3Order.h +++ b/src/V3Order.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Order { +class V3Order final { public: static void orderAll(AstNetlist* nodep); }; diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index 9ff15d083..579ea70bb 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -110,7 +110,7 @@ inline bool operator==(OrderVEdgeType::en lhs, const OrderVEdgeType& rhs) { //###################################################################### // Graph types -class OrderGraph : public V3Graph { +class OrderGraph final : public V3Graph { public: OrderGraph() = default; virtual ~OrderGraph() override = default; @@ -121,7 +121,7 @@ public: //###################################################################### // Vertex types -class OrderEitherVertex : public V3GraphVertex { +class OrderEitherVertex VL_NOT_FINAL : public V3GraphVertex { AstScope* m_scopep; // Scope the vertex is in AstSenTree* m_domainp; // Clock domain (nullptr = to be computed as we iterate) bool m_isFromInput = false; // From input, or derived therefrom (conservatively false) @@ -151,7 +151,7 @@ public: bool isFromInput() const { return m_isFromInput; } }; -class OrderInputsVertex : public OrderEitherVertex { +class OrderInputsVertex final : public OrderEitherVertex { OrderInputsVertex(V3Graph* graphp, const OrderInputsVertex& old) : OrderEitherVertex{graphp, old} {} @@ -171,7 +171,7 @@ public: virtual bool domainMatters() override { return false; } }; -class OrderLogicVertex : public OrderEitherVertex { +class OrderLogicVertex final : public OrderEitherVertex { AstNode* m_nodep; protected: @@ -197,7 +197,7 @@ public: virtual string dotColor() const override { return "yellow"; } }; -class OrderVarVertex : public OrderEitherVertex { +class OrderVarVertex VL_NOT_FINAL : public OrderEitherVertex { AstVarScope* m_varScp; bool m_isClock = false; // Used as clock bool m_isDelayed = false; // Set in a delayed assignment @@ -224,7 +224,7 @@ public: bool isDelayed() const { return m_isDelayed; } }; -class OrderVarStdVertex : public OrderVarVertex { +class OrderVarStdVertex final : public OrderVarVertex { OrderVarStdVertex(V3Graph* graphp, const OrderVarStdVertex& old) : OrderVarVertex{graphp, old} {} @@ -242,7 +242,7 @@ public: virtual string dotColor() const override { return "skyblue"; } virtual bool domainMatters() override { return true; } }; -class OrderVarPreVertex : public OrderVarVertex { +class OrderVarPreVertex final : public OrderVarVertex { OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old) : OrderVarVertex{graphp, old} {} @@ -260,7 +260,7 @@ public: virtual string dotColor() const override { return "lightblue"; } virtual bool domainMatters() override { return false; } }; -class OrderVarPostVertex : public OrderVarVertex { +class OrderVarPostVertex final : public OrderVarVertex { OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old) : OrderVarVertex{graphp, old} {} @@ -278,7 +278,7 @@ public: virtual string dotColor() const override { return "CadetBlue"; } virtual bool domainMatters() override { return false; } }; -class OrderVarPordVertex : public OrderVarVertex { +class OrderVarPordVertex final : public OrderVarVertex { OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old) : OrderVarVertex{graphp, old} {} @@ -296,7 +296,7 @@ public: virtual string dotColor() const override { return "NavyBlue"; } virtual bool domainMatters() override { return false; } }; -class OrderVarSettleVertex : public OrderVarVertex { +class OrderVarSettleVertex final : public OrderVarVertex { OrderVarSettleVertex(V3Graph* graphp, const OrderVarSettleVertex& old) : OrderVarVertex{graphp, old} {} @@ -318,7 +318,7 @@ public: //###################################################################### //--- Following only under the move graph, not the main graph -class OrderMoveVertex : public V3GraphVertex { +class OrderMoveVertex final : public V3GraphVertex { typedef enum : uint8_t { POM_WAIT, POM_READY, POM_MOVED } OrderMState; OrderLogicVertex* m_logicp; @@ -387,7 +387,7 @@ public: }; // Similar to OrderMoveVertex, but modified for threaded code generation. -class MTaskMoveVertex : public V3GraphVertex { +class MTaskMoveVertex final : public V3GraphVertex { // This could be more compact, since we know m_varp and m_logicp // cannot both be set. Each MTaskMoveVertex represents a logic node // or a var node, it can't be both. @@ -445,7 +445,7 @@ public: //###################################################################### // Edge types -class OrderEdge : public V3GraphEdge { +class OrderEdge VL_NOT_FINAL : public V3GraphEdge { protected: OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderEdge& old) : V3GraphEdge{graphp, fromp, top, old} {} @@ -470,7 +470,7 @@ public: } }; -class OrderComboCutEdge : public OrderEdge { +class OrderComboCutEdge final : public OrderEdge { // Edge created from output of combo logic // Breakable if the output var is also a input, // in which case we'll need a change detect loop around this var. @@ -491,7 +491,7 @@ public: virtual bool followComboConnected() const override { return true; } }; -class OrderPostCutEdge : public OrderEdge { +class OrderPostCutEdge final : public OrderEdge { // Edge created from output of post assignment // Breakable if the output var feeds back to input combo logic or another clock pin // in which case we'll need a change detect loop around this var. @@ -512,7 +512,7 @@ public: virtual bool followComboConnected() const override { return false; } }; -class OrderPreCutEdge : public OrderEdge { +class OrderPreCutEdge final : public OrderEdge { // Edge created from var_PREVAR->consuming logic vertex // Always breakable, just results in performance loss // in which case we can't optimize away the pre/post delayed assignments diff --git a/src/V3Os.h b/src/V3Os.h index 21fa583b9..a1eef9b86 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -28,7 +28,7 @@ //============================================================================ // V3Os: OS static class -class V3Os { +class V3Os final { public: // METHODS (environment) static string getenvStr(const string& envvar, const string& defaultValue); diff --git a/src/V3Param.cpp b/src/V3Param.cpp index a73845d39..6c491ae5e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -65,7 +65,7 @@ //###################################################################### // Hierarchical block and parameter db (modules without parameter is also handled) -class ParameterizedHierBlocks { +class ParameterizedHierBlocks final { typedef std::multimap HierBlockOptsByOrigName; typedef HierBlockOptsByOrigName::const_iterator HierMapIt; typedef std::map HierBlockModMap; @@ -197,7 +197,7 @@ public: //###################################################################### // Param state, as a visitor of each AstNode -class ParamVisitor : public AstNVisitor { +class ParamVisitor final : public AstNVisitor { private: // NODE STATE // AstNodeModule::user5() // bool True if processed diff --git a/src/V3Param.h b/src/V3Param.h index a2354de03..750e4177c 100644 --- a/src/V3Param.h +++ b/src/V3Param.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Param { +class V3Param final { public: static void param(AstNetlist* rootp); }; diff --git a/src/V3Parse.h b/src/V3Parse.h index 47bb0206e..198af1757 100644 --- a/src/V3Parse.h +++ b/src/V3Parse.h @@ -30,7 +30,7 @@ class V3ParseSym; //============================================================================ -class V3Parse { +class V3Parse final { private: V3ParseImp* m_impp; diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index c460ee22a..ee58a7eeb 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -156,7 +156,7 @@ std::ostream& operator<<(std::ostream& os, const V3ParseBisonYYSType& rhs); //###################################################################### -class V3ParseImp { +class V3ParseImp final { // MEMBERS AstNetlist* m_rootp; // Root of the design VInFilter* m_filterp; // Reading filter diff --git a/src/V3ParseLex.cpp b/src/V3ParseLex.cpp index 709f2fe96..04bfa9b90 100644 --- a/src/V3ParseLex.cpp +++ b/src/V3ParseLex.cpp @@ -32,7 +32,7 @@ // Lex-derived class /// Override the base lexer class so we can add some access functions -class V3Lexer : public V3LexerBase { +class V3Lexer final : public V3LexerBase { public: // CONSTRUCTORS V3Lexer() diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h index 60a829ace..42045f273 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -30,7 +30,7 @@ //###################################################################### // Symbol table for parsing -class V3ParseSym { +class V3ParseSym final { // TYPES typedef std::vector SymStack; diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index b927ad644..78ee3e236 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -243,7 +243,7 @@ private: VL_UNCOPYABLE(PartPropagateCp); }; -class PartPropagateCpSelfTest { +class PartPropagateCpSelfTest final { private: // MEMBERS V3Graph m_graph; // A graph @@ -350,7 +350,7 @@ public: //###################################################################### // LogicMTask -class LogicMTask : public AbstractLogicMTask { +class LogicMTask final : public AbstractLogicMTask { public: // TYPES typedef std::list VxList; @@ -366,7 +366,7 @@ public: // - PartPropagateCp can thus be declared before LogicMTask // - PartPropagateCp could be reused with graphs of other node types // in the future, using another Accessor adaptor. - class CpCostAccessor { + class CpCostAccessor final { public: CpCostAccessor() = default; ~CpCostAccessor() = default; @@ -690,7 +690,7 @@ private: // Sort AbstractMTask objects into deterministic order by calling id() // which is a unique and stable serial number. -class MTaskIdLessThan { +class MTaskIdLessThan final { public: MTaskIdLessThan() = default; virtual ~MTaskIdLessThan() = default; @@ -700,7 +700,7 @@ public: }; // Information associated with scoreboarding an MTask -class MergeCandidate { +class MergeCandidate VL_NOT_FINAL { private: bool m_removedFromSb = false; // Not on scoreboard, generally ignore vluint64_t m_id; // Serial number for ordering @@ -720,7 +720,7 @@ public: // A pair of associated LogicMTask's that are merge candidates for sibling // contraction -class SiblingMC : public MergeCandidate { +class SiblingMC final : public MergeCandidate { private: LogicMTask* m_ap; LogicMTask* m_bp; @@ -755,7 +755,7 @@ public: }; // GraphEdge for the MTask graph -class MTaskEdge : public V3GraphEdge, public MergeCandidate { +class MTaskEdge final : public V3GraphEdge, public MergeCandidate { public: // CONSTRUCTORS MTaskEdge(V3Graph* graphp, LogicMTask* fromp, LogicMTask* top, int weight) @@ -801,7 +801,7 @@ private: //###################################################################### // Vertex utility classes -class OrderByPtrId { +class OrderByPtrId final { PartPtrIdMap m_ids; public: @@ -815,7 +815,7 @@ public: //###################################################################### // PartParallelismEst - Estimate parallelism of graph -class PartParallelismEst { +class PartParallelismEst final { // MEMBERS const V3Graph* m_graphp; // Mtask-containing graph @@ -1028,7 +1028,7 @@ static void partMergeEdgesFrom(V3Graph* mtasksp, LogicMTask* recipientp, LogicMT // PartContraction // Perform edge or sibling contraction on the partition graph -class PartContraction { +class PartContraction final { private: // TYPES @@ -1633,7 +1633,7 @@ const GraphWay* PartContraction::s_shortestWaywardCpInclusiveWay = nullptr; // Scan node, indicate whether it contains a call to a DPI imported // routine. -class DpiImportCallVisitor : public AstNVisitor { +class DpiImportCallVisitor final : public AstNVisitor { private: bool m_hasDpiHazard = false; // Found a DPI import call. bool m_tracingCall = false; // Iterating into a CCall to a CFunc @@ -1753,7 +1753,7 @@ private: // clock signal. This leads to unordered reader/writer pairs in // parallel mode. // -class PartFixDataHazards { +class PartFixDataHazards final { private: // TYPES typedef std::set LogicMTaskSet; @@ -2015,7 +2015,7 @@ private: // depending on which thread is looking. Be a little bit pessimistic when // thread A checks the end time of an mtask running on thread B. This extra // "padding" avoids tight "layovers" at cross-thread dependencies. -class PartPackMTasks { +class PartPackMTasks final { private: // TYPES struct MTaskState { diff --git a/src/V3Partition.h b/src/V3Partition.h index 46cc267b2..0a91c6010 100644 --- a/src/V3Partition.h +++ b/src/V3Partition.h @@ -34,7 +34,7 @@ typedef std::unordered_map Vx2MTaskMap; /// of which contains of set of the logic nodes from the fine-grained /// graph. -class V3Partition { +class V3Partition final { // MEMBERS V3Graph* m_fineDepsGraphp; // Fine-grained dependency graph public: @@ -73,7 +73,7 @@ private: //************************************************************************* // Map a pointer into a id, for e.g. nodep to mtask mappings -class PartPtrIdMap { +class PartPtrIdMap final { private: // TYPES typedef std::unordered_map PtrMap; diff --git a/src/V3PartitionGraph.h b/src/V3PartitionGraph.h index 789125bba..74276c92d 100644 --- a/src/V3PartitionGraph.h +++ b/src/V3PartitionGraph.h @@ -28,7 +28,7 @@ //************************************************************************* // MTasks and graph structures -class AbstractMTask : public V3GraphVertex { +class AbstractMTask VL_NOT_FINAL : public V3GraphVertex { public: AbstractMTask(V3Graph* graphp) : V3GraphVertex{graphp} {} @@ -37,7 +37,7 @@ public: virtual uint32_t cost() const = 0; }; -class AbstractLogicMTask : public AbstractMTask { +class AbstractLogicMTask VL_NOT_FINAL : public AbstractMTask { public: // TYPES typedef std::list VxList; @@ -52,7 +52,7 @@ public: virtual uint32_t cost() const override = 0; }; -class ExecMTask : public AbstractMTask { +class ExecMTask final : public AbstractMTask { private: AstMTaskBody* m_bodyp; // Task body uint32_t m_id; // Unique id of this mtask. diff --git a/src/V3PreLex.h b/src/V3PreLex.h index 34f978de0..ee801421f 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -126,7 +126,7 @@ void yy_delete_buffer(YY_BUFFER_STATE b); //====================================================================== // Entry for each file processed; a stack of entries included -class VPreStream { +class VPreStream final { public: FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep) V3PreLex* m_lexp; // Lexer, for resource tracking @@ -149,7 +149,7 @@ private: //====================================================================== // Class entry for each per-lexer state -class V3PreLex { +class V3PreLex final { public: // Used only by V3PreLex.cpp and V3PreProc.cpp V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to std::stack m_streampStack; // Stack of processing files diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 344b939c2..122385e8f 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -43,7 +43,7 @@ //************************************************************************* -class VDefine { +class VDefine final { // Define class. One for each define. // string m_name; // Name of the define (list is keyed by this) FileLine* m_fileline; // Where it was declared @@ -64,7 +64,7 @@ public: //************************************************************************* -class VDefineRef { +class VDefineRef final { // One for each pending define substitution string m_name; // Define last name being defined string m_params; // Define parameter list for next expansion @@ -89,7 +89,7 @@ public: //************************************************************************* /// Data for parsing on/off -class VPreIfEntry { +class VPreIfEntry final { // One for each pending ifdef/ifndef bool m_on; // Current parse for this ifdef level is "on" bool m_everOn; // Some if term in elsif tree has been on @@ -105,7 +105,7 @@ public: //************************************************************************* // Data for a preprocessor instantiation. -class V3PreProcImp : public V3PreProc { +class V3PreProcImp final : public V3PreProc { public: // TYPES typedef std::map DefinesMap; diff --git a/src/V3PreProc.h b/src/V3PreProc.h index aae1dff36..39c7dbb48 100644 --- a/src/V3PreProc.h +++ b/src/V3PreProc.h @@ -33,7 +33,7 @@ class VInFilter; class VSpellCheck; -class V3PreProc { +class V3PreProc VL_NOT_FINAL { // This defines a preprocessor. Functions are virtual so implementation can be hidden. // After creating, call open(), then getline() in a loop. The class will to the rest... diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp index bdef192cd..e2f1042dd 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -29,7 +29,7 @@ //###################################################################### -class V3PreShellImp { +class V3PreShellImp final { protected: friend class V3PreShell; diff --git a/src/V3PreShell.h b/src/V3PreShell.h index ec8a7678a..3428a8a88 100644 --- a/src/V3PreShell.h +++ b/src/V3PreShell.h @@ -29,7 +29,7 @@ class VSpellCheck; //============================================================================ -class V3PreShell { +class V3PreShell final { // Static class for calling preprocessor public: static void boot(char** env); diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index bdbff1af1..5865a902f 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -36,7 +36,7 @@ //###################################################################### // Structure for global state -class PremitAssignVisitor : public AstNVisitor { +class PremitAssignVisitor final : public AstNVisitor { private: // NODE STATE // AstVar::user4() // bool; occurs on LHS of current assignment @@ -82,7 +82,7 @@ public: //###################################################################### // Premit state, as a visitor of each AstNode -class PremitVisitor : public AstNVisitor { +class PremitVisitor final : public AstNVisitor { private: // NODE STATE // AstNodeMath::user() -> bool. True if iterated already diff --git a/src/V3Premit.h b/src/V3Premit.h index b7a5e302d..8d798665c 100644 --- a/src/V3Premit.h +++ b/src/V3Premit.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Premit { +class V3Premit final { public: static void premitAll(AstNetlist* nodep); }; diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index 88bf6ba8f..599699b5a 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -28,7 +28,7 @@ //###################################################################### // ProtectLib top-level visitor -class ProtectVisitor : public AstNVisitor { +class ProtectVisitor final : public AstNVisitor { private: AstVFile* m_vfilep = nullptr; // DPI-enabled Verilog wrapper AstCFile* m_cfilep = nullptr; // C implementation of DPI functions diff --git a/src/V3ProtectLib.h b/src/V3ProtectLib.h index 879305054..8bb167db3 100644 --- a/src/V3ProtectLib.h +++ b/src/V3ProtectLib.h @@ -25,7 +25,7 @@ //============================================================================ -class V3ProtectLib { +class V3ProtectLib final { public: static void protect(); }; diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index 50c3e9e30..71379aa05 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -43,7 +43,7 @@ constexpr unsigned RELOOP_MIN_ITERS = 40; // Need at least this many loops to d //###################################################################### -class ReloopVisitor : public AstNVisitor { +class ReloopVisitor final : public AstNVisitor { private: // TYPES typedef std::vector AssVec; diff --git a/src/V3Reloop.h b/src/V3Reloop.h index 674ef408f..fb0a748dc 100644 --- a/src/V3Reloop.h +++ b/src/V3Reloop.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Reloop { +class V3Reloop final { public: static void reloopAll(AstNetlist* nodep); }; diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index a26971951..a1374541e 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -36,7 +36,7 @@ //###################################################################### // Scope class functions -class ScopeVisitor : public AstNVisitor { +class ScopeVisitor final : public AstNVisitor { private: // NODE STATE // AstVar::user1p -> AstVarScope replacement for this variable @@ -319,7 +319,7 @@ public: //###################################################################### // Scope cleanup -- remove unused activates -class ScopeCleanupVisitor : public AstNVisitor { +class ScopeCleanupVisitor final : public AstNVisitor { private: // STATE AstScope* m_scopep = nullptr; // Current scope we are building diff --git a/src/V3Scope.h b/src/V3Scope.h index 46a9691a4..ffce787f9 100644 --- a/src/V3Scope.h +++ b/src/V3Scope.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Scope { +class V3Scope final { public: static void scopeAll(AstNetlist* nodep); }; diff --git a/src/V3Scoreboard.cpp b/src/V3Scoreboard.cpp index cf25c090e..42df6dbd8 100644 --- a/src/V3Scoreboard.cpp +++ b/src/V3Scoreboard.cpp @@ -19,7 +19,7 @@ #include "V3Scoreboard.h" -class ScoreboardTestElem { +class ScoreboardTestElem final { public: // MEMBERS uint32_t m_score; diff --git a/src/V3Scoreboard.h b/src/V3Scoreboard.h index 2aa8207c3..d0a1ec3e7 100644 --- a/src/V3Scoreboard.h +++ b/src/V3Scoreboard.h @@ -41,7 +41,7 @@ /// break ties in the sort when values collide. template > -class SortByValueMap { +class SortByValueMap final { // TYPES private: typedef std::unordered_map Key2Val; @@ -56,7 +56,7 @@ public: // CONSTRUCTORS SortByValueMap() = default; - class const_iterator { + class const_iterator VL_NOT_FINAL { // TYPES public: typedef const_iterator value_type; @@ -193,7 +193,7 @@ public: } }; - class iterator : public const_iterator { + class iterator final : public const_iterator { public: // TYPES typedef iterator value_type; @@ -350,11 +350,11 @@ private: /// the full set size. template > -class V3Scoreboard { +class V3Scoreboard final { private: // TYPES typedef std::unordered_set NeedRescoreSet; - class CmpElems { + class CmpElems final { public: bool operator()(const T_Elem* const& ap, const T_Elem* const& bp) const { T_ElemCompare cmp; diff --git a/src/V3SenTree.h b/src/V3SenTree.h index b1fa10947..b64937081 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -31,7 +31,7 @@ // Collect SenTrees under the entire scope // And provide functions to find/add a new one -class SenTreeSet { +class SenTreeSet final { // Hash table of sensitive blocks. private: // TYPES @@ -71,7 +71,7 @@ private: VL_UNCOPYABLE(SenTreeSet); }; -class SenTreeFinder { +class SenTreeFinder final { private: // STATE AstTopScope* m_topScopep = nullptr; // Top scope to add global SenTrees to diff --git a/src/V3Simulate.h b/src/V3Simulate.h index cec2c81ee..6a251e905 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -48,7 +48,7 @@ //###################################################################### // Simulate class functions -class SimStackNode { +class SimStackNode final { public: // MEMBERS AstFuncRef* m_funcp; @@ -63,7 +63,7 @@ public: typedef std::deque ConstDeque; typedef std::map ConstPile; -class SimulateVisitor : public AstNVisitor { +class SimulateVisitor VL_NOT_FINAL : public AstNVisitor { // Simulate a node tree, returning value of variables // Two major operating modes: // Test the tree to see if it is conformant diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 76a31cde6..3c66b1648 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -44,7 +44,7 @@ //************************************************************************* -class SliceVisitor : public AstNVisitor { +class SliceVisitor final : public AstNVisitor { // NODE STATE // Cleared on netlist // AstNodeAssign::user1() -> bool. True if find is complete diff --git a/src/V3Slice.h b/src/V3Slice.h index 1ac23ac24..ad711d0f2 100644 --- a/src/V3Slice.h +++ b/src/V3Slice.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Slice { +class V3Slice final { public: static void sliceAll(AstNetlist* nodep); }; diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 83fc53856..9b7e0cd85 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -95,7 +95,7 @@ //###################################################################### // Support classes -class SplitNodeVertex : public V3GraphVertex { +class SplitNodeVertex VL_NOT_FINAL : public V3GraphVertex { AstNode* m_nodep; protected: @@ -115,7 +115,7 @@ public: virtual AstNode* nodep() const { return m_nodep; } }; -class SplitPliVertex : public SplitNodeVertex { +class SplitPliVertex final : public SplitNodeVertex { public: explicit SplitPliVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} @@ -124,7 +124,7 @@ public: virtual string dotColor() const override { return "green"; } }; -class SplitLogicVertex : public SplitNodeVertex { +class SplitLogicVertex final : public SplitNodeVertex { public: SplitLogicVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} @@ -132,7 +132,7 @@ public: virtual string dotColor() const override { return "yellow"; } }; -class SplitVarStdVertex : public SplitNodeVertex { +class SplitVarStdVertex final : public SplitNodeVertex { public: SplitVarStdVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} @@ -140,7 +140,7 @@ public: virtual string dotColor() const override { return "skyblue"; } }; -class SplitVarPostVertex : public SplitNodeVertex { +class SplitVarPostVertex final : public SplitNodeVertex { public: SplitVarPostVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} @@ -152,7 +152,7 @@ public: //###################################################################### // Edge types -class SplitEdge : public V3GraphEdge { +class SplitEdge VL_NOT_FINAL : public V3GraphEdge { uint32_t m_ignoreInStep = 0; // Step number that if set to, causes this edge to be ignored static uint32_t s_stepNum; // Global step number protected: @@ -185,7 +185,7 @@ public: }; uint32_t SplitEdge::s_stepNum = 0; -class SplitPostEdge : public SplitEdge { +class SplitPostEdge final : public SplitEdge { public: SplitPostEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} @@ -194,7 +194,7 @@ public: virtual string dotColor() const override { return "khaki"; } }; -class SplitLVEdge : public SplitEdge { +class SplitLVEdge final : public SplitEdge { public: SplitLVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} @@ -203,7 +203,7 @@ public: virtual string dotColor() const override { return "yellowGreen"; } }; -class SplitRVEdge : public SplitEdge { +class SplitRVEdge final : public SplitEdge { public: SplitRVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} @@ -235,7 +235,7 @@ public: //###################################################################### // Split class functions -class SplitReorderBaseVisitor : public AstNVisitor { +class SplitReorderBaseVisitor VL_NOT_FINAL : public AstNVisitor { private: // NODE STATE // AstVarScope::user1p -> Var SplitNodeVertex* for usage var, 0=not set yet @@ -439,7 +439,7 @@ private: VL_UNCOPYABLE(SplitReorderBaseVisitor); }; -class ReorderVisitor : public SplitReorderBaseVisitor { +class ReorderVisitor final : public SplitReorderBaseVisitor { // CONSTRUCTORS public: explicit ReorderVisitor(AstNetlist* nodep) { iterate(nodep); } @@ -622,7 +622,7 @@ private: typedef std::unordered_set ColorSet; typedef std::vector AlwaysVec; -class IfColorVisitor : public AstNVisitor { +class IfColorVisitor final : public AstNVisitor { // MEMBERS ColorSet m_colors; // All colors in the original always block @@ -680,7 +680,7 @@ private: VL_UNCOPYABLE(IfColorVisitor); }; -class EmitSplitVisitor : public AstNVisitor { +class EmitSplitVisitor final : public AstNVisitor { // MEMBERS AstAlways* m_origAlwaysp; // Block that *this will split const IfColorVisitor* m_ifColorp; // Digest of results of prior coloring @@ -793,7 +793,7 @@ private: VL_UNCOPYABLE(EmitSplitVisitor); }; -class RemovePlaceholdersVisitor : public AstNVisitor { +class RemovePlaceholdersVisitor final : public AstNVisitor { typedef std::unordered_set NodeSet; NodeSet m_removeSet; // placeholders to be removed public: @@ -812,7 +812,7 @@ private: VL_UNCOPYABLE(RemovePlaceholdersVisitor); }; -class SplitVisitor : public SplitReorderBaseVisitor { +class SplitVisitor final : public SplitReorderBaseVisitor { private: // Keys are original always blocks pending delete, // values are newly split always blocks pending insertion diff --git a/src/V3Split.h b/src/V3Split.h index a60268cee..bcabc01e3 100644 --- a/src/V3Split.h +++ b/src/V3Split.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Split { +class V3Split final { public: static void splitReorderAll(AstNetlist* nodep); static void splitAlwaysAll(AstNetlist* nodep); diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index 8b69134e6..e40a87f42 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -33,7 +33,7 @@ //###################################################################### -class SplitAsBaseVisitor : public AstNVisitor { +class SplitAsBaseVisitor VL_NOT_FINAL : public AstNVisitor { public: // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -42,7 +42,7 @@ public: //###################################################################### // Find all split variables in a block -class SplitAsFindVisitor : public SplitAsBaseVisitor { +class SplitAsFindVisitor final : public SplitAsBaseVisitor { private: // STATE AstVarScope* m_splitVscp = nullptr; // Variable we want to split @@ -66,7 +66,7 @@ public: //###################################################################### // Remove nodes not containing proper references -class SplitAsCleanVisitor : public SplitAsBaseVisitor { +class SplitAsCleanVisitor final : public SplitAsBaseVisitor { private: // STATE AstVarScope* m_splitVscp; // Variable we want to split @@ -124,7 +124,7 @@ public: //###################################################################### // SplitAs class functions -class SplitAsVisitor : public SplitAsBaseVisitor { +class SplitAsVisitor final : public SplitAsBaseVisitor { private: // NODE STATE // AstAlways::user() -> bool. True if already processed diff --git a/src/V3SplitAs.h b/src/V3SplitAs.h index e42d03678..82f9d4915 100644 --- a/src/V3SplitAs.h +++ b/src/V3SplitAs.h @@ -25,7 +25,7 @@ //============================================================================ -class V3SplitAs { +class V3SplitAs final { public: static void splitAsAll(AstNetlist* nodep); }; diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 9abdbe246..fd191ec24 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -232,7 +232,7 @@ struct AstNodeComparator { } }; -class UnpackRef { +class UnpackRef final { // m_nodep is called in this context (AstNodeStmt, AstCell, AstNodeFTask, or AstAlways) AstNode* m_contextp; AstNode* m_nodep; // ArraySel, SliceSel, ArrayVarRef (entire value) @@ -283,7 +283,7 @@ public: } }; -class UnpackRefMap { +class UnpackRefMap final { public: typedef std::map, AstNodeComparator> MapType; typedef MapType::iterator MapIt; @@ -384,7 +384,7 @@ public: typedef std::map SplitVarRefsMap; -class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { +class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl { typedef std::set VarSet; VarSet m_foundTargetVar; UnpackRefMap m_refs; @@ -802,7 +802,7 @@ public: // Split packed variables // Split variable -class SplitNewVar { +class SplitNewVar final { int m_lsb; // LSB in the original bitvector int m_bitwidth; AstVar* m_varp; // The LSB of this variable is always 0, not m_lsb @@ -828,7 +828,7 @@ public: }; // One Entry instance for an AstVarRef instance -class PackedVarRefEntry { +class PackedVarRefEntry final { AstNode* m_nodep; // Either AstSel or AstVarRef is expected. int m_lsb; int m_bitwidth; @@ -859,7 +859,7 @@ public: }; // How a variable is used -class PackedVarRef { +class PackedVarRef final { struct SortByFirst { bool operator()(const std::pair& a, const std::pair& b) const { if (a.first == b.first) return a.second < b.second; @@ -956,7 +956,7 @@ public: } }; -class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { +class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { typedef std::map PackedVarRefMap; AstNetlist* m_netp; AstNodeModule* m_modp; // Current module (just for log) diff --git a/src/V3SplitVar.h b/src/V3SplitVar.h index f9c1c64ab..41195bc57 100644 --- a/src/V3SplitVar.h +++ b/src/V3SplitVar.h @@ -22,7 +22,7 @@ class AstNetlist; class AstVar; -class V3SplitVar { +class V3SplitVar final { public: // Split variables marked with split_var metacomment. static void splitVariable(AstNetlist* nodep); diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index a73df13e4..612ea0244 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -30,7 +30,7 @@ //###################################################################### // Stats class functions -class StatsVisitor : public AstNVisitor { +class StatsVisitor final : public AstNVisitor { private: // NODE STATE/TYPES diff --git a/src/V3Stats.h b/src/V3Stats.h index 084eb312c..7f9012238 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -26,7 +26,7 @@ class AstNetlist; //============================================================================ -class VDouble0 { +class VDouble0 final { // Double counter, initializes to zero for easy use double m_d = 0.0; ///< Count of occurrences/ value public: @@ -65,7 +65,7 @@ public: //============================================================================ -class V3Statistic { +class V3Statistic final { // A statistical entry we want published into the database string m_name; ///< Nameiption of this statistic double m_count; ///< Count of occurrences/ value @@ -99,7 +99,7 @@ public: //============================================================================ -class V3Stats { +class V3Stats final { public: static void addStat(const V3Statistic&); static void addStat(const string& stage, const string& name, double count) { diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp index e93491eec..24c84932e 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -30,7 +30,7 @@ //###################################################################### // Stats dumping -class StatsReport { +class StatsReport final { // TYPES typedef std::vector StatColl; diff --git a/src/V3String.h b/src/V3String.h index 1a700d264..af5437092 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -66,7 +66,7 @@ inline string ucfirst(const string& text) { //###################################################################### // VString - String manipulation -class VString { +class VString final { static bool wildmatchi(const char* s, const char* p); public: @@ -104,7 +104,7 @@ public: //###################################################################### // VHashSha256 - Compute Sha256 hashes -class VHashSha256 { +class VHashSha256 final { // As blocks must be processed in 64 byte chunks, this does not at present // support calling input() on multiple non-64B chunks and getting the correct // hash. To do that first combine the string before calling here. @@ -157,7 +157,7 @@ private: // VName - string which contains a possibly hashed string // TODO use this wherever there is currently a "string m_name" -class VName { +class VName final { string m_name; string m_hashed; static std::map s_dehashMap; // hashed -> original decoder @@ -187,7 +187,7 @@ public: //###################################################################### // VSpellCheck - Find near-match spelling suggestions given list of possibilities -class VSpellCheck { +class VSpellCheck final { // CONSTANTS static constexpr unsigned NUM_CANDIDATE_LIMIT = 10000; // Avoid searching huge netlists static constexpr unsigned LENGTH_LIMIT = 100; // Maximum string length to search diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index 8590a57cf..8a0bb483c 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -36,7 +36,7 @@ //###################################################################### // Common debugging baseclass -class SubstBaseVisitor : public AstNVisitor { +class SubstBaseVisitor VL_NOT_FINAL : public AstNVisitor { public: VL_DEBUG_FUNC; // Declare debug() }; @@ -44,7 +44,7 @@ public: //###################################################################### // Class for each word of a multi-word variable -class SubstVarWord { +class SubstVarWord final { protected: // MEMBERS AstNodeAssign* m_assignp; // Last assignment to each word of this var @@ -64,7 +64,7 @@ protected: //###################################################################### // Class for every variable we may process -class SubstVarEntry { +class SubstVarEntry final { // MEMBERS AstVar* m_varp; // Variable this tracks bool m_wordAssign = false; // True if any word assignments @@ -174,7 +174,7 @@ public: // See if any variables have changed value since we determined subst value, // as a visitor of each AstNode -class SubstUseVisitor : public SubstBaseVisitor { +class SubstUseVisitor final : public SubstBaseVisitor { private: // NODE STATE // See SubstVisitor @@ -221,7 +221,7 @@ public: //###################################################################### // Subst state, as a visitor of each AstNode -class SubstVisitor : public SubstBaseVisitor { +class SubstVisitor final : public SubstBaseVisitor { private: // NODE STATE // Passed to SubstUseVisitor diff --git a/src/V3Subst.h b/src/V3Subst.h index fbc3e5708..9906f3487 100644 --- a/src/V3Subst.h +++ b/src/V3Subst.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Subst { +class V3Subst final { public: static void substituteAll(AstNetlist* nodep); }; diff --git a/src/V3SymTable.h b/src/V3SymTable.h index e77b982d7..68a2296f0 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -38,7 +38,7 @@ class VSymEnt; typedef std::set VSymConstMap; -class VSymEnt { +class VSymEnt final { // Symbol table that can have a "superior" table for resolving upper references // MEMBERS typedef std::multimap IdNameMap; @@ -277,7 +277,7 @@ public: //###################################################################### // Symbol tables -class VSymGraph { +class VSymGraph final { // Collection of symbol tables // TYPES typedef std::vector SymStack; diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 07a6d9e84..140815c74 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -119,7 +119,7 @@ public: return vertices; } - class EdgeCmp { + class EdgeCmp final { // Provides a deterministic compare for outgoing V3GraphEdge's // to be used in Prim's algorithm below. Also used in the // perfectMatching() routine. @@ -494,7 +494,7 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { //###################################################################### // Self Tests -class TspTestState : public V3TSP::TspStateBase { +class TspTestState final : public V3TSP::TspStateBase { public: TspTestState(unsigned xpos, unsigned ypos) : m_xpos{xpos} diff --git a/src/V3TSP.h b/src/V3TSP.h index cc9e79fed..b3cc20808 100644 --- a/src/V3TSP.h +++ b/src/V3TSP.h @@ -27,7 +27,7 @@ namespace V3TSP { // Perform a "Traveling Salesman Problem" optimizing sort // on any type you like -- so long as inherits from TspStateBase. -class TspStateBase { +class TspStateBase VL_NOT_FINAL { public: // This is the cost function that the TSP sort will minimize. // All costs in V3TSP are int, chosen to match the type of diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 6918493e1..271c8c649 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -48,7 +48,7 @@ static const int TABLE_MIN_NODE_COUNT = 32; // If < 32 instructions, not worth class TableVisitor; -class TableSimulateVisitor : public SimulateVisitor { +class TableSimulateVisitor final : public SimulateVisitor { // MEMBERS TableVisitor* m_cbthis; ///< Class for callback @@ -65,7 +65,7 @@ public: //###################################################################### // Table class functions -class TableVisitor : public AstNVisitor { +class TableVisitor final : public AstNVisitor { private: // NODE STATE // Cleared on each always/assignw diff --git a/src/V3Table.h b/src/V3Table.h index c54220b8d..3ad3de773 100644 --- a/src/V3Table.h +++ b/src/V3Table.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Table { +class V3Table final { public: static void tableAll(AstNetlist* nodep); }; diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 8cb19bedb..90f776cf3 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -39,7 +39,7 @@ //###################################################################### // Graph subclasses -class TaskBaseVertex : public V3GraphVertex { +class TaskBaseVertex VL_NOT_FINAL : public V3GraphVertex { AstNode* m_impurep = nullptr; // Node causing impure function w/ outside references bool m_noInline = false; // Marked with pragma public: @@ -53,7 +53,7 @@ public: void noInline(bool flag) { m_noInline = flag; } }; -class TaskFTaskVertex : public TaskBaseVertex { +class TaskFTaskVertex final : public TaskBaseVertex { // Every task gets a vertex, and we link tasks together based on funcrefs. AstNodeFTask* m_nodep; AstCFunc* m_cFuncp = nullptr; @@ -71,7 +71,7 @@ public: void cFuncp(AstCFunc* nodep) { m_cFuncp = nodep; } }; -class TaskCodeVertex : public TaskBaseVertex { +class TaskCodeVertex final : public TaskBaseVertex { // Top vertex for all calls not under another task public: explicit TaskCodeVertex(V3Graph* graphp) @@ -81,7 +81,7 @@ public: virtual string dotColor() const override { return "green"; } }; -class TaskEdge : public V3GraphEdge { +class TaskEdge final : public V3GraphEdge { public: TaskEdge(V3Graph* graphp, TaskBaseVertex* fromp, TaskBaseVertex* top) : V3GraphEdge{graphp, fromp, top, 1, false} {} @@ -91,7 +91,7 @@ public: //###################################################################### -class TaskStateVisitor : public AstNVisitor { +class TaskStateVisitor final : public AstNVisitor { private: // NODE STATE // Output: @@ -287,7 +287,7 @@ public: //###################################################################### -class TaskRelinkVisitor : public AstNVisitor { +class TaskRelinkVisitor final : public AstNVisitor { // Replace varrefs with new var pointer private: // NODE STATE @@ -323,7 +323,7 @@ public: //###################################################################### // Task state, as a visitor of each AstNode -class TaskVisitor : public AstNVisitor { +class TaskVisitor final : public AstNVisitor { private: // NODE STATE // Each module: diff --git a/src/V3Task.h b/src/V3Task.h index a1722a16c..9c162dccc 100644 --- a/src/V3Task.h +++ b/src/V3Task.h @@ -32,7 +32,7 @@ typedef std::vector V3TaskConnects; // [ [port, pin-connects-to] //============================================================================ -class V3Task { +class V3Task final { public: static void taskAll(AstNetlist* nodep); /// Return vector of [port, pin-connects-to] (SLOW) diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index a1598bb70..9a704175b 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -51,7 +51,7 @@ //###################################################################### // Graph vertexes -class TraceActivityVertex : public V3GraphVertex { +class TraceActivityVertex final : public V3GraphVertex { AstNode* const m_insertp; vlsint32_t m_activityCode; bool m_slow; // If always slow, we can use the same code @@ -95,7 +95,7 @@ public: } }; -class TraceCFuncVertex : public V3GraphVertex { +class TraceCFuncVertex final : public V3GraphVertex { AstCFunc* m_nodep; public: @@ -110,7 +110,7 @@ public: virtual FileLine* fileline() const override { return nodep()->fileline(); } }; -class TraceTraceVertex : public V3GraphVertex { +class TraceTraceVertex final : public V3GraphVertex { AstTraceDecl* const m_nodep; // TRACEINC this represents // nullptr, or other vertex with the real code() that duplicates this one TraceTraceVertex* m_duplicatep = nullptr; @@ -132,7 +132,7 @@ public: } }; -class TraceVarVertex : public V3GraphVertex { +class TraceVarVertex final : public V3GraphVertex { AstVarScope* m_nodep; public: @@ -150,7 +150,7 @@ public: //###################################################################### // Trace state, as a visitor of each AstNode -class TraceVisitor : public EmitCBaseVisitor { +class TraceVisitor final : public EmitCBaseVisitor { private: // NODE STATE // V3Hashed diff --git a/src/V3Trace.h b/src/V3Trace.h index 07d7fd679..c45922fe6 100644 --- a/src/V3Trace.h +++ b/src/V3Trace.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Trace { +class V3Trace final { public: static void traceAll(AstNetlist* nodep); }; diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index f8669c6bd..ba248b720 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -31,7 +31,7 @@ //###################################################################### // TraceDecl state, as a visitor of each AstNode -class TraceDeclVisitor : public EmitCBaseVisitor { +class TraceDeclVisitor final : public EmitCBaseVisitor { private: // NODE STATE diff --git a/src/V3TraceDecl.h b/src/V3TraceDecl.h index 1327b45df..024d284a7 100644 --- a/src/V3TraceDecl.h +++ b/src/V3TraceDecl.h @@ -25,7 +25,7 @@ //============================================================================ -class V3TraceDecl { +class V3TraceDecl final { public: static void traceDeclAll(AstNetlist* nodep); }; diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 086ecbb30..8988b6258 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -69,7 +69,7 @@ //###################################################################### -class TristateBaseVisitor : public AstNVisitor { +class TristateBaseVisitor VL_NOT_FINAL : public AstNVisitor { public: // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -78,7 +78,7 @@ public: //###################################################################### // Graph support classes -class TristateVertex : public V3GraphVertex { +class TristateVertex final : public V3GraphVertex { AstNode* m_nodep; bool m_isTristate = false; // Logic indicates a tristate bool m_feedsTri = false; // Propagates to a tristate node (on RHS) @@ -110,7 +110,7 @@ public: //###################################################################### -class TristateGraph { +class TristateGraph final { // NODE STATE // AstVar::user5p -> TristateVertex* for variable being built // AstUser5InUse m_inuser5; // In visitor below @@ -271,7 +271,7 @@ public: // Given a node, flip any VarRef from LValue to RValue (i.e. make it an input) // See also V3LinkLValue::linkLValueSet -class TristatePinVisitor : public TristateBaseVisitor { +class TristatePinVisitor final : public TristateBaseVisitor { TristateGraph& m_tgraph; bool m_lvalue; // Flip to be an LVALUE // VISITORS @@ -312,7 +312,7 @@ public: //###################################################################### -class TristateVisitor : public TristateBaseVisitor { +class TristateVisitor final : public TristateBaseVisitor { // NODE STATE // *::user1p -> pointer to output enable __en expressions // *::user2 -> int - already visited, see U2_ enum diff --git a/src/V3Tristate.h b/src/V3Tristate.h index 509a6bd94..5ea6c7d17 100644 --- a/src/V3Tristate.h +++ b/src/V3Tristate.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Tristate { +class V3Tristate final { public: static void tristateAll(AstNetlist* nodep); }; diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 1ff124aee..36077d610 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -37,7 +37,7 @@ //###################################################################### // Class for every variable we may process -class UndrivenVarEntry { +class UndrivenVarEntry final { // MEMBERS AstVar* m_varp; // Variable this tracks std::vector m_wholeFlags; // Used/Driven on whole vector @@ -226,7 +226,7 @@ public: //###################################################################### // Undriven state, as a visitor of each AstNode -class UndrivenVisitor : public AstNVisitor { +class UndrivenVisitor final : public AstNVisitor { private: // NODE STATE // Netlist: diff --git a/src/V3Undriven.h b/src/V3Undriven.h index 4475ab053..2a4e5d18c 100644 --- a/src/V3Undriven.h +++ b/src/V3Undriven.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Undriven { +class V3Undriven final { public: static void undrivenAll(AstNetlist* nodep); }; diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 21e61b019..dbfa9a101 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -41,7 +41,7 @@ //###################################################################### -class UnknownVisitor : public AstNVisitor { +class UnknownVisitor final : public AstNVisitor { private: // NODE STATE // Cleared on Netlist diff --git a/src/V3Unknown.h b/src/V3Unknown.h index db784a95a..2139cf771 100644 --- a/src/V3Unknown.h +++ b/src/V3Unknown.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Unknown { +class V3Unknown final { public: static void unknownAll(AstNetlist* nodep); }; diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 7a0165c15..85b7d4484 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -39,7 +39,7 @@ //###################################################################### // Unroll state, as a visitor of each AstNode -class UnrollVisitor : public AstNVisitor { +class UnrollVisitor final : public AstNVisitor { private: // STATE AstVar* m_forVarp; // Iterator variable diff --git a/src/V3Unroll.h b/src/V3Unroll.h index 39e588c41..61b662f1b 100644 --- a/src/V3Unroll.h +++ b/src/V3Unroll.h @@ -28,7 +28,7 @@ class UnrollVisitor; -class UnrollStateful { +class UnrollStateful final { // MEMBERS UnrollVisitor* m_unrollerp; VL_UNCOPYABLE(UnrollStateful); @@ -44,7 +44,7 @@ public: //============================================================================ -class V3Unroll { +class V3Unroll final { public: static void unrollAll(AstNetlist* nodep); }; diff --git a/src/V3Waiver.h b/src/V3Waiver.h index 67d4d65a0..7c93aa52c 100644 --- a/src/V3Waiver.h +++ b/src/V3Waiver.h @@ -22,7 +22,7 @@ #include #include -class V3Waiver { +class V3Waiver final { // TYPES typedef std::vector WaiverList; static WaiverList s_waiverList; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 17979e595..ed88444a9 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -103,7 +103,7 @@ std::ostream& operator<<(std::ostream& str, const Determ& rhs) { //###################################################################### // Width state, as a visitor of each AstNode -class WidthVP { +class WidthVP final { // Parameters to pass down hierarchy with visit functions. AstNodeDType* m_dtypep; // Parent's data type to resolve to Stage m_stage; // If true, report errors @@ -164,7 +164,7 @@ std::ostream& operator<<(std::ostream& str, const WidthVP* vup) { //###################################################################### -class WidthClearVisitor { +class WidthClearVisitor final { // Rather than a AstNVisitor, can just quickly touch every node void clearWidthRecurse(AstNode* nodep) { for (; nodep; nodep = nodep->nextp()) { @@ -188,7 +188,7 @@ public: //###################################################################### -class WidthVisitor : public AstNVisitor { +class WidthVisitor final : public AstNVisitor { private: // TYPES typedef std::map, AstVar*> TableMap; diff --git a/src/V3Width.h b/src/V3Width.h index 5ba10dc80..03e1fb037 100644 --- a/src/V3Width.h +++ b/src/V3Width.h @@ -25,7 +25,7 @@ //============================================================================ -class V3Width { +class V3Width final { public: static int debug(); static void width(AstNetlist* nodep); diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 047dec26e..2176bc8cd 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -34,7 +34,7 @@ /// Remove all $signed, $unsigned, we're done with them. /// This step is only called on real V3Width, not intermediate e.g. widthParams -class WidthRemoveVisitor : public AstNVisitor { +class WidthRemoveVisitor final : public AstNVisitor { private: // METHODS void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) { @@ -64,7 +64,7 @@ public: // Now that all widthing is complete, // Copy all width() to widthMin(). V3Const expects this -class WidthCommitVisitor : public AstNVisitor { +class WidthCommitVisitor final : public AstNVisitor { // NODE STATE // AstVar::user1p -> bool, processed AstUser1InUse m_inuser1; diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 71d805d20..37f5959ff 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -36,7 +36,7 @@ //###################################################################### // Width state, as a visitor of each AstNode -class WidthSelVisitor : public AstNVisitor { +class WidthSelVisitor final : public AstNVisitor { private: // IMPORTANT //**** This is not a normal visitor, in that all iteration is instead diff --git a/src/VlcBucket.h b/src/VlcBucket.h index 97df0c4b1..be7245e27 100644 --- a/src/VlcBucket.h +++ b/src/VlcBucket.h @@ -25,7 +25,7 @@ // This is a bitmap array - we store a single bit to indicate a test // has hit that point with sufficient coverage. -class VlcBuckets { +class VlcBuckets final { private: // MEMBERS vluint64_t* m_datap = nullptr; ///< Pointer to first bucket (dynamically allocated) diff --git a/src/VlcOptions.h b/src/VlcOptions.h index 0efd39e0f..53940bbb9 100644 --- a/src/VlcOptions.h +++ b/src/VlcOptions.h @@ -31,7 +31,7 @@ typedef std::set VlStringSet; -class VlcOptions { +class VlcOptions final { // MEMBERS (general options) // clang-format off string m_annotateOut; // main switch: --annotate I diff --git a/src/VlcPoint.h b/src/VlcPoint.h index e87c0de0f..36eea2feb 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -29,7 +29,7 @@ //******************************************************************** // VlcPoint - A coverage point (across all tests) -class VlcPoint { +class VlcPoint final { private: // MEMBERS string m_name; //< Name of the point @@ -90,7 +90,7 @@ public: //******************************************************************** // VlcPoints - Container of all points -class VlcPoints { +class VlcPoints final { private: // MEMBERS typedef std::map NameMap; // Sorted by name (ordered) diff --git a/src/VlcSource.h b/src/VlcSource.h index adebdde3a..7874b9de0 100644 --- a/src/VlcSource.h +++ b/src/VlcSource.h @@ -26,7 +26,7 @@ //******************************************************************** // VlcColumnCount - count at specific source file, line and column -class VlcSourceCount { +class VlcSourceCount final { private: // MEMBERS int m_lineno; ///< Line number @@ -57,7 +57,7 @@ public: //******************************************************************** // VlcSource - source file to annotate -class VlcSource { +class VlcSource final { public: // TYPES typedef std::map ColumnMap; // Map of {column} @@ -98,7 +98,7 @@ public: //******************************************************************** // VlcSources - Container of all source files -class VlcSources { +class VlcSources final { public: // TYPES typedef std::map NameMap; diff --git a/src/VlcTest.h b/src/VlcTest.h index 8db9a2059..5cc1c3ae2 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -29,7 +29,7 @@ //******************************************************************** // VlcTest - a single testrun i.e. a file containing coverage data -class VlcTest { +class VlcTest final { private: // MEMBERS string m_name; //< Name of the test @@ -84,7 +84,7 @@ public: //******************************************************************** // VlcTests - Container of all tests -class VlcTests { +class VlcTests final { public: // TYPES typedef std::vector ByName; diff --git a/src/VlcTop.h b/src/VlcTop.h index b00edd110..4284c69ed 100644 --- a/src/VlcTop.h +++ b/src/VlcTop.h @@ -28,7 +28,7 @@ //###################################################################### // VlcTop - Top level options container -class VlcTop { +class VlcTop final { public: // PUBLIC MEMBERS VlcOptions opt; //< Runtime options diff --git a/src/astgen b/src/astgen index f7ff60fcf..60f20a283 100644 --- a/src/astgen +++ b/src/astgen @@ -378,9 +378,9 @@ sub write_header { $line =~ s/^\s*#(define|undef)\s+ASTGEN_.*$//; # Track current node type and base class - if ($line =~ /^\s*class\s*Ast(\S+)\s*:\s*(public)?\s*(AstNode\S*)/) { + if ($line =~ /^\s*class\s*Ast(\S+)\s*(final|VL_NOT_FINAL)?\s*:\s*(public)?\s*(AstNode\S*)/) { $type = $1; - $base = $3; + $base = $4; } # Substitute macros diff --git a/test_regress/t/t_dist_portability.pl b/test_regress/t/t_dist_portability.pl index 5b6a8e037..78c4d6279 100755 --- a/test_regress/t/t_dist_portability.pl +++ b/test_regress/t/t_dist_portability.pl @@ -22,6 +22,7 @@ if (!-r "$root/.git") { printfll(); cstr(); vsnprintf(); + final(); } ok(1); @@ -30,7 +31,7 @@ sub uint { ### Must trim output before and after our file list #my $files = "*/*.c* */*.h test_regress/t/*.c* test_regress/t/*.h"; # src isn't clean, and probably doesn't need to be (yet?) - my $files = "include/*.c* include/*.h test_c/*.c* test_regress/t/*.c* test_regress/t/*.h"; + my $files = "include/*.c* include/*.h examples/*/*.c* test_regress/t/*.c* test_regress/t/*.h"; my $cmd = "cd $root && fgrep -n int $files | sort"; print "C $cmd\n"; my $grep = `$cmd`; @@ -52,7 +53,7 @@ sub uint { } sub printfll { - my $files = "src/*.c* src/*.h include/*.c* include/*.h test_c/*.c* test_regress/t/*.c* test_regress/t/*.h"; + my $files = "src/*.c* src/*.h include/*.c* include/*.h examples/*/*.c* test_regress/t/*.c* test_regress/t/*.h"; my $cmd = "cd $root && fgrep -n ll $files | sort"; print "C $cmd\n"; my $grep = `$cmd`; @@ -73,7 +74,7 @@ sub printfll { } sub cstr { - my $files = "src/*.c* src/*.h include/*.c* include/*.h test_c/*.c* test_regress/t/*.c* test_regress/t/*.h"; + my $files = "src/*.c* src/*.h include/*.c* include/*.h examples/*/*.c* test_regress/t/*.c* test_regress/t/*.h"; my $cmd = "cd $root && grep -n -P 'c_str|begin|end' $files | sort"; print "C $cmd\n"; my $grep = `$cmd`; @@ -92,7 +93,7 @@ sub cstr { sub vsnprintf { # Note do not do test_regress, as VPI files need to compile without verilatedos.h - my $files = "src/*.c* src/*.h include/*.c* include/*.h test_c/*.c*"; + my $files = "src/*.c* src/*.h include/*.c* include/*.h examples/*/*.c*"; my $cmd = "cd $root && grep -n -P '(snprintf|vsnprintf)' $files | sort"; print "C $cmd\n"; my $grep = `$cmd`; @@ -109,4 +110,25 @@ sub vsnprintf { } } +sub final { + # Note do not do test_regress, as VPI files need to compile without verilatedos.h + my $files = "src/*.c* src/*.h include/*.c* include/*.h"; + my $cmd = "cd $root && grep -n -P '(class)' $files | sort"; + print "C $cmd\n"; + my $grep = `$cmd`; + my %names; + foreach my $line (split /\n/, $grep) { + if ($line =~ /:\s*class /) { + next if $line =~ /final|VL_NOT_FINAL/; + next if $line =~ /{}/; # e.g. 'class Foo {};' + next if $line =~ /;/; # e.g. 'class Foo;' + print "$line\n"; + $names{$1} = 1; + } + } + if (keys %names) { + error("Files with classes without final/VL_NOT_FINAL: ",join(' ',sort keys %names)); + } +} + 1; From 5992d678beaff8dea4035822ad6c0af3104cc41f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 18 Nov 2020 22:18:29 -0500 Subject: [PATCH 25/91] Fix clang error, broke last commit. --- src/V3Broken.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index fe3c481c9..7ca71dfff 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -36,7 +36,7 @@ //###################################################################### -class BrokenTable final : public AstNVisitor { +class BrokenTable VL_NOT_FINAL : public AstNVisitor { // Table of brokenExists node pointers private: // MEMBERS From abfee1270f4383b3d526ce1bff700cbcad8459b4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 18 Nov 2020 22:21:48 -0500 Subject: [PATCH 26/91] Improve internal code coverage --- nodist/code_coverage.dat | 1 + src/V3Number.cpp | 10 -------- src/V3Number.h | 1 - test_regress/t/t_debug_emitv.out | 1 + test_regress/t/t_debug_emitv.pl | 2 +- test_regress/t/t_debug_emitv.v | 33 ++++++++++++++++++++++++++ test_regress/t/t_flag_hier1_bad.out | 3 +++ test_regress/t/t_flag_hier1_bad.pl | 25 +++++++++++++++++++ test_regress/t/t_flag_mmd.pl | 20 ++++++++++++++++ test_regress/t/t_flag_mmd.v | 8 +++++++ test_regress/t/t_math_equal.v | 4 ++++ test_regress/t/t_pp_recursedef_bad.out | 2 ++ test_regress/t/t_pp_recursedef_bad.pl | 19 +++++++++++++++ test_regress/t/t_pp_recursedef_bad.v | 13 ++++++++++ 14 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 test_regress/t/t_flag_hier1_bad.out create mode 100755 test_regress/t/t_flag_hier1_bad.pl create mode 100755 test_regress/t/t_flag_mmd.pl create mode 100644 test_regress/t/t_flag_mmd.v create mode 100644 test_regress/t/t_pp_recursedef_bad.out create mode 100755 test_regress/t/t_pp_recursedef_bad.pl create mode 100644 test_regress/t/t_pp_recursedef_bad.v diff --git a/nodist/code_coverage.dat b/nodist/code_coverage.dat index f4aacd760..a3a276afa 100644 --- a/nodist/code_coverage.dat +++ b/nodist/code_coverage.dat @@ -57,6 +57,7 @@ exclude_line_regexp(qr/(\bv3fatalSrc\b # Exclude for branch coverage only exclude_branch_regexp(qr/(\bdebug\(\) |\bassert\( + |\bBROKEN_RTK\( |\bSELF_CHECK)/x); 1; diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 551229f4e..8d4e57307 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -1775,16 +1775,6 @@ V3Number& V3Number::opShiftL(const V3Number& lhs, const V3Number& rhs) { //====================================================================== // Ops - Arithmetic -V3Number& V3Number::opAbsS(const V3Number& lhs) { - // op i, L(lhs) bit return - NUM_ASSERT_OP_ARGS1(lhs); - if (lhs.isFourState()) return setAllBitsX(); - if (lhs.isNegative()) { - return opNegate(lhs); - } else { - return opAssign(lhs); - } -} V3Number& V3Number::opNegate(const V3Number& lhs) { // op i, L(lhs) bit return NUM_ASSERT_OP_ARGS1(lhs); diff --git a/src/V3Number.h b/src/V3Number.h index 4433bae29..7a01876fb 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -348,7 +348,6 @@ public: V3Number& opLogOr(const V3Number& lhs, const V3Number& rhs); V3Number& opLogEq(const V3Number& lhs, const V3Number& rhs); V3Number& opLogIf(const V3Number& lhs, const V3Number& rhs); - V3Number& opAbsS(const V3Number& lhs); V3Number& opNegate(const V3Number& lhs); V3Number& opAdd(const V3Number& lhs, const V3Number& rhs); V3Number& opSub(const V3Number& lhs, const V3Number& rhs); diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out index 72286aad6..3507dee82 100644 --- a/test_regress/t/t_debug_emitv.out +++ b/test_regress/t/t_debug_emitv.out @@ -175,6 +175,7 @@ module Vt_debug_emitv; if ((32'sh5 != t.i)) begin $stop; end + t.sum = $urandom; end /*verilator public_flat_rw @(posedge clk)@(negedge clk) t.pubflat*/ diff --git a/test_regress/t/t_debug_emitv.pl b/test_regress/t/t_debug_emitv.pl index 3532795bc..06a25f291 100755 --- a/test_regress/t/t_debug_emitv.pl +++ b/test_regress/t/t_debug_emitv.pl @@ -13,7 +13,7 @@ scenarios(vlt => 1); lint( # We also have dump-tree turned on, so hit a lot of AstNode*::dump() functions # Likewise XML - v_flags => ["--lint-only --dump-treei 9 --debug-emitv"], + v_flags => ["--lint-only --dump-treei 9 --dump-treei-V3EmitV 9 --debug-emitv"], ); files_identical("$Self->{obj_dir}/$Self->{VM_PREFIX}__preorder.v", $Self->{golden_filename}); diff --git a/test_regress/t/t_debug_emitv.v b/test_regress/t/t_debug_emitv.v index d1ae29ee0..b5c7c5875 100644 --- a/test_regress/t/t_debug_emitv.v +++ b/test_regress/t/t_debug_emitv.v @@ -25,9 +25,13 @@ module t (/*AUTOARG*/ typedef struct { logic signed [2:0] a; } us_t; + typedef union { + logic a; + } union_t; const ps_t ps[3]; us_t us; + union_t unu; int array[3]; initial array = '{1,2,3}; @@ -140,6 +144,9 @@ module t (/*AUTOARG*/ $display("%% [%t] [%t] to=%o td=%d", $time, $realtime, $time, $time); $sscanf("foo=5", "foo=%d", i); if (i != 5) $stop; + + sum = $random; + sum = $urandom; end endmodule @@ -151,4 +158,30 @@ module sub(); if (v == 0) return 33; return {31'd0, v[2]} + 32'd1; endfunction + real r; + initial begin + r = 1.0; + r = $log10(r); + r = $ln(r); + r = $exp(r); + r = $sqrt(r); + r = $floor(r); + r = $ceil(r); + r = $sin(r); + r = $cos(r); + r = $tan(r); + r = $asin(r); + r = $acos(r); + r = $atan(r); + r = $sinh(r); + r = $cosh(r); + r = $tanh(r); + r = $asinh(r); + r = $acosh(r); + r = $atanh(r); + end endmodule + +package p; + logic pkgvar; +endpackage diff --git a/test_regress/t/t_flag_hier1_bad.out b/test_regress/t/t_flag_hier1_bad.out new file mode 100644 index 000000000..90f0cb247 --- /dev/null +++ b/test_regress/t/t_flag_hier1_bad.out @@ -0,0 +1,3 @@ +%Error: --hierarchical must not be set with --hierarchical-child or --hierarchical-block +%Error: --hierarchical-block must be set when --hierarchical-child is set +%Error: Exiting due to diff --git a/test_regress/t/t_flag_hier1_bad.pl b/test_regress/t/t_flag_hier1_bad.pl new file mode 100755 index 000000000..f41278e68 --- /dev/null +++ b/test_regress/t/t_flag_hier1_bad.pl @@ -0,0 +1,25 @@ +#!/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(vlt => 1); +top_filename("t/t_hier_block.v"); + +lint( + fails => 1, + verilator_flags2 => ['--hierarchical', + '--hierarchical-child', + 'modName', + ], + expect_filename => $Self->{golden_filename}, + ); + +ok(1); + +1; diff --git a/test_regress/t/t_flag_mmd.pl b/test_regress/t/t_flag_mmd.pl new file mode 100755 index 000000000..7f2955642 --- /dev/null +++ b/test_regress/t/t_flag_mmd.pl @@ -0,0 +1,20 @@ +#!/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(vlt => 1); + +compile( + verilator_flags2 => ["-MMD -MP"], + ); + +file_grep("$Self->{obj_dir}/Vt_flag_mmd__ver.d", qr!t/t_flag_mmd.v!x); + +ok(1); +1; diff --git a/test_regress/t/t_flag_mmd.v b/test_regress/t/t_flag_mmd.v new file mode 100644 index 000000000..df8679e7d --- /dev/null +++ b/test_regress/t/t_flag_mmd.v @@ -0,0 +1,8 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2016 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; +endmodule diff --git a/test_regress/t/t_math_equal.v b/test_regress/t/t_math_equal.v index 7346c86c4..54968a263 100644 --- a/test_regress/t/t_math_equal.v +++ b/test_regress/t/t_math_equal.v @@ -45,13 +45,17 @@ module t (/*AUTOARG*/ // if (5'd10 != 5'b1010) $stop; if (5'd10 != 5'd10) $stop; + if (5'd10 != 5'd1_0) $stop; if (5'd10 != 5'ha) $stop; if (5'd10 != 5'o12) $stop; + if (5'd10 != 5'o1_2) $stop; if (5'd10 != 5'B 1010) $stop; + if (5'd10 != 5'B 10_10) $stop; if (5'd10 != 5'D10) $stop; if (5'd10 != 5'H a) $stop; if (5'd10 != 5 'O 12) $stop; if (24'h29cbb8 != 24'o12345670) $stop; + if (24'h29__cbb8 != 24'o123456__70) $stop; if (6'b111xxx !== 6'o7x) $stop; if (6'b111??? !== 6'o7?) $stop; if (6'b111zzz !== 6'o7z) $stop; diff --git a/test_regress/t/t_pp_recursedef_bad.out b/test_regress/t/t_pp_recursedef_bad.out new file mode 100644 index 000000000..06f2e03e9 --- /dev/null +++ b/test_regress/t/t_pp_recursedef_bad.out @@ -0,0 +1,2 @@ +%Error: t/t_pp_recursedef_bad.v:9:8012: Recursive `define substitution: `RECURSE +%Error: Exiting due to diff --git a/test_regress/t/t_pp_recursedef_bad.pl b/test_regress/t/t_pp_recursedef_bad.pl new file mode 100755 index 000000000..a5846c699 --- /dev/null +++ b/test_regress/t/t_pp_recursedef_bad.pl @@ -0,0 +1,19 @@ +#!/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(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_pp_recursedef_bad.v b/test_regress/t/t_pp_recursedef_bad.v new file mode 100644 index 000000000..00a2aa78c --- /dev/null +++ b/test_regress/t/t_pp_recursedef_bad.v @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; +`define RECURSE `RECURSE + `RECURSE + + initial $stop; // Should have failed + +endmodule From 0102efd4eaede5e4baa490a17c63a7b94cdaa7ee Mon Sep 17 00:00:00 2001 From: Yutetsu TAKATSUKASA Date: Thu, 19 Nov 2020 22:02:58 +0900 Subject: [PATCH 27/91] Support unpacked array in DPI-C (#2648) * Add tests for unpacked array in DPI-C * Add more generic parameter generator to AstNodes * Supports multi dimensional array in DPI ( DPI argmuments <=> Verilator internal type conversion) consider typedef in V3Task fix export test fix inout for scalar support export func of time * V3Premit does not show an error for wide words nor ArraySel * Unnecessary pack func for unapcked array does not appear anymore * Support unpacked array in runtime header - Add an overload for lvalue VL_CVT_PACK_STR_NN - Allow conversion from void * * touch up tests for codacy advices * resolve free functions. no functional change intended. --- src/V3AstNodes.cpp | 135 +- src/V3AstNodes.h | 3 + src/V3Premit.cpp | 4 +- src/V3ProtectLib.cpp | 7 +- src/V3Task.cpp | 161 ++- src/V3Task.h | 3 +- src/V3Width.cpp | 42 + test_regress/t/t_dpi_arg_inout_unpack.cpp | 860 ++++++++++++ test_regress/t/t_dpi_arg_inout_unpack.pl | 44 + test_regress/t/t_dpi_arg_inout_unpack.v | 1162 +++++++++++++++++ .../t/t_dpi_arg_inout_unpack__Dpi.out | 313 +++++ test_regress/t/t_dpi_arg_input_unpack.cpp | 778 +++++++++++ test_regress/t/t_dpi_arg_input_unpack.pl | 44 + test_regress/t/t_dpi_arg_input_unpack.v | 770 +++++++++++ .../t/t_dpi_arg_input_unpack__Dpi.out | 313 +++++ test_regress/t/t_dpi_arg_output_unpack.cpp | 655 ++++++++++ test_regress/t/t_dpi_arg_output_unpack.pl | 44 + test_regress/t/t_dpi_arg_output_unpack.v | 761 +++++++++++ .../t/t_dpi_arg_output_unpack__Dpi.out | 313 +++++ test_regress/t/t_dpi_unpack_bad.out | 30 + test_regress/t/t_dpi_unpack_bad.pl | 19 + test_regress/t/t_dpi_unpack_bad.v | 31 + 22 files changed, 6421 insertions(+), 71 deletions(-) create mode 100644 test_regress/t/t_dpi_arg_inout_unpack.cpp create mode 100755 test_regress/t/t_dpi_arg_inout_unpack.pl create mode 100644 test_regress/t/t_dpi_arg_inout_unpack.v create mode 100644 test_regress/t/t_dpi_arg_inout_unpack__Dpi.out create mode 100644 test_regress/t/t_dpi_arg_input_unpack.cpp create mode 100755 test_regress/t/t_dpi_arg_input_unpack.pl create mode 100644 test_regress/t/t_dpi_arg_input_unpack.v create mode 100644 test_regress/t/t_dpi_arg_input_unpack__Dpi.out create mode 100644 test_regress/t/t_dpi_arg_output_unpack.cpp create mode 100755 test_regress/t/t_dpi_arg_output_unpack.pl create mode 100644 test_regress/t/t_dpi_arg_output_unpack.v create mode 100644 test_regress/t/t_dpi_arg_output_unpack__Dpi.out create mode 100644 test_regress/t/t_dpi_unpack_bad.out create mode 100755 test_regress/t/t_dpi_unpack_bad.pl create mode 100644 test_regress/t/t_dpi_unpack_bad.v diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 3f5dfb2d9..11bc1dd17 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -455,38 +455,99 @@ string AstVar::cPubArgType(bool named, bool forReturn) const { return arg; } -string AstVar::dpiArgType(bool named, bool forReturn) const { - if (forReturn) named = false; - string arg; - if (isDpiOpenArray()) { - arg = "const svOpenArrayHandle"; - } else if (!basicp()) { - arg = "UNKNOWN"; - } else if (basicp()->isDpiBitVec()) { - if (forReturn) { - arg = "svBitVecVal"; - } else if (isReadOnly()) { - arg = "const svBitVecVal*"; - } else { - arg = "svBitVecVal*"; - } - } else if (basicp()->isDpiLogicVec()) { - if (forReturn) { - arg = "svLogicVecVal"; - } else if (isReadOnly()) { - arg = "const svLogicVecVal*"; - } else { - arg = "svLogicVecVal*"; - } - } else { - arg = basicp()->keyword().dpiType(); - if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) { - arg = "unsigned " + arg; - } - if (!forReturn && isWritable()) arg += "*"; +class dpiTypesToStringConverter { +public: + virtual string openArray(const AstVar*) const { return "const svOpenArrayHandle"; } + virtual string bitLogicVector(const AstVar* varp, bool isBit) const { + return isBit ? "svBitVecVal" : "svLogicVecVal"; } - if (named) arg += " " + name(); - return arg; + virtual string primitive(const AstVar* varp) const { + string type; + if (varp->basicp()->keyword().isDpiUnsignable() && !varp->basicp()->isSigned()) { + type = "unsigned "; + } + type += varp->basicp()->keyword().dpiType(); + return type; + } + string convert(const AstVar* varp) const { + if (varp->isDpiOpenArray()) { + return openArray(varp); + } else if (!varp->basicp()) { + return "UNKNOWN"; + } else if (varp->basicp()->isDpiBitVec() || varp->basicp()->isDpiLogicVec()) { + return bitLogicVector(varp, varp->basicp()->isDpiBitVec()); + } else { + return primitive(varp); + } + } +}; + +string AstVar::dpiArgType(bool named, bool forReturn) const { + if (forReturn) { + return dpiTypesToStringConverter{}.convert(this); + } else { + class converter : public dpiTypesToStringConverter { + virtual string bitLogicVector(const AstVar* varp, bool isBit) const override { + return string(varp->isReadOnly() ? "const " : "") + + dpiTypesToStringConverter::bitLogicVector(varp, isBit) + '*'; + } + virtual string primitive(const AstVar* varp) const override { + string type = dpiTypesToStringConverter::primitive(varp); + if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) { + if (!varp->isWritable() + && varp->basicp()->keyword() != AstBasicDTypeKwd::STRING) + type = "const " + type; + type += "*"; + } + return type; + } + }; + string arg = converter{}.convert(this); + if (named) arg += " " + name(); + return arg; + } +} + +string AstVar::dpiTmpVarType(const string& varName) const { + class converter : public dpiTypesToStringConverter { + string m_name; + string arraySuffix(const AstVar* varp, size_t n) const { + if (AstUnpackArrayDType* unpackp + = VN_CAST(varp->dtypep()->skipRefp(), UnpackArrayDType)) { + // Convert multi dimensional unpacked array to 1D array + if (n == 0) n = 1; + n *= unpackp->arrayUnpackedElements(); + return '[' + cvtToStr(n) + ']'; + } else if (n > 0) { + return '[' + cvtToStr(n) + ']'; + } else { + return ""; + } + } + virtual string openArray(const AstVar* varp) const override { + return dpiTypesToStringConverter::openArray(varp) + ' ' + m_name + + arraySuffix(varp, 0); + } + virtual string bitLogicVector(const AstVar* varp, bool isBit) const override { + string type = dpiTypesToStringConverter::bitLogicVector(varp, isBit); + type += ' ' + m_name + arraySuffix(varp, varp->widthWords()); + return type; + } + virtual string primitive(const AstVar* varp) const override { + string type = dpiTypesToStringConverter::primitive(varp); + if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) { + if (!varp->isWritable() && varp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE) + type = "const " + type; + } + type += ' ' + m_name + arraySuffix(varp, 0); + return type; + } + + public: + explicit converter(const string& name) + : m_name(name) {} + }; + return converter{varName}.convert(this); } string AstVar::scType() const { @@ -1347,6 +1408,18 @@ string AstUnpackArrayDType::prettyDTypeName() const { os << subp->prettyDTypeName() << "$" << ranges; return os.str(); } +std::vector AstUnpackArrayDType::unpackDimensions() { + std::vector dims; + for (AstUnpackArrayDType* unpackp = this; unpackp;) { + dims.push_back(unpackp); + if (AstNodeDType* subp = unpackp->subDTypep()) { + unpackp = VN_CAST(subp, UnpackArrayDType); + } else { + unpackp = nullptr; + } + } + return dims; +} void AstNetlist::dump(std::ostream& str) const { this->AstNode::dump(str); str << " [" << timeunit() << "/" << timeprecision() << "]"; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index c70763cc9..d38a39675 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -721,6 +721,8 @@ public: } ASTNODE_NODE_FUNCS(UnpackArrayDType) virtual string prettyDTypeName() const override; + // Outer dimension comes first. The first element is this node. + std::vector unpackDimensions(); }; class AstUnsizedArrayDType final : public AstNodeDType { @@ -2026,6 +2028,7 @@ public: // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc. string cPubArgType(bool named, bool forReturn) const; string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument + string dpiTmpVarType(const string& varName) const; // Return Verilator internal type for argument: CData, SData, IData, WData string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc = "") const; string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 5865a902f..ac5582b4c 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -127,7 +127,9 @@ private: } else if (VN_IS(nodep->backp(), Sel) && VN_CAST(nodep->backp(), Sel)->widthp() == nodep) { // AstSel::width must remain a constant - } else if (nodep->firstAbovep() && VN_IS(nodep->firstAbovep(), ArraySel)) { + } else if ((nodep->firstAbovep() && VN_IS(nodep->firstAbovep(), ArraySel)) + || ((VN_IS(m_stmtp, CCall) || VN_IS(m_stmtp, CStmt)) + && VN_IS(nodep, ArraySel))) { // ArraySel's are pointer refs, ignore } else { UINFO(4, "Cre Temp: " << nodep << endl); diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index 599699b5a..188a5e8f3 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -411,11 +411,12 @@ private: string cInputConnection(AstVar* varp) { string frstmt; - bool useSetWSvlv = V3Task::dpiToInternalFrStmt(varp, varp->name(), frstmt); + string ket; + bool useSetWSvlv = V3Task::dpiToInternalFrStmt(varp, varp->name(), frstmt, ket); if (useSetWSvlv) { - return frstmt + " handlep__V->" + varp->name() + ", " + varp->name() + ");\n"; + return frstmt + ket + " handlep__V->" + varp->name() + ", " + varp->name() + ");\n"; } - return "handlep__V->" + varp->name() + " = " + frstmt + ";\n"; + return "handlep__V->" + varp->name() + " = " + frstmt + ket + ";\n"; } void handleClock(AstVar* varp) { diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 90f776cf3..11829195d 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -641,11 +641,7 @@ private: } AstNode* createDpiTemp(AstVar* portp, const string& suffix) { - string stmt = portp->dpiArgType(false, true) + " " + portp->name() + suffix; - if (!portp->basicp()->isDpiPrimitive()) { - stmt += "[" + cvtToStr(portp->widthWords()) + "]"; - } - stmt += ";\n"; + const string stmt = portp->dpiTmpVarType(portp->name() + suffix) + ";\n"; return new AstCStmt(portp->fileline(), stmt); } @@ -655,30 +651,80 @@ private: return new AstCStmt(portp->fileline(), stmt); } + static std::vector> unpackDimsAndStrides(AstVar* varp) { + std::vector> dimStrides; + if (AstUnpackArrayDType* dtypep = VN_CAST(varp->dtypep()->skipRefp(), UnpackArrayDType)) { + const std::vector dims = dtypep->unpackDimensions(); + dimStrides.resize(dims.size(), {nullptr, 0}); + dimStrides.back() = {dims.back(), 1}; + for (ssize_t i = dims.size() - 2; i >= 0; --i) { + dimStrides[i].first = dims[i]; + dimStrides[i].second = dimStrides[i + 1].second * dims[i + 1]->elementsConst(); + } + } + return dimStrides; + } + AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName) { // Create assignment from DPI temporary into internal format + // DPI temporary is scalar or 1D array (if unpacked array) + // Internal representation is scalar, 1D, or multi-dimensional array (similar to SV) AstVar* portp = portvscp->varp(); string frstmt; - bool useSetWSvlv = V3Task::dpiToInternalFrStmt(portp, frName, frstmt); - if (useSetWSvlv) { - AstNode* linesp = new AstText(portp->fileline(), frstmt); - linesp->addNext(new AstVarRef(portp->fileline(), portvscp, VAccess::WRITE)); - linesp->addNext(new AstText(portp->fileline(), "," + frName + ");")); - return new AstCStmt(portp->fileline(), linesp); - } + string ket; + const bool useSetWSvlv = V3Task::dpiToInternalFrStmt(portp, frName, frstmt, ket); // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. int cwidth = VL_IDATASIZE; - if (portp->basicp()) { + if (!useSetWSvlv && portp->basicp()) { if (portp->basicp()->keyword().isBitLogic()) { cwidth = VL_EDATASIZE * portp->widthWords(); } else { cwidth = portp->basicp()->keyword().width(); } } - AstNode* newp = new AstAssign( - portp->fileline(), new AstVarRef(portp->fileline(), portvscp, VAccess::WRITE), - new AstSel(portp->fileline(), new AstCMath(portp->fileline(), frstmt, cwidth, false), - 0, portp->width())); + + const std::vector> dimStrides + = unpackDimsAndStrides(portvscp->varp()); + const int total = dimStrides.empty() ? 1 + : dimStrides.front().first->elementsConst() + * dimStrides.front().second; + AstNode* newp = nullptr; + const int widthWords = portvscp->varp()->basicp()->widthWords(); + for (int i = 0; i < total; ++i) { + AstNode* srcp = new AstVarRef(portvscp->fileline(), portvscp, VAccess::WRITE); + // extract a scalar from multi-dimensional array (internal format) + for (auto&& dimStride : dimStrides) { + const size_t dimIdx = (i / dimStride.second) % dimStride.first->elementsConst(); + srcp = new AstArraySel(portvscp->fileline(), srcp, dimIdx); + } + AstNode* stmtp = nullptr; + // extract a scalar from DPI temporary var that is scalar or 1D array + if (useSetWSvlv) { + AstNode* linesp = new AstText(portvscp->fileline(), frstmt + ket); + linesp->addNext(srcp); + linesp->addNext( + new AstText(portvscp->fileline(), + "," + frName + " + " + cvtToStr(i * widthWords) + ");\n")); + stmtp = new AstCStmt(portvscp->fileline(), linesp); + } else { + string from = frstmt; + if (!dimStrides.empty()) { + // e.g. time is 64bit svLogicVector + const int coef = portvscp->varp()->basicp()->isDpiLogicVec() ? widthWords : 1; + from += "[" + cvtToStr(i * coef) + "]"; + } + from += ket; + AstNode* rhsp = new AstSel(portp->fileline(), + new AstCMath(portp->fileline(), from, cwidth, false), 0, + portp->width()); + stmtp = new AstAssign(portp->fileline(), srcp, rhsp); + } + if (i > 0) { + newp->addNext(stmtp); + } else { + newp = stmtp; + } + } return newp; } @@ -749,7 +795,10 @@ private: if (portp->isNonOutput()) { std::string frName - = portp->isInoutish() && portp->basicp()->isDpiPrimitive() ? "*" : ""; + = portp->isInoutish() && portp->basicp()->isDpiPrimitive() + && portp->dtypep()->skipRefp()->arrayUnpackedElements() == 1 + ? "*" + : ""; frName += portp->name(); dpip->addStmtsp(createAssignDpiToInternal(outvscp, frName)); } @@ -913,7 +962,7 @@ private: args += "&" + name; } else { if (portp->isWritable() && portp->basicp()->isDpiPrimitive()) { - args += "&"; + if (!VN_IS(portp->dtypep()->skipRefp(), UnpackArrayDType)) args += "&"; } args += portp->name() + tmpSuffixp; @@ -1532,37 +1581,76 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) string V3Task::assignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, const string& toSuffix, const string& frPrefix) { // Create assignment from internal format into DPI temporary + // Internal representation is scalar, 1D, or multi-dimensional array (similar to SV) + // DPI temporary is scalar or 1D array (if unpacked array) string stmt; string ket; // Someday we'll have better type support, and this can make variables and casts. // But for now, we'll just text-bash it. string frName = frPrefix + portp->name() + frSuffix; string toName = portp->name() + toSuffix; - if (portp->basicp()->isDpiBitVec()) { - stmt += ("VL_SET_SVBV_" + string(portp->dtypep()->charIQWN()) + "(" - + cvtToStr(portp->width()) + ", " + toName + ", " + frName + ")"); - } else if (portp->basicp()->isDpiLogicVec()) { - stmt += ("VL_SET_SVLV_" + string(portp->dtypep()->charIQWN()) + "(" - + cvtToStr(portp->width()) + ", " + toName + ", " + frName + ")"); + size_t unpackSize = 1; // non-unpacked array is treated as size 1 + int unpackDim = 0; + if (AstUnpackArrayDType* unpackp = VN_CAST(portp->dtypep()->skipRefp(), UnpackArrayDType)) { + unpackSize = unpackp->arrayUnpackedElements(); + unpackDim = unpackp->dimensions(false).second; + if (unpackDim > 0) UASSERT_OBJ(unpackSize > 0, portp, "size must be greater than 0"); + } + if (portp->basicp()->isDpiBitVec() || portp->basicp()->isDpiLogicVec()) { + const bool isBit = portp->basicp()->isDpiBitVec(); + const string idx = portp->name() + "__Vidx"; + stmt = "for (size_t " + idx + " = 0; " + idx + " < " + cvtToStr(unpackSize) + "; ++" + idx + + ") "; + stmt += (isBit ? "VL_SET_SVBV_" : "VL_SET_SVLV_") + + string(portp->dtypep()->skipRefp()->charIQWN()) + "(" + cvtToStr(portp->width()) + + ", "; + stmt += toName + " + " + cvtToStr(portp->dtypep()->skipRefp()->widthWords()) + " * " + idx + + ", "; + if (unpackDim > 0) { // Access multi-dimensional array as a 1D array + stmt += "(&" + frName; + for (int i = 0; i < unpackDim; ++i) stmt += "[0]"; + stmt += ")[" + idx + "])"; + } else { + stmt += frName + ")"; + } } else { - if (isPtr) stmt += "*"; // DPI outputs are pointers - stmt += toName + " = "; - if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE) { + const bool isChandle + = portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE; + const bool isString + = portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::STRING; + const string idx = portp->name() + "__Vidx"; + stmt = "for (size_t " + idx + " = 0; " + idx + " < " + cvtToStr(unpackSize) + "; ++" + idx + + ") "; + if (unpackDim > 0) { + stmt += toName + "[" + idx + "]"; + } else { + if (isPtr) stmt += "*"; // DPI outputs are pointers + stmt += toName; + } + stmt += " = "; + if (isChandle) { stmt += "VL_CVT_Q_VP("; ket += ")"; } - stmt += frName; - if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::STRING) { - stmt += ".c_str()"; + if (unpackDim > 0) { + stmt += "(&" + frName; + for (int i = 0; i < unpackDim; ++i) stmt += "[0]"; + stmt += ")[" + idx + "]"; + } else { + stmt += frName; } + if (isString) stmt += ".c_str()"; } stmt += ket + ";\n"; return stmt; } -bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt) { +bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt, + string& ket) { + ket.clear(); if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE) { - frstmt = "VL_CVT_VP_Q(" + frName + ")"; + frstmt = "VL_CVT_VP_Q(" + frName; + ket = ")"; } else if ((portp->basicp() && portp->basicp()->isDpiPrimitive())) { frstmt = frName; } else { @@ -1572,8 +1660,11 @@ bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& fr frstmt = "VL_SET_W_" + frSvType + "(" + cvtToStr(portp->width()) + ","; return true; } else { - frstmt = "VL_SET_" + string(portp->dtypep()->charIQWN()) + "_" + frSvType + "(" - + frName + ")"; + const AstNodeDType* dtypep = portp->dtypep()->skipRefp(); + frstmt = "VL_SET_" + string(dtypep->charIQWN()) + "_" + frSvType + "("; + if (VN_IS(dtypep, UnpackArrayDType)) frstmt += "&"; + frstmt += frName; + ket = ")"; } } return false; diff --git a/src/V3Task.h b/src/V3Task.h index 9c162dccc..78d7b0dde 100644 --- a/src/V3Task.h +++ b/src/V3Task.h @@ -39,7 +39,8 @@ public: static V3TaskConnects taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp); static string assignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, const string& toSuffix, const string& frPrefix = ""); - static bool dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt); + static bool dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt, + string& ket); static const char* dpiTemporaryVarSuffix(); }; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index ed88444a9..556a0cc9c 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -4238,6 +4238,46 @@ private: nodep->dtypeFrom(nodep->taskp()); // if (debug()) nodep->dumpTree(cout, " FuncOut: "); } + // Returns true if dtypep0 and dtypep1 have same dimensions + static bool areSameSize(AstUnpackArrayDType* dtypep0, AstUnpackArrayDType* dtypep1) { + const std::vector dims0 = dtypep0->unpackDimensions(); + const std::vector dims1 = dtypep1->unpackDimensions(); + if (dims0.size() != dims1.size()) return false; + for (size_t i = 0; i < dims0.size(); ++i) { + if (dims0[i]->elementsConst() != dims1[i]->elementsConst()) return false; + } + return true; + } + // Makes sure that port and pin have same size and same datatype + void checkUnpackedArrayArgs(AstVar* portp, AstNode* pinp) { + if (AstUnpackArrayDType* portDtypep + = VN_CAST(portp->dtypep()->skipRefp(), UnpackArrayDType)) { + if (AstUnpackArrayDType* pinDtypep + = VN_CAST(pinp->dtypep()->skipRefp(), UnpackArrayDType)) { + if (!areSameSize(portDtypep, pinDtypep)) { + pinp->v3warn(E_UNSUPPORTED, + "Shape of the argument does not match the shape of the parameter " + << "(" << pinDtypep->prettyDTypeNameQ() << " v.s. " + << portDtypep->prettyDTypeNameQ() << ")"); + } + if (portDtypep->basicp()->width() != pinDtypep->basicp()->width() + || (portDtypep->basicp()->keyword() != pinDtypep->basicp()->keyword() + && !(portDtypep->basicp()->keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT + && pinDtypep->basicp()->keyword() == AstBasicDTypeKwd::LOGIC) + && !(portDtypep->basicp()->keyword() == AstBasicDTypeKwd::LOGIC + && pinDtypep->basicp()->keyword() + == AstBasicDTypeKwd::LOGIC_IMPLICIT))) { + pinp->v3warn(E_UNSUPPORTED, + "Shape of the argument does not match the shape of the parameter " + << "(" << pinDtypep->basicp()->prettyDTypeNameQ() << " v.s. " + << portDtypep->basicp()->prettyDTypeNameQ() << ")"); + } + } else { + pinp->v3warn(E_UNSUPPORTED, "Argument is not an unpacked array while parameter " + << portp->prettyNameQ() << " is"); + } + } + } void processFTaskRefArgs(AstNodeFTaskRef* nodep) { // For arguments, is assignment-like context; see IEEE rules in AstNodeAssign // Function hasn't been widthed, so make it so. @@ -4288,6 +4328,7 @@ private: else if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::STRING && !VN_IS(pinp, CvtPackString) && !VN_IS(pinp, SFormatF) // Already generates a string + && !VN_IS(portp->dtypep(), UnpackArrayDType) // Unpacked array must match && !(VN_IS(pinp, VarRef) && VN_CAST(pinp, VarRef)->varp()->basicp()->keyword() == AstBasicDTypeKwd::STRING)) { @@ -4311,6 +4352,7 @@ private: AstNode* pinp = argp->exprp(); if (!pinp) continue; // Argument error we'll find later // Change data types based on above accept completion + if (nodep->taskp()->dpiImport()) checkUnpackedArrayArgs(portp, pinp); if (portp->isDouble()) VL_DO_DANGLING(spliceCvtD(pinp), pinp); } } diff --git a/test_regress/t/t_dpi_arg_inout_unpack.cpp b/test_regress/t/t_dpi_arg_inout_unpack.cpp new file mode 100644 index 000000000..9b029bfbd --- /dev/null +++ b/test_regress/t/t_dpi_arg_inout_unpack.cpp @@ -0,0 +1,860 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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 +// +//************************************************************************* + +#include +#include +#include +#include +#include + +// clang-format off +#if defined(NCSC) +// Used by NC's svdpi.h to pick up svLogicVecVal with _.aval and _.bval fields, +// rather than the IEEE 1800-2005 version which has _.a and _.b fields. +# define DPI_COMPATIBILITY_VERSION_1800v2012 +#endif + +#include "svdpi.h" + +#if defined(VERILATOR) // Verilator +# include "Vt_dpi_arg_inout_unpack__Dpi.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +# define NO_SHORTREAL +# define NO_UNPACK_STRUCT +# define CONSTARG const +#elif defined(VCS) // VCS +# include "../vc_hdrs.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +# define NO_TIME +# define CONSTARG const +#elif defined(NCSC) // NC +# include "dpi-exp.h" +# include "dpi-imp.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +# define NO_TIME +# define NO_INTEGER +# define NO_SHORTREAL +// Sadly NC does not declare pass-by reference input arguments as const +# define CONSTARG +#elif defined(MS) // ModelSim +# include "dpi.h" +typedef int64_t sv_longint_t; +typedef uint64_t sv_longint_unsigned_t; +# define CONSTARG const +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +//====================================================================== +// Implementations of imported functions +//====================================================================== + +namespace { // unnamed namespace + +const bool VERBOSE_MESSAGE = false; + +#define stop() \ + do { \ + printf(__FILE__ ":%d Bad value\n", __LINE__); \ + abort(); \ + } while (0) + +void set_uint(svLogicVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + if (i < 64) + svPutBitselLogic(v0, i, (val >> i) & 1); + else + svPutBitselLogic(v0, i, 0); + } +} + +void set_uint(svBitVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + if (i < 64) + svPutBitselBit(v0, i, (val >> i) & 1); + else + svPutBitselBit(v0, i, 0); + } +} + +template bool compare(const T& act, const T& exp) { + if (exp == act) { + if (VERBOSE_MESSAGE) { std::cout << "OK Exp:" << exp << " actual:" << act << std::endl; } + return true; + } else { + std::cout << "NG Exp:" << exp << " actual:" << act << std::endl; + return false; + } +} + +bool compare(const svLogicVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + const bool act_bit = svGetBitselLogic(v0, i); + const bool exp_bit = (i < 64) ? ((val >> i) & 1) : false; + if (act_bit != exp_bit) { + std::cout << "Mismatch at bit:" << i << " exp:" << exp_bit << " act:" << act_bit; + return false; + } + } + if (VERBOSE_MESSAGE) { + std::cout << "OK " << val << " as expected (width:" << bitwidth << ")" << std::endl; + } + return true; +} + +bool compare(const svBitVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + const bool act_bit = svGetBitselBit(v0, i); + const bool exp_bit = (i < 64) ? ((val >> i) & 1) : false; + if (act_bit != exp_bit) { + std::cout << "Mismatch at bit:" << i << " exp:" << exp_bit << " act:" << act_bit; + return false; + } + } + if (VERBOSE_MESSAGE) { + std::cout << "OK " << val << " as expected (width:" << bitwidth << ")" << std::endl; + } + return true; +} + +template bool update_0d(T* v) { + if (!compare(*v, 42)) return false; + ++(*v); + return true; +} + +template bool update_1d(T* v) { + if (!compare(v[0], 43)) return false; + if (!compare(v[1], 44)) return false; + ++v[0]; + ++v[1]; + return true; +} + +template bool update_2d(T* v) { + if (!compare(v[0 * 2 + 1], 45)) return false; + if (!compare(v[1 * 2 + 1], 46)) return false; + if (!compare(v[2 * 2 + 1], 47)) return false; + ++v[0 * 2 + 1]; + ++v[1 * 2 + 1]; + ++v[2 * 2 + 1]; + return true; +} + +template bool update_3d(T* v) { + if (!compare(v[(0 * 3 + 0) * 2 + 0], 48)) return false; + if (!compare(v[(1 * 3 + 0) * 2 + 0], 49)) return false; + if (!compare(v[(2 * 3 + 0) * 2 + 0], 50)) return false; + if (!compare(v[(3 * 3 + 0) * 2 + 0], 51)) return false; + ++v[(0 * 3 + 0) * 2 + 0]; + ++v[(1 * 3 + 0) * 2 + 0]; + ++v[(2 * 3 + 0) * 2 + 0]; + ++v[(3 * 3 + 0) * 2 + 0]; + return true; +} + +template bool update_0d(T* v, int bitwidth) { + if (!compare(v, 42, bitwidth)) return false; + set_uint(v, 43, bitwidth); + return true; +} +template bool update_1d(T* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + if (!compare(v + unit * 0, 43, bitwidth)) return false; + if (!compare(v + unit * 1, 44, bitwidth)) return false; + set_uint(v + unit * 0, 44, bitwidth); + set_uint(v + unit * 1, 45, bitwidth); + return true; +} +template bool update_2d(T* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + if (!compare(v + unit * (0 * 2 + 1), 45, bitwidth)) return false; + if (!compare(v + unit * (1 * 2 + 1), 46, bitwidth)) return false; + if (!compare(v + unit * (2 * 2 + 1), 47, bitwidth)) return false; + set_uint(v + unit * (0 * 2 + 1), 46, bitwidth); + set_uint(v + unit * (1 * 2 + 1), 47, bitwidth); + set_uint(v + unit * (2 * 2 + 1), 48, bitwidth); + return true; +} +template bool update_3d(T* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + if (!compare(v + unit * ((0 * 3 + 0) * 2 + 0), 48, bitwidth)) return false; + if (!compare(v + unit * ((1 * 3 + 0) * 2 + 0), 49, bitwidth)) return false; + if (!compare(v + unit * ((2 * 3 + 0) * 2 + 0), 50, bitwidth)) return false; + if (!compare(v + unit * ((3 * 3 + 0) * 2 + 0), 51, bitwidth)) return false; + set_uint(v + unit * ((0 * 3 + 0) * 2 + 0), 49, bitwidth); + set_uint(v + unit * ((1 * 3 + 0) * 2 + 0), 50, bitwidth); + set_uint(v + unit * ((2 * 3 + 0) * 2 + 0), 51, bitwidth); + set_uint(v + unit * ((3 * 3 + 0) * 2 + 0), 52, bitwidth); + return true; +} + +template void set_values(T (&v)[4][3][2]) { + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) v[i][j][k] = 0; + v[3][2][1] = 42; + v[2][1][0] = 43; + v[2][1][1] = 44; + v[1][0][1] = 45; + v[1][1][1] = 46; + v[1][2][1] = 47; + v[0][0][0] = 48; + v[1][0][0] = 49; + v[2][0][0] = 50; + v[3][0][0] = 51; +} + +template void set_values(T (&v)[4][3][2][N], int bitwidth) { + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) set_uint(v[i][j][k], 0, bitwidth); + set_uint(v[3][2][1], 42, bitwidth); + set_uint(v[2][1][0], 43, bitwidth); + set_uint(v[2][1][1], 44, bitwidth); + set_uint(v[1][0][1], 45, bitwidth); + set_uint(v[1][1][1], 46, bitwidth); + set_uint(v[1][2][1], 47, bitwidth); + set_uint(v[0][0][0], 48, bitwidth); + set_uint(v[1][0][0], 49, bitwidth); + set_uint(v[2][0][0], 50, bitwidth); + set_uint(v[3][0][0], 51, bitwidth); +} + +template bool check_0d(T v) { return compare(v, 43); } +template bool check_1d(const T (&v)[2]) { + return compare(v[0], 44) && compare(v[1], 45); +} +template bool check_2d(const T (&v)[3][2]) { + return compare(v[0][1], 46) && compare(v[1][1], 47) && compare(v[2][1], 48); +} +template bool check_3d(const T (&v)[4][3][2]) { + return compare(v[0][0][0], 49) && compare(v[1][0][0], 50) && compare(v[2][0][0], 51) + && compare(v[3][0][0], 52); +} + +template bool check_0d(const T (&v)[N], unsigned int bitwidth) { + return compare(v, 43, bitwidth); +} +template bool check_1d(const T (&v)[2][N], unsigned int bitwidth) { + return compare(v[0], 44, bitwidth) && compare(v[1], 45, bitwidth); +} +template bool check_2d(const T (&v)[3][2][N], unsigned int bitwidth) { + return compare(v[0][1], 46, bitwidth) && compare(v[1][1], 47, bitwidth) + && compare(v[2][1], 48, bitwidth); +} +template bool check_3d(const T (&v)[4][3][2][N], unsigned int bitwidth) { + return compare(v[0][0][0], 49, bitwidth) && compare(v[1][0][0], 50, bitwidth) + && compare(v[2][0][0], 51, bitwidth) && compare(v[3][0][0], 52, bitwidth); +} + +} // unnamed namespace + +void* get_non_null() { + static int v; + return &v; +} + +void i_byte_0d(char* v) { + if (!update_0d(v)) stop(); +} +void i_byte_1d(char* v) { + if (!update_1d(v)) stop(); +} +void i_byte_2d(char* v) { + if (!update_2d(v)) stop(); +} +void i_byte_3d(char* v) { + if (!update_3d(v)) stop(); +} + +void i_byte_unsigned_0d(unsigned char* v) { + if (!update_0d(v)) stop(); +} +void i_byte_unsigned_1d(unsigned char* v) { + if (!update_1d(v)) stop(); +} +void i_byte_unsigned_2d(unsigned char* v) { + if (!update_2d(v)) stop(); +} +void i_byte_unsigned_3d(unsigned char* v) { + if (!update_3d(v)) stop(); +} + +void i_shortint_0d(short* v) { + if (!update_0d(v)) stop(); +} +void i_shortint_1d(short* v) { + if (!update_1d(v)) stop(); +} +void i_shortint_2d(short* v) { + if (!update_2d(v)) stop(); +} +void i_shortint_3d(short* v) { + if (!update_3d(v)) stop(); +} + +void i_shortint_unsigned_0d(unsigned short* v) { + if (!update_0d(v)) stop(); +} +void i_shortint_unsigned_1d(unsigned short* v) { + if (!update_1d(v)) stop(); +} +void i_shortint_unsigned_2d(unsigned short* v) { + if (!update_2d(v)) stop(); +} +void i_shortint_unsigned_3d(unsigned short* v) { + if (!update_3d(v)) stop(); +} + +void i_int_0d(int* v) { + if (!update_0d(v)) stop(); +} +void i_int_1d(int* v) { + if (!update_1d(v)) stop(); +} +void i_int_2d(int* v) { + if (!update_2d(v)) stop(); +} +void i_int_3d(int* v) { + if (!update_3d(v)) stop(); +} + +void i_int_unsigned_0d(unsigned int* v) { + if (!update_0d(v)) stop(); +} +void i_int_unsigned_1d(unsigned int* v) { + if (!update_1d(v)) stop(); +} +void i_int_unsigned_2d(unsigned int* v) { + if (!update_2d(v)) stop(); +} +void i_int_unsigned_3d(unsigned int* v) { + if (!update_3d(v)) stop(); +} + +void i_longint_0d(sv_longint_t* v) { + if (!update_0d(v)) stop(); +} +void i_longint_1d(sv_longint_t* v) { + if (!update_1d(v)) stop(); +} +void i_longint_2d(sv_longint_t* v) { + if (!update_2d(v)) stop(); +} +void i_longint_3d(sv_longint_t* v) { + if (!update_3d(v)) stop(); +} + +void i_longint_unsigned_0d(sv_longint_unsigned_t* v) { + if (!update_0d(v)) stop(); +} +void i_longint_unsigned_1d(sv_longint_unsigned_t* v) { + if (!update_1d(v)) stop(); +} +void i_longint_unsigned_2d(sv_longint_unsigned_t* v) { + if (!update_2d(v)) stop(); +} +void i_longint_unsigned_3d(sv_longint_unsigned_t* v) { + if (!update_3d(v)) stop(); +} + +#ifndef NO_TIME +void i_time_0d(svLogicVecVal* v) { + if (!update_0d(v, 64)) stop(); +} +void i_time_1d(svLogicVecVal* v) { + if (!update_1d(v, 64)) stop(); +} +void i_time_2d(svLogicVecVal* v) { + if (!update_2d(v, 64)) stop(); +} +void i_time_3d(svLogicVecVal* v) { + if (!update_3d(v, 64)) stop(); +} +#endif + +#ifndef NO_INTEGER +void i_integer_0d(svLogicVecVal* v) { + if (!update_0d(v, 32)) stop(); +} +void i_integer_1d(svLogicVecVal* v) { + if (!update_1d(v, 32)) stop(); +} +void i_integer_2d(svLogicVecVal* v) { + if (!update_2d(v, 32)) stop(); +} +void i_integer_3d(svLogicVecVal* v) { + if (!update_3d(v, 32)) stop(); +} +#endif + +void i_real_0d(double* v) { update_0d(v); } +void i_real_1d(double* v) { update_1d(v); } +void i_real_2d(double* v) { update_2d(v); } +void i_real_3d(double* v) { update_3d(v); } + +#ifndef NO_SHORTREAL +void i_shortreal_0d(float* v) { update_0d(v); } +void i_shortreal_1d(float* v) { update_1d(v); } +void i_shortreal_2d(float* v) { update_2d(v); } +void i_shortreal_3d(float* v) { update_3d(v); } +#endif + +void i_chandle_0d(void** v) { + if (v[0]) stop(); + v[0] = get_non_null(); +} +void i_chandle_1d(void** v) { + if (v[0]) stop(); + if (v[1]) stop(); + v[0] = get_non_null(); + v[1] = get_non_null(); +} +void i_chandle_2d(void** v) { + if (v[2 * 0 + 1]) stop(); + if (v[2 * 1 + 1]) stop(); + if (v[2 * 2 + 1]) stop(); + v[2 * 0 + 1] = get_non_null(); + v[2 * 1 + 1] = get_non_null(); + v[2 * 2 + 1] = get_non_null(); +} +void i_chandle_3d(void** v) { + if (v[(0 * 3 + 0) * 2 + 0]) stop(); + if (v[(1 * 3 + 0) * 2 + 0]) stop(); + if (v[(2 * 3 + 0) * 2 + 0]) stop(); + if (v[(3 * 3 + 0) * 2 + 0]) stop(); + v[(0 * 3 + 0) * 2 + 0] = get_non_null(); + v[(1 * 3 + 0) * 2 + 0] = get_non_null(); + v[(2 * 3 + 0) * 2 + 0] = get_non_null(); + v[(3 * 3 + 0) * 2 + 0] = get_non_null(); +} + +void i_string_0d(const char** v) { + static const char s[] = "43"; + if (!compare(v[0], "42")) stop(); + v[0] = s; +} +void i_string_1d(const char** v) { + static const char s0[] = "44"; + static const char s1[] = "45"; + if (!compare(v[0], "43")) stop(); + if (!compare(v[1], "44")) stop(); + v[0] = s0; + v[1] = s1; +} +void i_string_2d(const char** v) { + static const char s0[] = "46"; + static const char s1[] = "47"; + static const char s2[] = "48"; + if (!compare(v[2 * 0 + 1], "45")) stop(); + if (!compare(v[2 * 1 + 1], "46")) stop(); + if (!compare(v[2 * 2 + 1], "47")) stop(); + v[2 * 0 + 1] = s0; + v[2 * 1 + 1] = s1; + v[2 * 2 + 1] = s2; +} +void i_string_3d(const char** v) { + static const char s0[] = "49"; + static const char s1[] = "50"; + static const char s2[] = "51"; + static const char s3[] = "52"; + if (!compare(v[(0 * 3 + 0) * 2 + 0], "48")) stop(); + if (!compare(v[(1 * 3 + 0) * 2 + 0], "49")) stop(); + if (!compare(v[(2 * 3 + 0) * 2 + 0], "50")) stop(); + if (!compare(v[(3 * 3 + 0) * 2 + 0], "51")) stop(); + v[(0 * 3 + 0) * 2 + 0] = s0; + v[(1 * 3 + 0) * 2 + 0] = s1; + v[(2 * 3 + 0) * 2 + 0] = s2; + v[(3 * 3 + 0) * 2 + 0] = s3; +} + +void i_bit7_0d(svBitVecVal* v) { update_0d(v, 7); } +void i_bit7_1d(svBitVecVal* v) { update_1d(v, 7); } +void i_bit7_2d(svBitVecVal* v) { update_2d(v, 7); } +void i_bit7_3d(svBitVecVal* v) { update_3d(v, 7); } + +void i_bit121_0d(svBitVecVal* v) { update_0d(v, 121); } +void i_bit121_1d(svBitVecVal* v) { update_1d(v, 121); } +void i_bit121_2d(svBitVecVal* v) { update_2d(v, 121); } +void i_bit121_3d(svBitVecVal* v) { update_3d(v, 121); } + +void i_logic7_0d(svLogicVecVal* v) { update_0d(v, 7); } +void i_logic7_1d(svLogicVecVal* v) { update_1d(v, 7); } +void i_logic7_2d(svLogicVecVal* v) { update_2d(v, 7); } +void i_logic7_3d(svLogicVecVal* v) { update_3d(v, 7); } + +void i_logic121_0d(svLogicVecVal* v) { update_0d(v, 121); } +void i_logic121_1d(svLogicVecVal* v) { update_1d(v, 121); } +void i_logic121_2d(svLogicVecVal* v) { update_2d(v, 121); } +void i_logic121_3d(svLogicVecVal* v) { update_3d(v, 121); } + +void i_pack_struct_0d(svLogicVecVal* v) { update_0d(v, 7); } +void i_pack_struct_1d(svLogicVecVal* v) { update_1d(v, 7); } +void i_pack_struct_2d(svLogicVecVal* v) { update_2d(v, 7); } +void i_pack_struct_3d(svLogicVecVal* v) { update_3d(v, 7); } + +#ifndef NO_UNPACK_STRUCT +void i_unpack_struct_0d(unpack_struct_t* v) { + if (!compare(v->val, 42, 121)) stop(); + set_uint(v->val, 43, 121); +} +void i_unpack_struct_1d(unpack_struct_t* v) { + if (!compare(v[0].val, 43, 121)) stop(); + if (!compare(v[1].val, 44, 121)) stop(); + set_uint(v[0].val, 44, 121); + set_uint(v[1].val, 45, 121); +} +void i_unpack_struct_2d(unpack_struct_t* v) { + if (!compare(v[0 * 2 + 1].val, 45, 121)) stop(); + if (!compare(v[1 * 2 + 1].val, 46, 121)) stop(); + if (!compare(v[2 * 2 + 1].val, 47, 121)) stop(); + set_uint(v[0 * 2 + 1].val, 46, 121); + set_uint(v[1 * 2 + 1].val, 47, 121); + set_uint(v[2 * 2 + 1].val, 48, 121); +} +void i_unpack_struct_3d(unpack_struct_t* v) { + if (!compare(v[(0 * 3 + 0) * 2 + 0].val, 48, 121)) stop(); + if (!compare(v[(1 * 3 + 0) * 2 + 0].val, 49, 121)) stop(); + if (!compare(v[(2 * 3 + 0) * 2 + 0].val, 50, 121)) stop(); + if (!compare(v[(3 * 3 + 0) * 2 + 0].val, 51, 121)) stop(); + set_uint(v[(0 * 3 + 0) * 2 + 0].val, 49, 121); + set_uint(v[(1 * 3 + 0) * 2 + 0].val, 50, 121); + set_uint(v[(2 * 3 + 0) * 2 + 0].val, 51, 121); + set_uint(v[(3 * 3 + 0) * 2 + 0].val, 52, 121); +} +#endif + +void check_exports() { + { + char byte_array[4][3][2]; + set_values(byte_array); + e_byte_0d(&byte_array[3][2][1]); + if (!check_0d(byte_array[3][2][1])) stop(); + e_byte_1d(&byte_array[2][1][0]); + if (!check_1d(byte_array[2][1])) stop(); + e_byte_2d(&byte_array[1][0][0]); + if (!check_2d(byte_array[1])) stop(); + e_byte_3d(&byte_array[0][0][0]); + if (!check_3d(byte_array)) stop(); + } + { + unsigned char byte_unsigned_array[4][3][2]; + set_values(byte_unsigned_array); + e_byte_unsigned_0d(&byte_unsigned_array[3][2][1]); + if (!check_0d(byte_unsigned_array[3][2][1])) stop(); + e_byte_unsigned_1d(&byte_unsigned_array[2][1][0]); + if (!check_1d(byte_unsigned_array[2][1])) stop(); + e_byte_unsigned_2d(&byte_unsigned_array[1][0][0]); + if (!check_2d(byte_unsigned_array[1])) stop(); + e_byte_unsigned_3d(&byte_unsigned_array[0][0][0]); + if (!check_3d(byte_unsigned_array)) stop(); + } + { + short shortint_array[4][3][2]; + set_values(shortint_array); + e_shortint_0d(&shortint_array[3][2][1]); + if (!check_0d(shortint_array[3][2][1])) stop(); + e_shortint_1d(&shortint_array[2][1][0]); + if (!check_1d(shortint_array[2][1])) stop(); + e_shortint_2d(&shortint_array[1][0][0]); + if (!check_2d(shortint_array[1])) stop(); + e_shortint_3d(&shortint_array[0][0][0]); + if (!check_3d(shortint_array)) stop(); + } + { + unsigned short shortint_unsigned_array[4][3][2]; + set_values(shortint_unsigned_array); + e_shortint_unsigned_0d(&shortint_unsigned_array[3][2][1]); + if (!check_0d(shortint_unsigned_array[3][2][1])) stop(); + e_shortint_unsigned_1d(&shortint_unsigned_array[2][1][0]); + if (!check_1d(shortint_unsigned_array[2][1])) stop(); + e_shortint_unsigned_2d(&shortint_unsigned_array[1][0][0]); + if (!check_2d(shortint_unsigned_array[1])) stop(); + e_shortint_unsigned_3d(&shortint_unsigned_array[0][0][0]); + if (!check_3d(shortint_unsigned_array)) stop(); + } + + { + int int_array[4][3][2]; + set_values(int_array); + e_int_0d(&int_array[3][2][1]); + if (!check_0d(int_array[3][2][1])) stop(); + e_int_1d(&int_array[2][1][0]); + if (!check_1d(int_array[2][1])) stop(); + e_int_2d(&int_array[1][0][0]); + if (!check_2d(int_array[1])) stop(); + e_int_3d(&int_array[0][0][0]); + if (!check_3d(int_array)) stop(); + } + { + unsigned int int_unsigned_array[4][3][2]; + set_values(int_unsigned_array); + e_int_unsigned_0d(&int_unsigned_array[3][2][1]); + if (!check_0d(int_unsigned_array[3][2][1])) stop(); + e_int_unsigned_1d(&int_unsigned_array[2][1][0]); + if (!check_1d(int_unsigned_array[2][1])) stop(); + e_int_unsigned_2d(&int_unsigned_array[1][0][0]); + if (!check_2d(int_unsigned_array[1])) stop(); + e_int_unsigned_3d(&int_unsigned_array[0][0][0]); + if (!check_3d(int_unsigned_array)) stop(); + } + + { + sv_longint_t longint_array[4][3][2]; + set_values(longint_array); + e_longint_0d(&longint_array[3][2][1]); + if (!check_0d(longint_array[3][2][1])) stop(); + e_longint_1d(&longint_array[2][1][0]); + if (!check_1d(longint_array[2][1])) stop(); + e_longint_2d(&longint_array[1][0][0]); + if (!check_2d(longint_array[1])) stop(); + e_longint_3d(&longint_array[0][0][0]); + if (!check_3d(longint_array)) stop(); + } + { + sv_longint_unsigned_t longint_unsigned_array[4][3][2]; + set_values(longint_unsigned_array); + e_longint_unsigned_0d(&longint_unsigned_array[3][2][1]); + if (!check_0d(longint_unsigned_array[3][2][1])) stop(); + e_longint_unsigned_1d(&longint_unsigned_array[2][1][0]); + if (!check_1d(longint_unsigned_array[2][1])) stop(); + e_longint_unsigned_2d(&longint_unsigned_array[1][0][0]); + if (!check_2d(longint_unsigned_array[1])) stop(); + e_longint_unsigned_3d(&longint_unsigned_array[0][0][0]); + if (!check_3d(longint_unsigned_array)) stop(); + } + +#ifndef NO_TIME + { + svLogicVecVal time_array[4][3][2][2]; + set_values(time_array, 64); + e_time_0d(time_array[3][2][1]); + if (!check_0d(time_array[3][2][1], 64)) stop(); + e_time_1d(time_array[2][1][0]); + if (!check_1d(time_array[2][1], 64)) stop(); + e_time_2d(time_array[1][0][0]); + if (!check_2d(time_array[1], 64)) stop(); + e_time_3d(time_array[0][0][0]); + if (!check_3d(time_array, 64)) stop(); + } +#endif + +#ifndef NO_INTEGER + { + svLogicVecVal integer_array[4][3][2][1]; + set_values(integer_array, 32); + e_integer_0d(integer_array[3][2][1]); + if (!check_0d(integer_array[3][2][1], 32)) stop(); + e_integer_1d(integer_array[2][1][0]); + if (!check_1d(integer_array[2][1], 32)) stop(); + e_integer_2d(integer_array[1][0][0]); + if (!check_2d(integer_array[1], 32)) stop(); + e_integer_3d(integer_array[0][0][0]); + if (!check_3d(integer_array, 32)) stop(); + } +#endif + + { + double real_array[4][3][2]; + set_values(real_array); + e_real_0d(&real_array[3][2][1]); + if (!check_0d(real_array[3][2][1])) stop(); + e_real_1d(&real_array[2][1][0]); + if (!check_1d(real_array[2][1])) stop(); + e_real_2d(&real_array[1][0][0]); + if (!check_2d(real_array[1])) stop(); + e_real_3d(&real_array[0][0][0]); + if (!check_3d(real_array)) stop(); + } +#ifndef NO_SHORTREAL + { + float shortreal_array[4][3][2]; + set_values(shortreal_array); + e_shortreal_0d(&shortreal_array[3][2][1]); + if (!check_0d(shortreal_array[3][2][1])) stop(); + e_shortreal_1d(&shortreal_array[2][1][0]); + if (!check_1d(shortreal_array[2][1])) stop(); + e_shortreal_2d(&shortreal_array[1][0][0]); + if (!check_2d(shortreal_array[1])) stop(); + e_shortreal_3d(&shortreal_array[0][0][0]); + if (!check_3d(shortreal_array)) stop(); + } +#endif + + { + void* chandle_array[4][3][2]; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) chandle_array[i][j][k] = NULL; + chandle_array[3][2][1] = get_non_null(); + e_chandle_0d(&chandle_array[3][2][1]); + if (chandle_array[3][2][1]) stop(); + + chandle_array[2][1][0] = get_non_null(); + chandle_array[2][1][1] = get_non_null(); + e_chandle_1d(&chandle_array[2][1][0]); + if (chandle_array[2][1][0]) stop(); + if (chandle_array[2][1][1]) stop(); + + chandle_array[1][0][1] = get_non_null(); + chandle_array[1][1][1] = get_non_null(); + chandle_array[1][2][1] = get_non_null(); + e_chandle_2d(&chandle_array[1][0][0]); + if (chandle_array[1][0][1]) stop(); + if (chandle_array[1][1][1]) stop(); + if (chandle_array[1][2][1]) stop(); + + chandle_array[0][0][0] = get_non_null(); + chandle_array[1][0][0] = get_non_null(); + chandle_array[2][0][0] = get_non_null(); + chandle_array[3][0][0] = get_non_null(); + e_chandle_3d(&chandle_array[0][0][0]); + if (chandle_array[0][0][0]) stop(); + if (chandle_array[1][0][0]) stop(); + if (chandle_array[2][0][0]) stop(); + if (chandle_array[3][0][0]) stop(); + } + + { + const char* string_array[4][3][2]; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) string_array[i][j][k] = ""; + string_array[3][2][1] = "42"; + e_string_0d(&string_array[3][2][1]); + if (!compare(string_array[3][2][1], "43")) stop(); + + string_array[2][1][0] = "43"; + string_array[2][1][1] = "44"; + e_string_1d(&string_array[2][1][0]); + if (!compare(string_array[2][1][0], "44")) stop(); + if (!compare(string_array[2][1][1], "45")) stop(); + + string_array[1][0][1] = "45"; + string_array[1][1][1] = "46"; + string_array[1][2][1] = "47"; + e_string_2d(&string_array[1][0][0]); + if (!compare(string_array[1][0][1], "46")) stop(); + if (!compare(string_array[1][1][1], "47")) stop(); + if (!compare(string_array[1][2][1], "48")) stop(); + + string_array[0][0][0] = "48"; + string_array[1][0][0] = "49"; + string_array[2][0][0] = "50"; + string_array[3][0][0] = "51"; + e_string_3d(&string_array[0][0][0]); + if (!compare(string_array[0][0][0], "49")) stop(); + if (!compare(string_array[1][0][0], "50")) stop(); + if (!compare(string_array[2][0][0], "51")) stop(); + if (!compare(string_array[3][0][0], "52")) stop(); + } + + { + svBitVecVal bit7_array[4][3][2][1]; + set_values(bit7_array, 7); + e_bit7_0d(bit7_array[3][2][1]); + if (!check_0d(bit7_array[3][2][1], 7)) stop(); + e_bit7_1d(bit7_array[2][1][0]); + if (!check_1d(bit7_array[2][1], 7)) stop(); + e_bit7_2d(bit7_array[1][0][0]); + if (!check_2d(bit7_array[1], 7)) stop(); + e_bit7_3d(bit7_array[0][0][0]); + if (!check_3d(bit7_array, 7)) stop(); + } + { + svBitVecVal bit121_array[4][3][2][4]; + set_values(bit121_array, 121); + e_bit121_0d(bit121_array[3][2][1]); + if (!check_0d(bit121_array[3][2][1], 121)) stop(); + e_bit121_1d(bit121_array[2][1][0]); + if (!check_1d(bit121_array[2][1], 121)) stop(); + e_bit121_2d(bit121_array[1][0][0]); + if (!check_2d(bit121_array[1], 121)) stop(); + e_bit121_3d(bit121_array[0][0][0]); + if (!check_3d(bit121_array, 121)) stop(); + } + + { + svLogicVecVal logic7_array[4][3][2][1]; + set_values(logic7_array, 7); + e_logic7_0d(logic7_array[3][2][1]); + if (!check_0d(logic7_array[3][2][1], 7)) stop(); + e_logic7_1d(logic7_array[2][1][0]); + if (!check_1d(logic7_array[2][1], 7)) stop(); + e_logic7_2d(logic7_array[1][0][0]); + if (!check_2d(logic7_array[1], 7)) stop(); + e_logic7_3d(logic7_array[0][0][0]); + if (!check_3d(logic7_array, 7)) stop(); + } + { + svLogicVecVal logic121_array[4][3][2][4]; + set_values(logic121_array, 121); + e_logic121_0d(logic121_array[3][2][1]); + if (!check_0d(logic121_array[3][2][1], 121)) stop(); + e_logic121_1d(logic121_array[2][1][0]); + if (!check_1d(logic121_array[2][1], 121)) stop(); + e_logic121_2d(logic121_array[1][0][0]); + if (!check_2d(logic121_array[1], 121)) stop(); + e_logic121_3d(logic121_array[0][0][0]); + if (!check_3d(logic121_array, 121)) stop(); + } + + { + svLogicVecVal pack_struct_array[4][3][2][1]; + set_values(pack_struct_array, 7); + e_pack_struct_0d(pack_struct_array[3][2][1]); + if (!check_0d(pack_struct_array[3][2][1], 7)) stop(); + e_pack_struct_1d(pack_struct_array[2][1][0]); + if (!check_1d(pack_struct_array[2][1], 7)) stop(); + e_pack_struct_2d(pack_struct_array[1][0][0]); + if (!check_2d(pack_struct_array[1], 7)) stop(); + e_pack_struct_3d(pack_struct_array[0][0][0]); + if (!check_3d(pack_struct_array, 7)) stop(); + } + +#ifndef NO_UNPACK_STRUCT + { + unpack_struct_t unpack_struct_array[4][3][2]; + set_uint(unpack_struct_array[3][2][1].val, 42, 121); + e_unpack_struct_0d(&unpack_struct_array[3][2][1]); + if (!compare(unpack_struct_array[3][2][1].val, 43, 121)) stop(); + + set_uint(unpack_struct_array[2][1][0].val, 43, 121); + set_uint(unpack_struct_array[2][1][1].val, 44, 121); + e_unpack_struct_1d(&unpack_struct_array[2][1][0]); + if (!compare(unpack_struct_array[2][1][0].val, 44, 121)) stop(); + if (!compare(unpack_struct_array[2][1][1].val, 45, 121)) stop(); + + set_uint(unpack_struct_array[1][0][1].val, 45, 121); + set_uint(unpack_struct_array[1][1][1].val, 46, 121); + set_uint(unpack_struct_array[1][2][1].val, 47, 121); + e_unpack_struct_2d(&unpack_struct_array[1][0][0]); + if (!compare(unpack_struct_array[1][0][1].val, 46, 121)) stop(); + if (!compare(unpack_struct_array[1][1][1].val, 47, 121)) stop(); + if (!compare(unpack_struct_array[1][2][1].val, 48, 121)) stop(); + + set_uint(unpack_struct_array[0][0][0].val, 48, 121); + set_uint(unpack_struct_array[1][0][0].val, 49, 121); + set_uint(unpack_struct_array[2][0][0].val, 50, 121); + set_uint(unpack_struct_array[3][0][0].val, 51, 121); + e_unpack_struct_3d(&unpack_struct_array[0][0][0]); + if (!compare(unpack_struct_array[0][0][0].val, 49, 121)) stop(); + if (!compare(unpack_struct_array[1][0][0].val, 50, 121)) stop(); + if (!compare(unpack_struct_array[2][0][0].val, 51, 121)) stop(); + if (!compare(unpack_struct_array[3][0][0].val, 52, 121)) stop(); + } +#endif +} diff --git a/test_regress/t/t_dpi_arg_inout_unpack.pl b/test_regress/t/t_dpi_arg_inout_unpack.pl new file mode 100755 index 000000000..59dfe0252 --- /dev/null +++ b/test_regress/t/t_dpi_arg_inout_unpack.pl @@ -0,0 +1,44 @@ +#!/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 Geza Lore. 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); + +if ($Self->{nc}) { + # For NC, compile twice, first just to generate DPI headers + compile( + nc_flags2 => ["+ncdpiheader+$Self->{obj_dir}/dpi-exp.h", + "+ncdpiimpheader+$Self->{obj_dir}/dpi-imp.h"] + ); +} + +compile( + v_flags2 => ["t/t_dpi_arg_inout_unpack.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # NC: Gdd the obj_dir to the C include path + nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], + # ModelSim: Generate DPI header, add obj_dir to the C include path + ms_flags2 => ["-dpiheader $Self->{obj_dir}/dpi.h", + "-ccflags -I$Self->{obj_dir}"], + ); + +if ($Self->{vlt_all}) { + files_identical( + "$Self->{obj_dir}/Vt_dpi_arg_inout_unpack__Dpi.h", + "t/t_dpi_arg_inout_unpack__Dpi.out" + ); +} + +execute( + check_finished => 1, + ms_pli => 0 + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_arg_inout_unpack.v b/test_regress/t/t_dpi_arg_inout_unpack.v new file mode 100644 index 000000000..a37a24cc2 --- /dev/null +++ b/test_regress/t/t_dpi_arg_inout_unpack.v @@ -0,0 +1,1162 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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 + +`ifdef VCS + `define NO_TIME +`endif + +`ifdef NC + `define NO_TIME + `define NO_INTEGER + `define NO_SHORTREAL +`endif + +`ifdef MS +`endif + +`ifdef VERILATOR + `define NO_SHORTREAL + `define NO_UNPACK_STRUCT +//%Error-TASKNSVAR: Unsupported: Function/task input argument is not simple variable + `define NO_INOUT_COMPLEX_TYPE +`else +`endif + +`define CHECK_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ + end else begin \ + $display("Mismatch %s expected:%d actual:%d at %d", `"act`", int'(exp), int'(act), `__LINE__); \ + $stop; \ + end + +`define CHECK_CHANDLE_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":non-null as expected"); \ + end else begin \ + $display("Mismatch %s expected:%s but %s at %d", `"act`", \ + (exp) != null ? "null" : "non-null", \ + (act) != null ? "null" : "non-null", `__LINE__); \ + $stop; \ + end + +`define CHECK_STRING_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ + end else begin \ + $display("Mismatch %s expected:%s actual:%s at %d", `"act`", (exp), (act), `__LINE__); \ + $stop; \ + end + +`define UPDATE_VAL(var, val) `CHECK_VAL(var, val); var += 1 +`define UPDATE_0D(val) `UPDATE_VAL(val, 42) +`define UPDATE_1D(val) `UPDATE_VAL(val[0], 43); \ +`UPDATE_VAL(val[1], 44) +`define UPDATE_2D(val) `UPDATE_VAL(val[0][1], 45); \ +`UPDATE_VAL(val[1][1], 46); \ +`UPDATE_VAL(val[2][1], 47) +`define UPDATE_3D(val) `UPDATE_VAL(val[0][0][0], 48); \ +`UPDATE_VAL(val[1][0][0], 49); \ +`UPDATE_VAL(val[2][0][0], 50); \ +`UPDATE_VAL(val[3][0][0], 51) + +`define CHECK_0D(val) `CHECK_VAL((val), 43) +`define CHECK_1D(val) `CHECK_VAL(val[0], 44); \ +`CHECK_VAL(val[1], 45) +`define CHECK_2D(val) `CHECK_VAL(val[0][1], 46); \ +`CHECK_VAL(val[1][1], 47); `CHECK_VAL(val[2][1], 48) +`define CHECK_3D(val) `CHECK_VAL(val[0][0][0], 49); \ +`CHECK_VAL(val[1][0][0], 50); \ +`CHECK_VAL(val[2][0][0], 51); \ +`CHECK_VAL(val[3][0][0], 52) + +`define CHECK_DOUBLE_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display("%s:%f as expected", `"act`", (act)); \ + end else begin \ + $display("Mismatch %s expected:%d actual:%f at %f", `"act`", (exp), (act), `__LINE__); \ + $stop; \ + end + +`define CHECK_DOUBLE_0D(val) `CHECK_DOUBLE_VAL((val), 43.0) +`define CHECK_DOUBLE_1D(val) `CHECK_DOUBLE_VAL(val[0], 44.0); \ +`CHECK_DOUBLE_VAL(val[1], 45.0) +`define CHECK_DOUBLE_2D(val) `CHECK_DOUBLE_VAL(val[0][1], 46.0); \ +`CHECK_DOUBLE_VAL(val[1][1], 47.0); \ +`CHECK_DOUBLE_VAL(val[2][1], 48.0) +`define CHECK_DOUBLE_3D(val) `CHECK_DOUBLE_VAL(val[0][0][0], 49.0); \ +`CHECK_DOUBLE_VAL(val[1][0][0], 50.0); \ +`CHECK_DOUBLE_VAL(val[2][0][0], 51.0); \ +`CHECK_DOUBLE_VAL(val[3][0][0], 52.0) + +`define SET_VALUE_0D(val) val = 42 +`define SET_VALUE_1D(val) val[0] = 43; val[1] = 44 +`define SET_VALUE_2D(val) val[0][1] = 45; val[1][1] = 46; val[2][1] = 47 +`define SET_VALUES(val) \ +val[3][2][1] = 42; \ +val[2][1][0] = 43; val[2][1][1] = 44; \ +val[1][0][1] = 45; val[1][1][1] = 46; val[1][2][1] = 47; \ +val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 + +module t; + + localparam ENABLE_VERBOSE_MESSAGE = 0; + + // Legal output argument types for DPI functions + + //====================================================================== + // Type definitions + //====================================================================== + + typedef byte byte_t; + typedef byte_t byte_array_t[4][3][2]; + typedef byte unsigned byte_unsigned_t; + typedef byte_unsigned_t byte_unsigned_array_t[4][3][2]; + typedef shortint shortint_t; + typedef shortint_t shortint_array_t[4][3][2]; + typedef shortint unsigned shortint_unsigned_t; + typedef shortint_unsigned_t shortint_unsigned_array_t[4][3][2]; + typedef int int_t; + typedef int_t int_array_t[4][3][2]; + typedef int unsigned int_unsigned_t; + typedef int_unsigned_t int_unsigned_array_t[4][3][2]; + typedef longint longint_t; + typedef longint_t longint_array_t[4][3][2]; + typedef longint unsigned longint_unsigned_t; + typedef longint_unsigned_t longint_unsigned_array_t[4][3][2]; +`ifndef NO_TIME + typedef time time_t; + typedef time_t time_array_t[4][3][2]; +`endif +`ifndef NO_INTEGER + typedef integer integer_t; + typedef integer_t integer_array_t[4][3][2]; +`endif + typedef real real_t; + typedef real_t real_array_t[4][3][2]; +`ifndef NO_SHORTREAL + typedef shortreal shortreal_t; + typedef shortreal_t shortreal_array_t[4][3][2]; +`endif + typedef chandle chandle_t; + typedef chandle_t chandle_array_t[4][3][2]; + typedef string string_t; + typedef string_t string_array_t[4][3][2]; + typedef bit [6:0] bit7_t; + typedef bit7_t bit7_array_t[4][3][2]; + typedef bit [120:0] bit121_t; + typedef bit121_t bit121_array_t[4][3][2]; + typedef logic [6:0] logic7_t; + typedef logic7_t logic7_array_t[4][3][2]; + typedef logic [120:0] logic121_t; + typedef logic121_t logic121_array_t[4][3][2]; + + typedef struct packed { + logic [6:0] val; + } pack_struct_t; + typedef pack_struct_t pack_struct_array_t[4][3][2]; +`ifndef NO_UNPACK_STRUCT + typedef struct { + logic [120:0] val; + } unpack_struct_t; + typedef unpack_struct_t unpack_struct_array_t[4][3][2]; +`endif + + //====================================================================== + // Imports + //====================================================================== + + // Returns non-null pointer + import "DPI-C" function chandle get_non_null(); + + import "DPI-C" function void i_byte_0d(inout byte_t val); + import "DPI-C" function void i_byte_1d(inout byte_t val[2]); + import "DPI-C" function void i_byte_2d(inout byte_t val[3][2]); + import "DPI-C" function void i_byte_3d(inout byte_array_t val); + + import "DPI-C" function void i_byte_unsigned_0d(inout byte unsigned val); + import "DPI-C" function void i_byte_unsigned_1d(inout byte unsigned val[2]); + import "DPI-C" function void i_byte_unsigned_2d(inout byte unsigned val[3][2]); + import "DPI-C" function void i_byte_unsigned_3d(inout byte_unsigned_array_t val); + + import "DPI-C" function void i_shortint_0d(inout shortint val); + import "DPI-C" function void i_shortint_1d(inout shortint val[2]); + import "DPI-C" function void i_shortint_2d(inout shortint val[3][2]); + import "DPI-C" function void i_shortint_3d(inout shortint_array_t val); + + import "DPI-C" function void i_shortint_unsigned_0d(inout shortint unsigned val); + import "DPI-C" function void i_shortint_unsigned_1d(inout shortint unsigned val[2]); + import "DPI-C" function void i_shortint_unsigned_2d(inout shortint unsigned val[3][2]); + import "DPI-C" function void i_shortint_unsigned_3d(inout shortint_unsigned_array_t val); + + import "DPI-C" function void i_int_0d(inout int val); + import "DPI-C" function void i_int_1d(inout int val[2]); + import "DPI-C" function void i_int_2d(inout int val[3][2]); + import "DPI-C" function void i_int_3d(inout int_array_t val); + + import "DPI-C" function void i_int_unsigned_0d(inout int unsigned val); + import "DPI-C" function void i_int_unsigned_1d(inout int unsigned val[2]); + import "DPI-C" function void i_int_unsigned_2d(inout int unsigned val[3][2]); + import "DPI-C" function void i_int_unsigned_3d(inout int_unsigned_array_t val); + + import "DPI-C" function void i_longint_0d(inout longint val); + import "DPI-C" function void i_longint_1d(inout longint val[2]); + import "DPI-C" function void i_longint_2d(inout longint val[3][2]); + import "DPI-C" function void i_longint_3d(inout longint_array_t val); + + import "DPI-C" function void i_longint_unsigned_0d(inout longint unsigned val); + import "DPI-C" function void i_longint_unsigned_1d(inout longint unsigned val[2]); + import "DPI-C" function void i_longint_unsigned_2d(inout longint unsigned val[3][2]); + import "DPI-C" function void i_longint_unsigned_3d(inout longint_unsigned_array_t val); + +`ifndef NO_TIME + import "DPI-C" function void i_time_0d(inout time val); + import "DPI-C" function void i_time_1d(inout time val[2]); + import "DPI-C" function void i_time_2d(inout time val[3][2]); + import "DPI-C" function void i_time_3d(inout time_array_t val); +`endif + +`ifndef NO_INTEGER + import "DPI-C" function void i_integer_0d(inout integer val); + import "DPI-C" function void i_integer_1d(inout integer val[2]); + import "DPI-C" function void i_integer_2d(inout integer val[3][2]); + import "DPI-C" function void i_integer_3d(inout integer_array_t val); +`endif + + import "DPI-C" function void i_real_0d(inout real val); + import "DPI-C" function void i_real_1d(inout real val[2]); + import "DPI-C" function void i_real_2d(inout real val[3][2]); + import "DPI-C" function void i_real_3d(inout real_array_t val); + +`ifndef NO_SHORTREAL + import "DPI-C" function void i_shortreal_0d(inout shortreal val); + import "DPI-C" function void i_shortreal_1d(inout shortreal val[2]); + import "DPI-C" function void i_shortreal_2d(inout shortreal val[3][2]); + import "DPI-C" function void i_shortreal_3d(inout shortreal_array_t val); +`endif + + import "DPI-C" function void i_chandle_0d(inout chandle val); + import "DPI-C" function void i_chandle_1d(inout chandle val[2]); + import "DPI-C" function void i_chandle_2d(inout chandle val[3][2]); + import "DPI-C" function void i_chandle_3d(inout chandle_array_t val); + + import "DPI-C" function void i_string_0d(inout string val); + import "DPI-C" function void i_string_1d(inout string val[2]); + import "DPI-C" function void i_string_2d(inout string val[3][2]); + import "DPI-C" function void i_string_3d(inout string_array_t val); + + import "DPI-C" function void i_bit7_0d(inout bit[6:0] val); + import "DPI-C" function void i_bit7_1d(inout bit[6:0] val[2]); + import "DPI-C" function void i_bit7_2d(inout bit[6:0] val[3][2]); + import "DPI-C" function void i_bit7_3d(inout bit7_array_t val); + + import "DPI-C" function void i_bit121_0d(inout bit[120:0] val); + import "DPI-C" function void i_bit121_1d(inout bit[120:0] val[2]); + import "DPI-C" function void i_bit121_2d(inout bit[120:0] val[3][2]); + import "DPI-C" function void i_bit121_3d(inout bit121_array_t val); + + import "DPI-C" function void i_logic7_0d(inout logic[6:0] val); + import "DPI-C" function void i_logic7_1d(inout logic[6:0] val[2]); + import "DPI-C" function void i_logic7_2d(inout logic[6:0] val[3][2]); + import "DPI-C" function void i_logic7_3d(inout logic7_array_t val); + + import "DPI-C" function void i_logic121_0d(inout logic[120:0] val); + import "DPI-C" function void i_logic121_1d(inout logic[120:0] val[2]); + import "DPI-C" function void i_logic121_2d(inout logic[120:0] val[3][2]); + import "DPI-C" function void i_logic121_3d(inout logic121_array_t val); + + import "DPI-C" function void i_pack_struct_0d(inout pack_struct_t val); + import "DPI-C" function void i_pack_struct_1d(inout pack_struct_t val[2]); + import "DPI-C" function void i_pack_struct_2d(inout pack_struct_t val[3][2]); + import "DPI-C" function void i_pack_struct_3d(inout pack_struct_array_t val); + +`ifndef NO_UNPACK_STRUCT + import "DPI-C" function void i_unpack_struct_0d(inout unpack_struct_t val); + import "DPI-C" function void i_unpack_struct_1d(inout unpack_struct_t val[2]); + import "DPI-C" function void i_unpack_struct_2d(inout unpack_struct_t val[3][2]); + import "DPI-C" function void i_unpack_struct_3d(inout unpack_struct_array_t val); +`endif + + //====================================================================== + // Exports + //====================================================================== + export "DPI-C" function e_byte_0d; + export "DPI-C" function e_byte_1d; + export "DPI-C" function e_byte_2d; + export "DPI-C" function e_byte_3d; + + export "DPI-C" function e_byte_unsigned_0d; + export "DPI-C" function e_byte_unsigned_1d; + export "DPI-C" function e_byte_unsigned_2d; + export "DPI-C" function e_byte_unsigned_3d; + + export "DPI-C" function e_shortint_0d; + export "DPI-C" function e_shortint_1d; + export "DPI-C" function e_shortint_2d; + export "DPI-C" function e_shortint_3d; + + export "DPI-C" function e_shortint_unsigned_0d; + export "DPI-C" function e_shortint_unsigned_1d; + export "DPI-C" function e_shortint_unsigned_2d; + export "DPI-C" function e_shortint_unsigned_3d; + + export "DPI-C" function e_int_0d; + export "DPI-C" function e_int_1d; + export "DPI-C" function e_int_2d; + export "DPI-C" function e_int_3d; + + export "DPI-C" function e_int_unsigned_0d; + export "DPI-C" function e_int_unsigned_1d; + export "DPI-C" function e_int_unsigned_2d; + export "DPI-C" function e_int_unsigned_3d; + + export "DPI-C" function e_longint_0d; + export "DPI-C" function e_longint_1d; + export "DPI-C" function e_longint_2d; + export "DPI-C" function e_longint_3d; + + export "DPI-C" function e_longint_unsigned_0d; + export "DPI-C" function e_longint_unsigned_1d; + export "DPI-C" function e_longint_unsigned_2d; + export "DPI-C" function e_longint_unsigned_3d; + +`ifndef NO_TIME + export "DPI-C" function e_time_0d; + export "DPI-C" function e_time_1d; + export "DPI-C" function e_time_2d; + export "DPI-C" function e_time_3d; +`endif + +`ifndef NO_INTEGER + export "DPI-C" function e_integer_0d; + export "DPI-C" function e_integer_1d; + export "DPI-C" function e_integer_2d; + export "DPI-C" function e_integer_3d; +`endif + + export "DPI-C" function e_real_0d; + export "DPI-C" function e_real_1d; + export "DPI-C" function e_real_2d; + export "DPI-C" function e_real_3d; + +`ifndef NO_SHORTREAL + export "DPI-C" function e_shortreal_0d; + export "DPI-C" function e_shortreal_1d; + export "DPI-C" function e_shortreal_2d; + export "DPI-C" function e_shortreal_3d; +`endif + + export "DPI-C" function e_chandle_0d; + export "DPI-C" function e_chandle_1d; + export "DPI-C" function e_chandle_2d; + export "DPI-C" function e_chandle_3d; + + export "DPI-C" function e_string_0d; + export "DPI-C" function e_string_1d; + export "DPI-C" function e_string_2d; + export "DPI-C" function e_string_3d; + + export "DPI-C" function e_bit7_0d; + export "DPI-C" function e_bit7_1d; + export "DPI-C" function e_bit7_2d; + export "DPI-C" function e_bit7_3d; + + export "DPI-C" function e_bit121_0d; + export "DPI-C" function e_bit121_1d; + export "DPI-C" function e_bit121_2d; + export "DPI-C" function e_bit121_3d; + + export "DPI-C" function e_logic7_0d; + export "DPI-C" function e_logic7_1d; + export "DPI-C" function e_logic7_2d; + export "DPI-C" function e_logic7_3d; + + export "DPI-C" function e_logic121_0d; + export "DPI-C" function e_logic121_1d; + export "DPI-C" function e_logic121_2d; + export "DPI-C" function e_logic121_3d; + + export "DPI-C" function e_pack_struct_0d; + export "DPI-C" function e_pack_struct_1d; + export "DPI-C" function e_pack_struct_2d; + export "DPI-C" function e_pack_struct_3d; + +`ifndef NO_UNPACK_STRUCT + export "DPI-C" function e_unpack_struct_0d; + export "DPI-C" function e_unpack_struct_1d; + export "DPI-C" function e_unpack_struct_2d; + export "DPI-C" function e_unpack_struct_3d; +`endif + //====================================================================== + // Definitions of exported functions + //====================================================================== + + function void e_byte_0d(inout byte val); `UPDATE_0D(val); endfunction + function void e_byte_1d(inout byte val[2]); `UPDATE_1D(val); endfunction + function void e_byte_2d(inout byte val[3][2]); `UPDATE_2D(val); endfunction + function void e_byte_3d(inout byte_array_t val); `UPDATE_3D(val); endfunction + + function void e_byte_unsigned_0d(inout byte unsigned val); `UPDATE_0D(val); endfunction + function void e_byte_unsigned_1d(inout byte unsigned val[2]); `UPDATE_1D(val); endfunction + function void e_byte_unsigned_2d(inout byte unsigned val[3][2]); `UPDATE_2D(val); endfunction + function void e_byte_unsigned_3d(inout byte_unsigned_array_t val); `UPDATE_3D(val); endfunction + + function void e_shortint_0d(inout shortint val); `UPDATE_0D(val); endfunction + function void e_shortint_1d(inout shortint val[2]); `UPDATE_1D(val); endfunction + function void e_shortint_2d(inout shortint val[3][2]); `UPDATE_2D(val); endfunction + function void e_shortint_3d(inout shortint_array_t val); `UPDATE_3D(val); endfunction + + function void e_shortint_unsigned_0d(inout shortint unsigned val); `UPDATE_0D(val); endfunction + function void e_shortint_unsigned_1d(inout shortint unsigned val[2]); `UPDATE_1D(val); endfunction + function void e_shortint_unsigned_2d(inout shortint unsigned val[3][2]); `UPDATE_2D(val); endfunction + function void e_shortint_unsigned_3d(inout shortint_unsigned_array_t val); `UPDATE_3D(val); endfunction + + + function void e_int_0d(inout int val); `UPDATE_0D(val); endfunction + function void e_int_1d(inout int val[2]); `UPDATE_1D(val); endfunction + function void e_int_2d(inout int val[3][2]); `UPDATE_2D(val); endfunction + function void e_int_3d(inout int_array_t val); `UPDATE_3D(val); endfunction + + function void e_int_unsigned_0d(inout int unsigned val); `UPDATE_0D(val); endfunction + function void e_int_unsigned_1d(inout int unsigned val[2]); `UPDATE_1D(val); endfunction + function void e_int_unsigned_2d(inout int unsigned val[3][2]); `UPDATE_2D(val); endfunction + function void e_int_unsigned_3d(inout int_unsigned_array_t val); `UPDATE_3D(val); endfunction + + + + function void e_longint_0d(inout longint val); `UPDATE_0D(val); endfunction + function void e_longint_1d(inout longint val[2]); `UPDATE_1D(val); endfunction + function void e_longint_2d(inout longint val[3][2]); `UPDATE_2D(val); endfunction + function void e_longint_3d(inout longint_array_t val); `UPDATE_3D(val); endfunction + + function void e_longint_unsigned_0d(inout longint unsigned val); `UPDATE_0D(val); endfunction + function void e_longint_unsigned_1d(inout longint unsigned val[2]); `UPDATE_1D(val); endfunction + function void e_longint_unsigned_2d(inout longint unsigned val[3][2]); `UPDATE_2D(val); endfunction + function void e_longint_unsigned_3d(inout longint_unsigned_array_t val); `UPDATE_3D(val); endfunction + +`ifndef NO_TIME + function void e_time_0d(inout time val); `UPDATE_0D(val); endfunction + function void e_time_1d(inout time val[2]); `UPDATE_1D(val); endfunction + function void e_time_2d(inout time val[3][2]); `UPDATE_2D(val); endfunction + function void e_time_3d(inout time_array_t val); `UPDATE_3D(val); endfunction +`endif + +`ifndef NO_INTEGER + function void e_integer_0d(inout integer val); `UPDATE_0D(val); endfunction + function void e_integer_1d(inout integer val[2]); `UPDATE_1D(val); endfunction + function void e_integer_2d(inout integer val[3][2]); `UPDATE_2D(val); endfunction + function void e_integer_3d(inout integer_array_t val); `UPDATE_3D(val); endfunction +`endif + + function void e_real_0d(inout real val); `UPDATE_0D(val); endfunction + function void e_real_1d(inout real val[2]); `UPDATE_1D(val); endfunction + function void e_real_2d(inout real val[3][2]); `UPDATE_2D(val); endfunction + function void e_real_3d(inout real_array_t val); `UPDATE_3D(val); endfunction + +`ifndef NO_SHORTREAL + function void e_shortreal_0d(inout shortreal val); `UPDATE_0D(val); endfunction + function void e_shortreal_1d(inout shortreal val[2]); `UPDATE_1D(val); endfunction + function void e_shortreal_2d(inout shortreal val[3][2]); `UPDATE_2D(val); endfunction + function void e_shortreal_3d(inout shortreal_array_t val); `UPDATE_3D(val); endfunction +`endif + + + function void e_chandle_0d(inout chandle val); + `CHECK_CHANDLE_VAL(val, get_non_null()); + val = null; + endfunction + function void e_chandle_1d(inout chandle val[2]); + `CHECK_CHANDLE_VAL(val[0], get_non_null()); + `CHECK_CHANDLE_VAL(val[1], get_non_null()); + val[0] = null; + val[1] = null; + endfunction + function void e_chandle_2d(inout chandle val[3][2]); + `CHECK_CHANDLE_VAL(val[0][1], get_non_null()); + `CHECK_CHANDLE_VAL(val[1][1], get_non_null()); + `CHECK_CHANDLE_VAL(val[2][1], get_non_null()); + val[0][1] = null; + val[1][1] = null; + val[2][1] = null; + endfunction + function void e_chandle_3d(inout chandle_array_t val); + `CHECK_CHANDLE_VAL(val[0][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(val[1][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(val[2][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(val[3][0][0], get_non_null()); + val[0][0][0] = null; + val[1][0][0] = null; + val[2][0][0] = null; + val[3][0][0] = null; + endfunction + + + function void e_string_0d(inout string val); + `CHECK_STRING_VAL(val, "42"); + val = "43"; + endfunction + function void e_string_1d(inout string val[2]); + `CHECK_STRING_VAL(val[0], "43"); + `CHECK_STRING_VAL(val[1], "44"); + val[0] = "44"; + val[1] = "45"; + endfunction + function void e_string_2d(inout string val[3][2]); + `CHECK_STRING_VAL(val[0][1], "45"); + `CHECK_STRING_VAL(val[1][1], "46"); + `CHECK_STRING_VAL(val[2][1], "47"); + val[0][1] = "46"; + val[1][1] = "47"; + val[2][1] = "48"; + endfunction + function void e_string_3d(inout string_array_t val); + `CHECK_STRING_VAL(val[0][0][0], "48"); + `CHECK_STRING_VAL(val[1][0][0], "49"); + `CHECK_STRING_VAL(val[2][0][0], "50"); + `CHECK_STRING_VAL(val[3][0][0], "51"); + val[0][0][0] = "49"; + val[1][0][0] = "50"; + val[2][0][0] = "51"; + val[3][0][0] = "52"; + endfunction + + function void e_bit7_0d(inout bit[6:0] val); `UPDATE_0D(val); endfunction + function void e_bit7_1d(inout bit[6:0] val[2]); `UPDATE_1D(val); endfunction + function void e_bit7_2d(inout bit[6:0] val[3][2]); `UPDATE_2D(val); endfunction + function void e_bit7_3d(inout bit7_array_t val); `UPDATE_3D(val); endfunction + + function void e_bit121_0d(inout bit[120:0] val); `UPDATE_0D(val); endfunction + function void e_bit121_1d(inout bit[120:0] val[2]); `UPDATE_1D(val); endfunction + function void e_bit121_2d(inout bit[120:0] val[3][2]); `UPDATE_2D(val); endfunction + function void e_bit121_3d(inout bit121_array_t val); `UPDATE_3D(val); endfunction + + function void e_logic7_0d(inout logic[6:0] val); `UPDATE_0D(val); endfunction + function void e_logic7_1d(inout logic[6:0] val[2]); `UPDATE_1D(val); endfunction + function void e_logic7_2d(inout logic[6:0] val[3][2]); `UPDATE_2D(val); endfunction + function void e_logic7_3d(inout logic7_array_t val); `UPDATE_3D(val); endfunction + + function void e_logic121_0d(inout logic[120:0] val); `UPDATE_0D(val); endfunction + function void e_logic121_1d(inout logic[120:0] val[2]); `UPDATE_1D(val); endfunction + function void e_logic121_2d(inout logic[120:0] val[3][2]); `UPDATE_2D(val); endfunction + function void e_logic121_3d(inout logic121_array_t val); `UPDATE_3D(val); endfunction + + function void e_pack_struct_0d(inout pack_struct_t val); `UPDATE_0D(val); endfunction + function void e_pack_struct_1d(inout pack_struct_t val[2]); `UPDATE_1D(val); endfunction + function void e_pack_struct_2d(inout pack_struct_t val[3][2]); `UPDATE_2D(val); endfunction + function void e_pack_struct_3d(inout pack_struct_array_t val); `UPDATE_3D(val); endfunction + +`ifndef NO_UNPACK_STRUCT + function void e_unpack_struct_0d(inout unpack_struct_t val); + `CHECK_VAL(val.val, 42); + val.val = 43; + endfunction + function void e_unpack_struct_1d(inout unpack_struct_t val[2]); + `CHECK_VAL(val[0].val, 43); + `CHECK_VAL(val[1].val, 44); + val[0].val = 44; + val[1].val = 45; + endfunction + function void e_unpack_struct_2d(inout unpack_struct_t val[3][2]); + `CHECK_VAL(val[0][1].val, 45); + `CHECK_VAL(val[1][1].val, 46); + `CHECK_VAL(val[2][1].val, 47); + val[0][1].val = 46; + val[1][1].val = 47; + val[2][1].val = 48; + endfunction + function void e_unpack_struct_3d(inout unpack_struct_array_t val); + `CHECK_VAL(val[0][0][0].val, 48); + `CHECK_VAL(val[1][0][0].val, 49); + `CHECK_VAL(val[2][0][0].val, 50); + `CHECK_VAL(val[3][0][0].val, 51); + val[0][0][0].val = 49; + val[1][0][0].val = 50; + val[2][0][0].val = 51; + val[3][0][0].val = 52; + endfunction +`endif + + //====================================================================== + // Invoke all imported functions + //====================================================================== + + import "DPI-C" context function void check_exports(); + initial begin + byte_t byte_array_0d; + byte_t byte_array_1d[2]; + byte_t byte_array_2d[3][2]; + byte_array_t byte_array; + byte_unsigned_t byte_unsigned_array_0d; + byte_unsigned_t byte_unsigned_array_1d[2]; + byte_unsigned_t byte_unsigned_array_2d[3][2]; + byte_unsigned_array_t byte_unsigned_array; + shortint_t shortint_array_0d; + shortint_t shortint_array_1d[2]; + shortint_t shortint_array_2d[3][2]; + shortint_array_t shortint_array; + shortint_unsigned_t shortint_unsigned_array_0d; + shortint_unsigned_t shortint_unsigned_array_1d[2]; + shortint_unsigned_t shortint_unsigned_array_2d[3][2]; + shortint_unsigned_array_t shortint_unsigned_array; + int_t int_array_0d; + int_t int_array_1d[2]; + int_t int_array_2d[3][2]; + int_array_t int_array; + int_unsigned_t int_unsigned_array_0d; + int_unsigned_t int_unsigned_array_1d[2]; + int_unsigned_t int_unsigned_array_2d[3][2]; + int_unsigned_array_t int_unsigned_array; + longint_t longint_array_0d; + longint_t longint_array_1d[2]; + longint_t longint_array_2d[3][2]; + longint_array_t longint_array; + longint_unsigned_t longint_unsigned_array_0d; + longint_unsigned_t longint_unsigned_array_1d[2]; + longint_unsigned_t longint_unsigned_array_2d[3][2]; + longint_unsigned_array_t longint_unsigned_array; +`ifndef NO_TIME + time_t time_array_0d; + time_t time_array_1d[2]; + time_t time_array_2d[3][2]; + time_array_t time_array; +`endif +`ifndef NO_INTEGER + integer_t integer_array_0d; + integer_t integer_array_1d[2]; + integer_t integer_array_2d[3][2]; + integer_array_t integer_array; +`endif + real_t real_array_0d; + real_t real_array_1d[2]; + real_t real_array_2d[3][2]; + real_array_t real_array; +`ifndef NO_SHORTREAL + shortreal_t shortreal_array_0d; + shortreal_t shortreal_array_1d[2]; + shortreal_t shortreal_array_2d[3][2]; + shortreal_array_t shortreal_array; +`endif + chandle_t chandle_array_0d; + chandle_t chandle_array_1d[2]; + chandle_t chandle_array_2d[3][2]; + chandle_array_t chandle_array; + + string_t string_array_0d; + string_t string_array_1d[2]; + string_t string_array_2d[3][2]; + string_array_t string_array; + + bit7_t bit7_array_0d; + bit7_t bit7_array_1d[2]; + bit7_t bit7_array_2d[3][2]; + bit7_array_t bit7_array; + + bit121_t bit121_array_0d; + bit121_t bit121_array_1d[2]; + bit121_t bit121_array_2d[3][2]; + bit121_array_t bit121_array; + + logic7_t logic7_array_0d; + logic7_t logic7_array_1d[2]; + logic7_t logic7_array_2d[3][2]; + logic7_array_t logic7_array; + + logic121_t logic121_array_0d; + logic121_t logic121_array_1d[2]; + logic121_t logic121_array_2d[3][2]; + logic121_array_t logic121_array; + + pack_struct_t pack_struct_array_0d; + pack_struct_t pack_struct_array_1d[2]; + pack_struct_t pack_struct_array_2d[3][2]; + pack_struct_array_t pack_struct_array; + +`ifndef NO_UNPACK_STRUCT + unpack_struct_t unpack_struct_array_0d; + unpack_struct_t unpack_struct_array_1d[2]; + unpack_struct_t unpack_struct_array_2d[3][2]; + unpack_struct_array_t unpack_struct_array; +`endif + + `SET_VALUES(byte_array); + `SET_VALUE_0D(byte_array_0d); + `SET_VALUE_1D(byte_array_1d); + `SET_VALUE_2D(byte_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_byte_0d(byte_array[3][2][1]); + `CHECK_0D(byte_array[3][2][1]); + i_byte_1d(byte_array[2][1]); + `CHECK_1D(byte_array[2][1]); + i_byte_2d(byte_array[1]); + `CHECK_2D(byte_array[1]); +`endif + i_byte_0d(byte_array_0d); + `CHECK_0D(byte_array_0d); + i_byte_1d(byte_array_1d); + `CHECK_1D(byte_array_1d); + i_byte_2d(byte_array_2d); + `CHECK_2D(byte_array_2d); + i_byte_3d(byte_array); + `CHECK_3D(byte_array); + + `SET_VALUES(byte_unsigned_array); + `SET_VALUE_0D(byte_unsigned_array_0d); + `SET_VALUE_1D(byte_unsigned_array_1d); + `SET_VALUE_2D(byte_unsigned_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_byte_unsigned_0d(byte_unsigned_array[3][2][1]); + `CHECK_0D(byte_unsigned_array[3][2][1]); + i_byte_unsigned_1d(byte_unsigned_array[2][1]); + `CHECK_1D(byte_unsigned_array[2][1]); + i_byte_unsigned_2d(byte_unsigned_array[1]); + `CHECK_2D(byte_unsigned_array[1]); +`endif + i_byte_unsigned_0d(byte_unsigned_array_0d); + `CHECK_0D(byte_unsigned_array_0d); + i_byte_unsigned_1d(byte_unsigned_array_1d); + `CHECK_1D(byte_unsigned_array_1d); + i_byte_unsigned_2d(byte_unsigned_array_2d); + `CHECK_2D(byte_unsigned_array_2d); + i_byte_unsigned_3d(byte_unsigned_array); + `CHECK_3D(byte_unsigned_array); + + `SET_VALUES(shortint_array); + `SET_VALUE_0D(shortint_array_0d); + `SET_VALUE_1D(shortint_array_1d); + `SET_VALUE_2D(shortint_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_shortint_0d(shortint_array[3][2][1]); + `CHECK_0D(shortint_array[3][2][1]); + i_shortint_1d(shortint_array[2][1]); + `CHECK_1D(shortint_array[2][1]); + i_shortint_2d(shortint_array[1]); + `CHECK_2D(shortint_array[1]); +`endif + i_shortint_0d(shortint_array_0d); + `CHECK_0D(shortint_array_0d); + i_shortint_1d(shortint_array_1d); + `CHECK_1D(shortint_array_1d); + i_shortint_2d(shortint_array_2d); + `CHECK_2D(shortint_array_2d); + i_shortint_3d(shortint_array); + `CHECK_3D(shortint_array); + + `SET_VALUES(shortint_unsigned_array); + `SET_VALUE_0D(shortint_unsigned_array_0d); + `SET_VALUE_1D(shortint_unsigned_array_1d); + `SET_VALUE_2D(shortint_unsigned_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_shortint_unsigned_0d(shortint_unsigned_array[3][2][1]); + `CHECK_0D(shortint_unsigned_array[3][2][1]); + i_shortint_unsigned_1d(shortint_unsigned_array[2][1]); + `CHECK_1D(shortint_unsigned_array[2][1]); + i_shortint_unsigned_2d(shortint_unsigned_array[1]); + `CHECK_2D(shortint_unsigned_array[1]); +`endif + i_shortint_unsigned_0d(shortint_unsigned_array_0d); + `CHECK_0D(shortint_unsigned_array_0d); + i_shortint_unsigned_1d(shortint_unsigned_array_1d); + `CHECK_1D(shortint_unsigned_array_1d); + i_shortint_unsigned_2d(shortint_unsigned_array_2d); + `CHECK_2D(shortint_unsigned_array_2d); + i_shortint_unsigned_3d(shortint_unsigned_array); + `CHECK_3D(shortint_unsigned_array); + + `SET_VALUES(int_array); + `SET_VALUE_0D(int_array_0d); + `SET_VALUE_1D(int_array_1d); + `SET_VALUE_2D(int_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_int_0d(int_array[3][2][1]); + `CHECK_0D(int_array[3][2][1]); + i_int_1d(int_array[2][1]); + `CHECK_1D(int_array[2][1]); + i_int_2d(int_array[1]); + `CHECK_2D(int_array[1]); +`endif + i_int_0d(int_array_0d); + `CHECK_0D(int_array_0d); + i_int_1d(int_array_1d); + `CHECK_1D(int_array_1d); + i_int_2d(int_array_2d); + `CHECK_2D(int_array_2d); + i_int_3d(int_array); + `CHECK_3D(int_array); + + `SET_VALUES(int_unsigned_array); + `SET_VALUE_0D(int_unsigned_array_0d); + `SET_VALUE_1D(int_unsigned_array_1d); + `SET_VALUE_2D(int_unsigned_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_int_unsigned_0d(int_unsigned_array[3][2][1]); + `CHECK_0D(int_unsigned_array[3][2][1]); + i_int_unsigned_1d(int_unsigned_array[2][1]); + `CHECK_1D(int_unsigned_array[2][1]); + i_int_unsigned_2d(int_unsigned_array[1]); + `CHECK_2D(int_unsigned_array[1]); +`endif + i_int_unsigned_0d(int_unsigned_array_0d); + `CHECK_0D(int_unsigned_array_0d); + i_int_unsigned_1d(int_unsigned_array_1d); + `CHECK_1D(int_unsigned_array_1d); + i_int_unsigned_2d(int_unsigned_array_2d); + `CHECK_2D(int_unsigned_array_2d); + i_int_unsigned_3d(int_unsigned_array); + `CHECK_3D(int_unsigned_array); + + `SET_VALUES(longint_array); + `SET_VALUE_0D(longint_array_0d); + `SET_VALUE_1D(longint_array_1d); + `SET_VALUE_2D(longint_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_longint_0d(longint_array[3][2][1]); + `CHECK_0D(longint_array[3][2][1]); + i_longint_1d(longint_array[2][1]); + `CHECK_1D(longint_array[2][1]); + i_longint_2d(longint_array[1]); + `CHECK_2D(longint_array[1]); +`endif + i_longint_0d(longint_array_0d); + `CHECK_0D(longint_array_0d); + i_longint_1d(longint_array_1d); + `CHECK_1D(longint_array_1d); + i_longint_2d(longint_array_2d); + `CHECK_2D(longint_array_2d); + i_longint_3d(longint_array); + `CHECK_3D(longint_array); + + `SET_VALUES(longint_unsigned_array); + `SET_VALUE_0D(longint_unsigned_array_0d); + `SET_VALUE_1D(longint_unsigned_array_1d); + `SET_VALUE_2D(longint_unsigned_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_longint_unsigned_0d(longint_unsigned_array[3][2][1]); + `CHECK_0D(longint_unsigned_array[3][2][1]); + i_longint_unsigned_1d(longint_unsigned_array[2][1]); + `CHECK_1D(longint_unsigned_array[2][1]); + i_longint_unsigned_2d(longint_unsigned_array[1]); + `CHECK_2D(longint_unsigned_array[1]); +`endif + i_longint_unsigned_0d(longint_unsigned_array_0d); + `CHECK_0D(longint_unsigned_array_0d); + i_longint_unsigned_1d(longint_unsigned_array_1d); + `CHECK_1D(longint_unsigned_array_1d); + i_longint_unsigned_2d(longint_unsigned_array_2d); + `CHECK_2D(longint_unsigned_array_2d); + i_longint_unsigned_3d(longint_unsigned_array); + `CHECK_3D(longint_unsigned_array); + +`ifndef NO_TIME + `SET_VALUES(time_array); + `SET_VALUE_0D(time_array_0d); + `SET_VALUE_1D(time_array_1d); + `SET_VALUE_2D(time_array_2d); + `ifndef NO_INOUT_COMPLEX_TYPE + i_time_0d(time_array[3][2][1]); + `CHECK_0D(time_array[3][2][1]); + i_time_1d(time_array[2][1]); + `CHECK_1D(time_array[2][1]); + i_time_2d(time_array[1]); + `CHECK_2D(time_array[1]); + `endif + i_time_0d(time_array_0d); + `CHECK_0D(time_array_0d); + i_time_1d(time_array_1d); + `CHECK_1D(time_array_1d); + i_time_2d(time_array_2d); + `CHECK_2D(time_array_2d); + i_time_3d(time_array); + `CHECK_3D(time_array); +`endif + +`ifndef NO_INTEGER + `SET_VALUES(integer_array); + `SET_VALUE_0D(integer_array_0d); + `SET_VALUE_1D(integer_array_1d); + `SET_VALUE_2D(integer_array_2d); + `ifndef NO_INOUT_COMPLEX_TYPE + i_integer_0d(integer_array[3][2][1]); + `CHECK_0D(integer_array[3][2][1]); + i_integer_1d(integer_array[2][1]); + `CHECK_1D(integer_array[2][1]); + i_integer_2d(integer_array[1]); + `CHECK_2D(integer_array[1]); + `endif + i_integer_0d(integer_array_0d); + `CHECK_0D(integer_array_0d); + i_integer_1d(integer_array_1d); + `CHECK_1D(integer_array_1d); + i_integer_2d(integer_array_2d); + `CHECK_2D(integer_array_2d); + i_integer_3d(integer_array); + `CHECK_3D(integer_array); +`endif + + `SET_VALUES(real_array); + `SET_VALUE_0D(real_array_0d); + `SET_VALUE_1D(real_array_1d); + `SET_VALUE_2D(real_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_real_0d(real_array[3][2][1]); + `CHECK_DOUBLE_0D(real_array[3][2][1]); + i_real_1d(real_array[2][1]); + `CHECK_DOUBLE_1D(real_array[2][1]); + i_real_2d(real_array[1]); + `CHECK_DOUBLE_2D(real_array[1]); +`endif + i_real_0d(real_array_0d); + `CHECK_DOUBLE_0D(real_array_0d); + i_real_1d(real_array_1d); + `CHECK_DOUBLE_1D(real_array_1d); + i_real_2d(real_array_2d); + `CHECK_DOUBLE_2D(real_array_2d); + i_real_3d(real_array); + `CHECK_DOUBLE_3D(real_array); + +`ifndef NO_SHORTREAL + `SET_VALUES(shortreal_array); + `SET_VALUE_0D(shortreal_array_0d); + `SET_VALUE_1D(shortreal_array_1d); + `SET_VALUE_2D(shortreal_array_2d); + `ifndef NO_INOUT_COMPLEX_TYPE + i_shortreal_0d(shortreal_array[3][2][1]); + `CHECK_DOUBLE_0D(shortreal_array[3][2][1]); + i_shortreal_1d(shortreal_array[2][1]); + `CHECK_DOUBLE_1D(shortreal_array[2][1]); + i_shortreal_2d(shortreal_array[1]); + `CHECK_DOUBLE_2D(shortreal_array[1]); + `endif + i_shortreal_0d(shortreal_array_0d); + `CHECK_DOUBLE_0D(shortreal_array_0d); + i_shortreal_1d(shortreal_array_1d); + `CHECK_DOUBLE_1D(shortreal_array_1d); + i_shortreal_2d(shortreal_array_2d); + `CHECK_DOUBLE_2D(shortreal_array_2d); + i_shortreal_3d(shortreal_array); + `CHECK_DOUBLE_3D(shortreal_array); +`endif + + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) + chandle_array[i][j][k] = null; +`ifndef NO_INOUT_COMPLEX_TYPE + i_chandle_0d(chandle_array[3][2][1]); + `CHECK_CHANDLE_VAL(chandle_array[3][2][1], get_non_null()); + i_chandle_1d(chandle_array[2][1]); + `CHECK_CHANDLE_VAL(chandle_array[2][1][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[2][1][1], get_non_null()); + i_chandle_2d(chandle_array[1]); + `CHECK_CHANDLE_VAL(chandle_array[1][0][1], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[1][1][1], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[1][2][1], get_non_null()); +`endif + chandle_array_0d = null; + i_chandle_0d(chandle_array_0d); + `CHECK_CHANDLE_VAL(chandle_array_0d, get_non_null()); + chandle_array_1d[0] = null; + chandle_array_1d[1] = null; + i_chandle_1d(chandle_array_1d); + `CHECK_CHANDLE_VAL(chandle_array_1d[0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array_1d[1], get_non_null()); + chandle_array_2d[0][1] = null; + chandle_array_2d[1][1] = null; + chandle_array_2d[2][1] = null; + i_chandle_2d(chandle_array_2d); + `CHECK_CHANDLE_VAL(chandle_array_2d[0][1], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array_2d[1][1], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array_2d[2][1], get_non_null()); + i_chandle_3d(chandle_array); + `CHECK_CHANDLE_VAL(chandle_array[0][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[1][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[2][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[3][0][0], get_non_null()); + +`ifndef NO_INOUT_COMPLEX_TYPE + string_array[3][2][1] = "42"; + i_string_0d(string_array[3][2][1]); + `CHECK_STRING_VAL(string_array[3][2][1], "43"); + + string_array[2][1][0] = "43"; + string_array[2][1][1] = "44"; + i_string_1d(string_array[2][1]); + `CHECK_STRING_VAL(string_array[2][1][0], "44"); + `CHECK_STRING_VAL(string_array[2][1][1], "45"); + + string_array[1][0][1] = "45"; + string_array[1][1][1] = "46"; + string_array[1][2][1] = "47"; + i_string_2d(string_array[1]); + `CHECK_STRING_VAL(string_array[1][0][1], "46"); + `CHECK_STRING_VAL(string_array[1][1][1], "47"); + `CHECK_STRING_VAL(string_array[1][2][1], "48"); +`endif + string_array_0d = "42"; + i_string_0d(string_array_0d); + `CHECK_STRING_VAL(string_array_0d, "43"); + string_array_1d[0] = "43"; + string_array_1d[1] = "44"; + i_string_1d(string_array_1d); + `CHECK_STRING_VAL(string_array_1d[0], "44"); + `CHECK_STRING_VAL(string_array_1d[1], "45"); + + string_array_2d[0][1] = "45"; + string_array_2d[1][1] = "46"; + string_array_2d[2][1] = "47"; + i_string_2d(string_array_2d); + `CHECK_STRING_VAL(string_array_2d[0][1], "46"); + `CHECK_STRING_VAL(string_array_2d[1][1], "47"); + `CHECK_STRING_VAL(string_array_2d[2][1], "48"); + + string_array[0][0][0] = "48"; + string_array[1][0][0] = "49"; + string_array[2][0][0] = "50"; + string_array[3][0][0] = "51"; + i_string_3d(string_array); + `CHECK_STRING_VAL(string_array[0][0][0], "49"); + `CHECK_STRING_VAL(string_array[1][0][0], "50"); + `CHECK_STRING_VAL(string_array[2][0][0], "51"); + `CHECK_STRING_VAL(string_array[3][0][0], "52"); + + `SET_VALUES(bit7_array); + `SET_VALUE_0D(bit7_array_0d); + `SET_VALUE_1D(bit7_array_1d); + `SET_VALUE_2D(bit7_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_bit7_0d(bit7_array[3][2][1]); + `CHECK_0D(bit7_array[3][2][1]); + i_bit7_1d(bit7_array[2][1]); + `CHECK_1D(bit7_array[2][1]); + i_bit7_2d(bit7_array[1]); + `CHECK_2D(bit7_array[1]); +`endif + i_bit7_0d(bit7_array_0d); + `CHECK_0D(bit7_array_0d); + i_bit7_1d(bit7_array_1d); + `CHECK_1D(bit7_array_1d); + i_bit7_2d(bit7_array_2d); + `CHECK_2D(bit7_array_2d); + i_bit7_3d(bit7_array); + `CHECK_3D(bit7_array); + + `SET_VALUES(bit121_array); + `SET_VALUE_0D(bit121_array_0d); + `SET_VALUE_1D(bit121_array_1d); + `SET_VALUE_2D(bit121_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_bit121_0d(bit121_array[3][2][1]); + `CHECK_0D(bit121_array[3][2][1]); + i_bit121_1d(bit121_array[2][1]); + `CHECK_1D(bit121_array[2][1]); + i_bit121_2d(bit121_array[1]); + `CHECK_2D(bit121_array[1]); +`endif + i_bit121_0d(bit121_array_0d); + `CHECK_0D(bit121_array_0d); + i_bit121_1d(bit121_array_1d); + `CHECK_1D(bit121_array_1d); + i_bit121_2d(bit121_array_2d); + `CHECK_2D(bit121_array_2d); + i_bit121_3d(bit121_array); + `CHECK_3D(bit121_array); + + `SET_VALUES(logic7_array); + `SET_VALUE_0D(logic7_array_0d); + `SET_VALUE_1D(logic7_array_1d); + `SET_VALUE_2D(logic7_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_logic7_0d(logic7_array[3][2][1]); + `CHECK_0D(logic7_array[3][2][1]); + i_logic7_1d(logic7_array[2][1]); + `CHECK_1D(logic7_array[2][1]); + i_logic7_2d(logic7_array[1]); + `CHECK_2D(logic7_array[1]); +`endif + i_logic7_0d(logic7_array_0d); + `CHECK_0D(logic7_array_0d); + i_logic7_1d(logic7_array_1d); + `CHECK_1D(logic7_array_1d); + i_logic7_2d(logic7_array_2d); + `CHECK_2D(logic7_array_2d); + i_logic7_3d(logic7_array); + `CHECK_3D(logic7_array); + + `SET_VALUES(logic121_array); + `SET_VALUE_0D(logic121_array_0d); + `SET_VALUE_1D(logic121_array_1d); + `SET_VALUE_2D(logic121_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_logic121_0d(logic121_array[3][2][1]); + `CHECK_0D(logic121_array[3][2][1]); + i_logic121_1d(logic121_array[2][1]); + `CHECK_1D(logic121_array[2][1]); + i_logic121_2d(logic121_array[1]); + `CHECK_2D(logic121_array[1]); +`endif + i_logic121_0d(logic121_array_0d); + `CHECK_0D(logic121_array_0d); + i_logic121_1d(logic121_array_1d); + `CHECK_1D(logic121_array_1d); + i_logic121_2d(logic121_array_2d); + `CHECK_2D(logic121_array_2d); + i_logic121_3d(logic121_array); + `CHECK_3D(logic121_array); + + `SET_VALUES(pack_struct_array); + `SET_VALUE_0D(pack_struct_array_0d); + `SET_VALUE_1D(pack_struct_array_1d); + `SET_VALUE_2D(pack_struct_array_2d); +`ifndef NO_INOUT_COMPLEX_TYPE + i_pack_struct_0d(pack_struct_array[3][2][1]); + `CHECK_0D(pack_struct_array[3][2][1]); + i_pack_struct_1d(pack_struct_array[2][1]); + `CHECK_1D(pack_struct_array[2][1]); + i_pack_struct_2d(pack_struct_array[1]); + `CHECK_2D(pack_struct_array[1]); +`endif + i_pack_struct_0d(pack_struct_array_0d); + `CHECK_0D(pack_struct_array_0d); + i_pack_struct_1d(pack_struct_array_1d); + `CHECK_1D(pack_struct_array_1d); + i_pack_struct_2d(pack_struct_array_2d); + `CHECK_2D(pack_struct_array_2d); + i_pack_struct_3d(pack_struct_array); + `CHECK_3D(pack_struct_array); + +`ifndef NO_UNPACK_STRUCT + unpack_struct_array[3][2][1].val = 42; + i_unpack_struct_0d(unpack_struct_array[3][2][1]); + `CHECK_VAL(unpack_struct_array[3][2][1].val, 43); + + unpack_struct_array[2][1][0].val = 43; + unpack_struct_array[2][1][1].val = 44; + i_unpack_struct_1d(unpack_struct_array[2][1]); + `CHECK_VAL(unpack_struct_array[2][1][0].val, 44); + `CHECK_VAL(unpack_struct_array[2][1][1].val, 45); + + unpack_struct_array[1][0][1].val = 45; + unpack_struct_array[1][1][1].val = 46; + unpack_struct_array[1][2][1].val = 47; + i_unpack_struct_2d(unpack_struct_array[1]); + `CHECK_VAL(unpack_struct_array[1][0][1].val, 46); + `CHECK_VAL(unpack_struct_array[1][1][1].val, 47); + `CHECK_VAL(unpack_struct_array[1][2][1].val, 48); + + unpack_struct_array[0][0][0].val = 48; + unpack_struct_array[1][0][0].val = 49; + unpack_struct_array[2][0][0].val = 50; + unpack_struct_array[3][0][0].val = 51; + i_unpack_struct_3d(unpack_struct_array); + `CHECK_VAL(unpack_struct_array[0][0][0].val, 49); + `CHECK_VAL(unpack_struct_array[1][0][0].val, 50); + `CHECK_VAL(unpack_struct_array[2][0][0].val, 51); + `CHECK_VAL(unpack_struct_array[3][0][0].val, 52); +`endif + + check_exports(); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_dpi_arg_inout_unpack__Dpi.out b/test_regress/t/t_dpi_arg_inout_unpack__Dpi.out new file mode 100644 index 000000000..c525fa429 --- /dev/null +++ b/test_regress/t/t_dpi_arg_inout_unpack__Dpi.out @@ -0,0 +1,313 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Prototypes for DPI import and export functions. +// +// Verilator includes this file in all generated .cpp files that use DPI functions. +// Manually include this file where DPI .c import functions are declared to ensure +// the C functions match the expectations of the DPI imports. + +#include "svdpi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + // DPI EXPORTS + // DPI export at t/t_dpi_arg_inout_unpack.v:529:18 + extern void e_bit121_0d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:530:18 + extern void e_bit121_1d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:531:18 + extern void e_bit121_2d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:532:18 + extern void e_bit121_3d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:524:18 + extern void e_bit7_0d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:525:18 + extern void e_bit7_1d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:526:18 + extern void e_bit7_2d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:527:18 + extern void e_bit7_3d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:395:18 + extern void e_byte_0d(char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:396:18 + extern void e_byte_1d(char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:397:18 + extern void e_byte_2d(char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:398:18 + extern void e_byte_3d(char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:400:18 + extern void e_byte_unsigned_0d(unsigned char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:401:18 + extern void e_byte_unsigned_1d(unsigned char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:402:18 + extern void e_byte_unsigned_2d(unsigned char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:403:18 + extern void e_byte_unsigned_3d(unsigned char* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:465:18 + extern void e_chandle_0d(void** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:469:18 + extern void e_chandle_1d(void** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:475:18 + extern void e_chandle_2d(void** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:483:18 + extern void e_chandle_3d(void** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:416:18 + extern void e_int_0d(int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:417:18 + extern void e_int_1d(int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:418:18 + extern void e_int_2d(int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:419:18 + extern void e_int_3d(int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:421:18 + extern void e_int_unsigned_0d(unsigned int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:422:18 + extern void e_int_unsigned_1d(unsigned int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:423:18 + extern void e_int_unsigned_2d(unsigned int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:424:18 + extern void e_int_unsigned_3d(unsigned int* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:446:18 + extern void e_integer_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:447:18 + extern void e_integer_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:448:18 + extern void e_integer_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:449:18 + extern void e_integer_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:539:18 + extern void e_logic121_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:540:18 + extern void e_logic121_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:541:18 + extern void e_logic121_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:542:18 + extern void e_logic121_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:534:18 + extern void e_logic7_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:535:18 + extern void e_logic7_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:536:18 + extern void e_logic7_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:537:18 + extern void e_logic7_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:428:18 + extern void e_longint_0d(long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:429:18 + extern void e_longint_1d(long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:430:18 + extern void e_longint_2d(long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:431:18 + extern void e_longint_3d(long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:433:18 + extern void e_longint_unsigned_0d(unsigned long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:434:18 + extern void e_longint_unsigned_1d(unsigned long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:435:18 + extern void e_longint_unsigned_2d(unsigned long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:436:18 + extern void e_longint_unsigned_3d(unsigned long long* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:544:18 + extern void e_pack_struct_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:545:18 + extern void e_pack_struct_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:546:18 + extern void e_pack_struct_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:547:18 + extern void e_pack_struct_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:452:18 + extern void e_real_0d(double* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:453:18 + extern void e_real_1d(double* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:454:18 + extern void e_real_2d(double* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:455:18 + extern void e_real_3d(double* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:405:18 + extern void e_shortint_0d(short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:406:18 + extern void e_shortint_1d(short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:407:18 + extern void e_shortint_2d(short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:408:18 + extern void e_shortint_3d(short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:410:18 + extern void e_shortint_unsigned_0d(unsigned short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:411:18 + extern void e_shortint_unsigned_1d(unsigned short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:412:18 + extern void e_shortint_unsigned_2d(unsigned short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:413:18 + extern void e_shortint_unsigned_3d(unsigned short* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:495:18 + extern void e_string_0d(const char** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:499:18 + extern void e_string_1d(const char** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:505:18 + extern void e_string_2d(const char** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:513:18 + extern void e_string_3d(const char** val); + // DPI export at t/t_dpi_arg_inout_unpack.v:439:18 + extern void e_time_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:440:18 + extern void e_time_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:441:18 + extern void e_time_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_inout_unpack.v:442:18 + extern void e_time_3d(svLogicVecVal* val); + + // DPI IMPORTS + // DPI import at t/t_dpi_arg_inout_unpack.v:584:41 + extern void check_exports(); + // DPI import at t/t_dpi_arg_inout_unpack.v:171:36 + extern void* get_non_null(); + // DPI import at t/t_dpi_arg_inout_unpack.v:254:33 + extern void i_bit121_0d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:255:33 + extern void i_bit121_1d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:256:33 + extern void i_bit121_2d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:257:33 + extern void i_bit121_3d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:249:33 + extern void i_bit7_0d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:250:33 + extern void i_bit7_1d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:251:33 + extern void i_bit7_2d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:252:33 + extern void i_bit7_3d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:173:33 + extern void i_byte_0d(char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:174:33 + extern void i_byte_1d(char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:175:33 + extern void i_byte_2d(char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:176:33 + extern void i_byte_3d(char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:178:33 + extern void i_byte_unsigned_0d(unsigned char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:179:33 + extern void i_byte_unsigned_1d(unsigned char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:180:33 + extern void i_byte_unsigned_2d(unsigned char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:181:33 + extern void i_byte_unsigned_3d(unsigned char* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:239:33 + extern void i_chandle_0d(void** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:240:33 + extern void i_chandle_1d(void** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:241:33 + extern void i_chandle_2d(void** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:242:33 + extern void i_chandle_3d(void** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:193:33 + extern void i_int_0d(int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:194:33 + extern void i_int_1d(int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:195:33 + extern void i_int_2d(int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:196:33 + extern void i_int_3d(int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:198:33 + extern void i_int_unsigned_0d(unsigned int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:199:33 + extern void i_int_unsigned_1d(unsigned int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:200:33 + extern void i_int_unsigned_2d(unsigned int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:201:33 + extern void i_int_unsigned_3d(unsigned int* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:221:33 + extern void i_integer_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:222:33 + extern void i_integer_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:223:33 + extern void i_integer_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:224:33 + extern void i_integer_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:264:33 + extern void i_logic121_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:265:33 + extern void i_logic121_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:266:33 + extern void i_logic121_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:267:33 + extern void i_logic121_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:259:33 + extern void i_logic7_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:260:33 + extern void i_logic7_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:261:33 + extern void i_logic7_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:262:33 + extern void i_logic7_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:203:33 + extern void i_longint_0d(long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:204:33 + extern void i_longint_1d(long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:205:33 + extern void i_longint_2d(long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:206:33 + extern void i_longint_3d(long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:208:33 + extern void i_longint_unsigned_0d(unsigned long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:209:33 + extern void i_longint_unsigned_1d(unsigned long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:210:33 + extern void i_longint_unsigned_2d(unsigned long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:211:33 + extern void i_longint_unsigned_3d(unsigned long long* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:269:33 + extern void i_pack_struct_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:270:33 + extern void i_pack_struct_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:271:33 + extern void i_pack_struct_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:272:33 + extern void i_pack_struct_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:227:33 + extern void i_real_0d(double* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:228:33 + extern void i_real_1d(double* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:229:33 + extern void i_real_2d(double* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:230:33 + extern void i_real_3d(double* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:183:33 + extern void i_shortint_0d(short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:184:33 + extern void i_shortint_1d(short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:185:33 + extern void i_shortint_2d(short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:186:33 + extern void i_shortint_3d(short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:188:33 + extern void i_shortint_unsigned_0d(unsigned short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:189:33 + extern void i_shortint_unsigned_1d(unsigned short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:190:33 + extern void i_shortint_unsigned_2d(unsigned short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:191:33 + extern void i_shortint_unsigned_3d(unsigned short* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:244:33 + extern void i_string_0d(const char** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:245:33 + extern void i_string_1d(const char** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:246:33 + extern void i_string_2d(const char** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:247:33 + extern void i_string_3d(const char** val); + // DPI import at t/t_dpi_arg_inout_unpack.v:214:33 + extern void i_time_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:215:33 + extern void i_time_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:216:33 + extern void i_time_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_inout_unpack.v:217:33 + extern void i_time_3d(svLogicVecVal* val); + +#ifdef __cplusplus +} +#endif diff --git a/test_regress/t/t_dpi_arg_input_unpack.cpp b/test_regress/t/t_dpi_arg_input_unpack.cpp new file mode 100644 index 000000000..695cedc6c --- /dev/null +++ b/test_regress/t/t_dpi_arg_input_unpack.cpp @@ -0,0 +1,778 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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 +// +//************************************************************************* + +#include +#include +#include +#include +#include + +// clang-format off +#if defined(NCSC) +// Used by NC's svdpi.h to pick up svLogicVecVal with _.aval and _.bval fields, +// rather than the IEEE 1800-2005 version which has _.a and _.b fields. +# define DPI_COMPATIBILITY_VERSION_1800v2012 +#endif + +#include "svdpi.h" + +#if defined(VERILATOR) // Verilator +# include "Vt_dpi_arg_input_unpack__Dpi.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +typedef const void** sv_chandle_array_ptr_t; +# define NO_SHORTREAL +# define NO_UNPACK_STRUCT +# define CONSTARG const +#elif defined(VCS) // VCS +# include "../vc_hdrs.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +typedef void** sv_chandle_array_ptr_t; +# define NO_TIME +# define CONSTARG const +#elif defined(NCSC) // NC +# include "dpi-exp.h" +# include "dpi-imp.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +typedef void** sv_chandle_array_ptr_t; +# define NO_TIME +# define NO_INTEGER +# define NO_SHORTREAL +// Sadly NC does not declare pass-by reference input arguments as const +# define CONSTARG +#elif defined(MS) // ModelSim +# include "dpi.h" +typedef int64_t sv_longint_t; +typedef uint64_t sv_longint_unsigned_t; +typedef const void** sv_chandle_array_ptr_t; +# define CONSTARG const +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +//====================================================================== +// Implementations of imported functions +//====================================================================== + +namespace { // unnamed namespace + +const bool VERBOSE_MESSAGE = false; + +#define stop() \ + do { \ + printf(__FILE__ ":%d Bad value\n", __LINE__); \ + abort(); \ + } while (0) + +template bool compare(const T& act, const T& exp) { + if (exp == act) { + if (VERBOSE_MESSAGE) { std::cout << "OK Exp:" << exp << " actual:" << act << std::endl; } + return true; + } else { + std::cout << "NG Exp:" << exp << " actual:" << act << std::endl; + return false; + } +} + +bool compare(const svLogicVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + const bool act_bit = svGetBitselLogic(v0, i); + const bool exp_bit = (i < 64) ? ((val >> i) & 1) : false; + if (act_bit != exp_bit) { + std::cout << "Mismatch at bit:" << i << " exp:" << exp_bit << " act:" << act_bit; + return false; + } + } + if (VERBOSE_MESSAGE) { + std::cout << "OK " << val << " as expected (width:" << bitwidth << ")" << std::endl; + } + return true; +} + +bool compare(const svBitVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + const bool act_bit = svGetBitselBit(v0, i); + const bool exp_bit = (i < 64) ? ((val >> i) & 1) : false; + if (act_bit != exp_bit) { + std::cout << "Mismatch at bit:" << i << " exp:" << exp_bit << " act:" << act_bit; + return false; + } + } + if (VERBOSE_MESSAGE) { + std::cout << "OK " << val << " as expected (width:" << bitwidth << ")" << std::endl; + } + return true; +} + +template bool check_0d(T v) { return compare(v, 42); } +template bool check_1d(const T* v) { + return compare(v[0], 43) && compare(v[1], 44); +} +template bool check_2d(const T* v) { + return compare(v[0 * 2 + 1], 45) && compare(v[1 * 2 + 1], 46) + && compare(v[2 * 2 + 1], 47); +} +template bool check_3d(const T* v) { + return compare(v[(0 * 3 + 0) * 2 + 0], 48) && compare(v[(1 * 3 + 0) * 2 + 0], 49) + && compare(v[(2 * 3 + 0) * 2 + 0], 50) && compare(v[(3 * 3 + 0) * 2 + 0], 51); +} + +bool check_0d(const svLogicVecVal* v, int bitwidth) { return compare(v, 42, bitwidth); } +bool check_1d(const svLogicVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + return compare(v + unit * 0, 43, bitwidth) && compare(v + unit * 1, 44, bitwidth); +} +bool check_2d(const svLogicVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + return compare(v + unit * (0 * 2 + 1), 45, bitwidth) + && compare(v + unit * (1 * 2 + 1), 46, bitwidth) + && compare(v + unit * (2 * 2 + 1), 47, bitwidth); +} +bool check_3d(const svLogicVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + return compare(v + unit * ((0 * 3 + 0) * 2 + 0), 48, bitwidth) + && compare(v + unit * ((1 * 3 + 0) * 2 + 0), 49, bitwidth) + && compare(v + unit * ((2 * 3 + 0) * 2 + 0), 50, bitwidth) + && compare(v + unit * ((3 * 3 + 0) * 2 + 0), 51, bitwidth); +} + +bool check_0d(const svBitVecVal* v, int bitwidth) { return compare(v, 42, bitwidth); } +bool check_1d(const svBitVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + return compare(v + unit * 0, 43, bitwidth) && compare(v + unit * 1, 44, bitwidth); +} +bool check_2d(const svBitVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + return compare(v + unit * (0 * 2 + 1), 45, bitwidth) + && compare(v + unit * (1 * 2 + 1), 46, bitwidth) + && compare(v + unit * (2 * 2 + 1), 47, bitwidth); +} +bool check_3d(const svBitVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + return compare(v + unit * ((0 * 3 + 0) * 2 + 0), 48, bitwidth) + && compare(v + unit * ((1 * 3 + 0) * 2 + 0), 49, bitwidth) + && compare(v + unit * ((2 * 3 + 0) * 2 + 0), 50, bitwidth) + && compare(v + unit * ((3 * 3 + 0) * 2 + 0), 51, bitwidth); +} + +bool check_0d(const char* v) { return compare(v, "42"); } +bool check_1d(const char** v) { + return compare(v[0], "43") && compare(v[1], "44"); +} +bool check_2d(const char** v) { + return compare(v[0 * 2 + 1], "45") && compare(v[1 * 2 + 1], "46") + && compare(v[2 * 2 + 1], "47"); +} +bool check_3d(const char** v) { + return compare(v[(0 * 3 + 0) * 2 + 0], "48") + && compare(v[(1 * 3 + 0) * 2 + 0], "49") + && compare(v[(2 * 3 + 0) * 2 + 0], "50") + && compare(v[(3 * 3 + 0) * 2 + 0], "51"); +} + +template void set_values(T (&v)[4][3][2]) { + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) v[i][j][k] = 0; + v[3][2][1] = 42; + v[2][1][0] = 43; + v[2][1][1] = 44; + v[1][0][1] = 45; + v[1][1][1] = 46; + v[1][2][1] = 47; + v[0][0][0] = 48; + v[1][0][0] = 49; + v[2][0][0] = 50; + v[3][0][0] = 51; +} + +void set_uint(svLogicVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + if (i < 64) + svPutBitselLogic(v0, i, (val >> i) & 1); + else + svPutBitselLogic(v0, i, 0); + } +} + +void set_uint(svBitVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + if (i < 64) + svPutBitselBit(v0, i, (val >> i) & 1); + else + svPutBitselBit(v0, i, 0); + } +} + +template void set_values(svLogicVecVal (&v)[4][3][2][N], int bitwidth) { + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) set_uint(v[i][j][k], 0, bitwidth); + set_uint(v[3][2][1], 42, bitwidth); + + set_uint(v[2][1][0], 43, bitwidth); + set_uint(v[2][1][1], 44, bitwidth); + + set_uint(v[1][0][1], 45, bitwidth); + set_uint(v[1][1][1], 46, bitwidth); + set_uint(v[1][2][1], 47, bitwidth); + + set_uint(v[0][0][0], 48, bitwidth); + set_uint(v[1][0][0], 49, bitwidth); + set_uint(v[2][0][0], 50, bitwidth); + set_uint(v[3][0][0], 51, bitwidth); +} + +template void set_values(svBitVecVal (&v)[4][3][2][N], int bitwidth) { + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) set_uint(v[i][j][k], 0, bitwidth); + set_uint(v[3][2][1], 42, bitwidth); + + set_uint(v[2][1][0], 43, bitwidth); + set_uint(v[2][1][1], 44, bitwidth); + + set_uint(v[1][0][1], 45, bitwidth); + set_uint(v[1][1][1], 46, bitwidth); + set_uint(v[1][2][1], 47, bitwidth); + + set_uint(v[0][0][0], 48, bitwidth); + set_uint(v[1][0][0], 49, bitwidth); + set_uint(v[2][0][0], 50, bitwidth); + set_uint(v[3][0][0], 51, bitwidth); +} + +sv_chandle_array_ptr_t add_const(void** ptr) { + return static_cast(static_cast(ptr)); +} + +} // unnamed namespace + +void* get_non_null() { + static int v; + return &v; +} + +void i_byte_0d(char v) { + if (!check_0d(v)) stop(); +} +void i_byte_1d(const char* v) { + if (!check_1d(v)) stop(); +} +void i_byte_2d(const char* v) { + if (!check_2d(v)) stop(); +} +void i_byte_3d(const char* v) { + if (!check_3d(v)) stop(); +} + +void i_byte_unsigned_0d(unsigned char v) { + if (!check_0d(v)) stop(); +} +void i_byte_unsigned_1d(const unsigned char* v) { + if (!check_1d(v)) stop(); +} +void i_byte_unsigned_2d(const unsigned char* v) { + if (!check_2d(v)) stop(); +} +void i_byte_unsigned_3d(const unsigned char* v) { + if (!check_3d(v)) stop(); +} + +void i_shortint_0d(short v) { + if (!check_0d(v)) stop(); +} +void i_shortint_1d(const short* v) { + if (!check_1d(v)) stop(); +} +void i_shortint_2d(const short* v) { + if (!check_2d(v)) stop(); +} +void i_shortint_3d(const short* v) { + if (!check_3d(v)) stop(); +} + +void i_shortint_unsigned_0d(unsigned short v) { + if (!check_0d(v)) stop(); +} +void i_shortint_unsigned_1d(const unsigned short* v) { + if (!check_1d(v)) stop(); +} +void i_shortint_unsigned_2d(const unsigned short* v) { + if (!check_2d(v)) stop(); +} +void i_shortint_unsigned_3d(const unsigned short* v) { + if (!check_3d(v)) stop(); +} + +void i_int_0d(int v) { + if (!check_0d(v)) stop(); +} +void i_int_1d(const int* v) { + if (!check_1d(v)) stop(); +} +void i_int_2d(const int* v) { + if (!check_2d(v)) stop(); +} +void i_int_3d(const int* v) { + if (!check_3d(v)) stop(); +} + +void i_int_unsigned_0d(unsigned v) { + if (!check_0d(v)) stop(); +} +void i_int_unsigned_1d(const unsigned* v) { + if (!check_1d(v)) stop(); +} +void i_int_unsigned_2d(const unsigned* v) { + if (!check_2d(v)) stop(); +} +void i_int_unsigned_3d(const unsigned* v) { + if (!check_3d(v)) stop(); +} + +void i_longint_0d(sv_longint_t v) { + if (!check_0d(v)) stop(); +} +void i_longint_1d(const sv_longint_t* v) { + if (!check_1d(v)) stop(); +} +void i_longint_2d(const sv_longint_t* v) { + if (!check_2d(v)) stop(); +} +void i_longint_3d(const sv_longint_t* v) { + if (!check_3d(v)) stop(); +} + +void i_longint_unsigned_0d(sv_longint_unsigned_t v) { + if (!check_0d(v)) stop(); +} +void i_longint_unsigned_1d(const sv_longint_unsigned_t* v) { + if (!check_1d(v)) stop(); +} +void i_longint_unsigned_2d(const sv_longint_unsigned_t* v) { + if (!check_2d(v)) stop(); +} +void i_longint_unsigned_3d(const sv_longint_unsigned_t* v) { + if (!check_3d(v)) stop(); +} + +#ifndef NO_TIME +void i_time_0d(CONSTARG svLogicVecVal* v) { + if (!check_0d(v, 64)) stop(); +} +void i_time_1d(CONSTARG svLogicVecVal* v) { + if (!check_1d(v, 64)) stop(); +} +void i_time_2d(CONSTARG svLogicVecVal* v) { + if (!check_2d(v, 64)) stop(); +} +void i_time_3d(CONSTARG svLogicVecVal* v) { + if (!check_3d(v, 64)) stop(); +} +#endif + +#ifndef NO_INTEGER +void i_integer_0d(CONSTARG svLogicVecVal* v) { + if (!check_0d(v, 32)) stop(); +} +void i_integer_1d(CONSTARG svLogicVecVal* v) { + if (!check_1d(v, 32)) stop(); +} +void i_integer_2d(CONSTARG svLogicVecVal* v) { + if (!check_2d(v, 32)) stop(); +} +void i_integer_3d(CONSTARG svLogicVecVal* v) { + if (!check_3d(v, 32)) stop(); +} +#endif + +void i_real_0d(double v) { + if (!check_0d(v)) stop(); +} +void i_real_1d(CONSTARG double* v) { + if (!check_1d(v)) stop(); +} +void i_real_2d(CONSTARG double* v) { + if (!check_2d(v)) stop(); +} +void i_real_3d(CONSTARG double* v) { + if (!check_3d(v)) stop(); +} + +#ifndef NO_SHORTREAL +void i_shortreal_0d(float v) { + if (!check_0d(v)) stop(); +} +void i_shortreal_1d(CONSTARG float* v) { + if (!check_1d(v)) stop(); +} +void i_shortreal_2d(CONSTARG float* v) { + if (!check_2d(v)) stop(); +} +void i_shortreal_3d(CONSTARG float* v) { + if (!check_3d(v)) stop(); +} +#endif + +void i_chandle_0d(void* v) { + if (!v) stop(); +} +void i_chandle_1d(sv_chandle_array_ptr_t v) { + if (!v[0]) stop(); + if (!v[1]) stop(); +} +void i_chandle_2d(sv_chandle_array_ptr_t v) { + if (!v[2 * 0 + 1]) stop(); + if (!v[2 * 1 + 1]) stop(); + if (!v[2 * 2 + 1]) stop(); +} +void i_chandle_3d(sv_chandle_array_ptr_t v) { + if (!v[(0 * 3 + 0) * 2 + 0]) stop(); + if (!v[(1 * 3 + 0) * 2 + 0]) stop(); + if (!v[(2 * 3 + 0) * 2 + 0]) stop(); + if (!v[(3 * 3 + 0) * 2 + 0]) stop(); +} + +void i_string_0d(CONSTARG char* v) { + if (!check_0d(v)) stop(); +} +void i_string_1d(CONSTARG char** v) { + if (!check_1d(v)) stop(); +} +void i_string_2d(CONSTARG char** v) { + if (!check_2d(v)) stop(); +} +void i_string_3d(CONSTARG char** v) { + if (!check_3d(v)) stop(); +} + +void i_bit7_0d(CONSTARG svBitVecVal* v) { + if (!check_0d(v, 7)) stop(); +} +void i_bit7_1d(CONSTARG svBitVecVal* v) { + if (!check_1d(v, 7)) stop(); +} +void i_bit7_2d(CONSTARG svBitVecVal* v) { + if (!check_2d(v, 7)) stop(); +} +void i_bit7_3d(CONSTARG svBitVecVal* v) { + if (!check_3d(v, 7)) stop(); +} + +void i_bit121_0d(CONSTARG svBitVecVal* v) { + if (!check_0d(v, 121)) stop(); +} +void i_bit121_1d(CONSTARG svBitVecVal* v) { + if (!check_1d(v, 121)) stop(); +} +void i_bit121_2d(CONSTARG svBitVecVal* v) { + if (!check_2d(v, 121)) stop(); +} +void i_bit121_3d(CONSTARG svBitVecVal* v) { + if (!check_3d(v, 121)) stop(); +} + +void i_logic7_0d(CONSTARG svLogicVecVal* v) { + if (!check_0d(v, 7)) stop(); +} +void i_logic7_1d(CONSTARG svLogicVecVal* v) { + if (!check_1d(v, 7)) stop(); +} +void i_logic7_2d(CONSTARG svLogicVecVal* v) { + if (!check_2d(v, 7)) stop(); +} +void i_logic7_3d(CONSTARG svLogicVecVal* v) { + if (!check_3d(v, 7)) stop(); +} + +void i_logic121_0d(CONSTARG svLogicVecVal* v) { + if (!check_0d(v, 121)) stop(); +} +void i_logic121_1d(CONSTARG svLogicVecVal* v) { + if (!check_1d(v, 121)) stop(); +} +void i_logic121_2d(CONSTARG svLogicVecVal* v) { + if (!check_2d(v, 121)) stop(); +} +void i_logic121_3d(CONSTARG svLogicVecVal* v) { + if (!check_3d(v, 121)) stop(); +} + +void i_pack_struct_0d(CONSTARG svLogicVecVal* v) { + if (!check_0d(v, 7)) stop(); +} +void i_pack_struct_1d(CONSTARG svLogicVecVal* v) { + if (!check_1d(v, 7)) stop(); +} +void i_pack_struct_2d(CONSTARG svLogicVecVal* v) { + if (!check_2d(v, 7)) stop(); +} +void i_pack_struct_3d(CONSTARG svLogicVecVal* v) { + if (!check_3d(v, 7)) stop(); +} + +#ifndef NO_UNPACK_STRUCT +void i_unpack_struct_0d(CONSTARG unpack_struct_t* v) { + if (!compare(v->val, 42, 121)) stop(); +} +void i_unpack_struct_1d(CONSTARG unpack_struct_t* v) { + if (!compare(v[0].val, 43, 121)) stop(); + if (!compare(v[1].val, 44, 121)) stop(); +} +void i_unpack_struct_2d(CONSTARG unpack_struct_t* v) { + if (!compare(v[0 * 2 + 1].val, 45, 121)) stop(); + if (!compare(v[1 * 2 + 1].val, 46, 121)) stop(); + if (!compare(v[2 * 2 + 1].val, 47, 121)) stop(); +} +void i_unpack_struct_3d(CONSTARG unpack_struct_t* v) { + if (!compare(v[(0 * 3 + 0) * 2 + 0].val, 48, 121)) stop(); + if (!compare(v[(1 * 3 + 0) * 2 + 0].val, 49, 121)) stop(); + if (!compare(v[(2 * 3 + 0) * 2 + 0].val, 50, 121)) stop(); + if (!compare(v[(3 * 3 + 0) * 2 + 0].val, 51, 121)) stop(); +} +#endif + +void check_exports() { + { + char byte_array[4][3][2]; + set_values(byte_array); + e_byte_0d(byte_array[3][2][1]); + e_byte_1d(&byte_array[2][1][0]); + e_byte_2d(&byte_array[1][0][0]); + e_byte_3d(&byte_array[0][0][0]); + } + { + unsigned char byte_unsigned_array[4][3][2]; + set_values(byte_unsigned_array); + e_byte_unsigned_0d(byte_unsigned_array[3][2][1]); + e_byte_unsigned_1d(&byte_unsigned_array[2][1][0]); + e_byte_unsigned_2d(&byte_unsigned_array[1][0][0]); + e_byte_unsigned_3d(&byte_unsigned_array[0][0][0]); + } + { + short shortint_array[4][3][2]; + set_values(shortint_array); + e_shortint_0d(shortint_array[3][2][1]); + e_shortint_1d(&shortint_array[2][1][0]); + e_shortint_2d(&shortint_array[1][0][0]); + e_shortint_3d(&shortint_array[0][0][0]); + } + { + unsigned short shortint_unsigned_array[4][3][2]; + set_values(shortint_unsigned_array); + e_shortint_unsigned_0d(shortint_unsigned_array[3][2][1]); + e_shortint_unsigned_1d(&shortint_unsigned_array[2][1][0]); + e_shortint_unsigned_2d(&shortint_unsigned_array[1][0][0]); + e_shortint_unsigned_3d(&shortint_unsigned_array[0][0][0]); + } + { + int int_array[4][3][2]; + set_values(int_array); + e_int_0d(int_array[3][2][1]); + e_int_1d(&int_array[2][1][0]); + e_int_2d(&int_array[1][0][0]); + e_int_3d(&int_array[0][0][0]); + } + { + unsigned int int_unsigned_array[4][3][2]; + set_values(int_unsigned_array); + e_int_unsigned_0d(int_unsigned_array[3][2][1]); + e_int_unsigned_1d(&int_unsigned_array[2][1][0]); + e_int_unsigned_2d(&int_unsigned_array[1][0][0]); + e_int_unsigned_3d(&int_unsigned_array[0][0][0]); + } + { + sv_longint_t longint_array[4][3][2]; + set_values(longint_array); + e_longint_0d(longint_array[3][2][1]); + e_longint_1d(&longint_array[2][1][0]); + e_longint_2d(&longint_array[1][0][0]); + e_longint_3d(&longint_array[0][0][0]); + } + { + sv_longint_unsigned_t longint_unsigned_array[4][3][2]; + set_values(longint_unsigned_array); + e_longint_unsigned_0d(longint_unsigned_array[3][2][1]); + e_longint_unsigned_1d(&longint_unsigned_array[2][1][0]); + e_longint_unsigned_2d(&longint_unsigned_array[1][0][0]); + e_longint_unsigned_3d(&longint_unsigned_array[0][0][0]); + } +#ifndef NO_TIME + { + svLogicVecVal time_array[4][3][2][2]; + set_values(time_array, 64); + e_time_0d(time_array[3][2][1]); + e_time_1d(time_array[2][1][0]); + e_time_2d(&time_array[1][0][0][0]); + e_time_3d(time_array[0][0][0]); + } +#endif + +#ifndef NO_INTEGER + { + svLogicVecVal integer_array[4][3][2][1]; + set_values(integer_array, 32); + e_integer_0d(integer_array[3][2][1]); + e_integer_1d(integer_array[2][1][0]); + e_integer_2d(&integer_array[1][0][0][0]); + e_integer_3d(integer_array[0][0][0]); + } +#endif + + { + double real_array[4][3][2]; + set_values(real_array); + e_real_0d(real_array[3][2][1]); + e_real_1d(&real_array[2][1][0]); + e_real_2d(&real_array[1][0][0]); + e_real_3d(&real_array[0][0][0]); + } +#ifndef NO_SHORTREAL + { + float shortreal_array[4][3][2]; + set_values(shortreal_array); + e_shortreal_0d(shortreal_array[3][2][1]); + e_shortreal_1d(&shortreal_array[2][1][0]); + e_shortreal_2d(&shortreal_array[1][0][0]); + e_shortreal_3d(&shortreal_array[0][0][0]); + } +#endif + + { + void* chandle_array[4][3][2]; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) chandle_array[i][j][k] = NULL; + chandle_array[3][2][1] = get_non_null(); + chandle_array[2][1][0] = get_non_null(); + chandle_array[2][1][1] = get_non_null(); + + chandle_array[1][0][1] = get_non_null(); + chandle_array[1][1][1] = get_non_null(); + chandle_array[1][2][1] = get_non_null(); + + chandle_array[0][0][0] = get_non_null(); + chandle_array[1][0][0] = get_non_null(); + chandle_array[2][0][0] = get_non_null(); + chandle_array[3][0][0] = get_non_null(); + + e_chandle_0d(chandle_array[3][2][1]); + e_chandle_1d(add_const(&chandle_array[2][1][0])); + e_chandle_2d(add_const(&chandle_array[1][0][0])); + e_chandle_3d(add_const(&chandle_array[0][0][0])); + } + + { + std::vector buf; + buf.resize(4 * 3 * 2 * 16, '\0'); + buf[((3 * 3 + 2) * 2 + 1) * 16 + 0] = '4'; + buf[((3 * 3 + 2) * 2 + 1) * 16 + 1] = '2'; + buf[((2 * 3 + 1) * 2 + 0) * 16 + 0] = '4'; + buf[((2 * 3 + 1) * 2 + 0) * 16 + 1] = '3'; + buf[((2 * 3 + 1) * 2 + 1) * 16 + 0] = '4'; + buf[((2 * 3 + 1) * 2 + 1) * 16 + 1] = '4'; + buf[((1 * 3 + 0) * 2 + 1) * 16 + 0] = '4'; + buf[((1 * 3 + 0) * 2 + 1) * 16 + 1] = '5'; + buf[((1 * 3 + 1) * 2 + 1) * 16 + 0] = '4'; + buf[((1 * 3 + 1) * 2 + 1) * 16 + 1] = '6'; + buf[((1 * 3 + 2) * 2 + 1) * 16 + 0] = '4'; + buf[((1 * 3 + 2) * 2 + 1) * 16 + 1] = '7'; + buf[((0 * 3 + 0) * 2 + 0) * 16 + 0] = '4'; + buf[((0 * 3 + 0) * 2 + 0) * 16 + 1] = '8'; + buf[((1 * 3 + 0) * 2 + 0) * 16 + 0] = '4'; + buf[((1 * 3 + 0) * 2 + 0) * 16 + 1] = '9'; + buf[((2 * 3 + 0) * 2 + 0) * 16 + 0] = '5'; + buf[((2 * 3 + 0) * 2 + 0) * 16 + 1] = '0'; + buf[((3 * 3 + 0) * 2 + 0) * 16 + 0] = '5'; + buf[((3 * 3 + 0) * 2 + 0) * 16 + 1] = '1'; + const char* string_array[4][3][2]; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) + string_array[i][j][k] = buf.data() + ((i * 3 + j) * 2 + k) * 16; + e_string_0d(string_array[3][2][1]); + e_string_1d(&string_array[2][1][0]); + e_string_2d(&string_array[1][0][0]); + e_string_3d(&string_array[0][0][0]); + } + + { + svBitVecVal bit7_array[4][3][2][1]; + set_values(bit7_array, 7); + e_bit7_0d(bit7_array[3][2][1]); + e_bit7_1d(bit7_array[2][1][0]); + e_bit7_2d(bit7_array[1][0][0]); + e_bit7_3d(bit7_array[0][0][0]); + } + + { + svBitVecVal bit121_array[4][3][2][4]; + set_values(bit121_array, 121); + e_bit121_0d(bit121_array[3][2][1]); + e_bit121_1d(bit121_array[2][1][0]); + e_bit121_2d(bit121_array[1][0][0]); + e_bit121_3d(bit121_array[0][0][0]); + } + + { + svLogicVecVal logic7_array[4][3][2][1]; + set_values(logic7_array, 7); + e_logic7_0d(logic7_array[3][2][1]); + e_logic7_1d(logic7_array[2][1][0]); + e_logic7_2d(logic7_array[1][0][0]); + e_logic7_3d(logic7_array[0][0][0]); + } + + { + svLogicVecVal logic121_array[4][3][2][4]; + set_values(logic121_array, 121); + e_logic121_0d(logic121_array[3][2][1]); + e_logic121_1d(logic121_array[2][1][0]); + e_logic121_2d(logic121_array[1][0][0]); + e_logic121_3d(logic121_array[0][0][0]); + } + + { + svLogicVecVal pack_struct_array[4][3][2][1]; + set_values(pack_struct_array, 7); + e_pack_struct_0d(pack_struct_array[3][2][1]); + e_pack_struct_1d(pack_struct_array[2][1][0]); + e_pack_struct_2d(pack_struct_array[1][0][0]); + e_pack_struct_3d(pack_struct_array[0][0][0]); + } + +#ifndef NO_UNPACK_STRUCT + { + unpack_struct_t unpack_struct_array[4][3][2]; + set_uint(unpack_struct_array[3][2][1].val, 42, 121); + + set_uint(unpack_struct_array[2][1][0].val, 43, 121); + set_uint(unpack_struct_array[2][1][1].val, 44, 121); + + set_uint(unpack_struct_array[1][0][1].val, 45, 121); + set_uint(unpack_struct_array[1][1][1].val, 46, 121); + set_uint(unpack_struct_array[1][2][1].val, 47, 121); + + set_uint(unpack_struct_array[0][0][0].val, 48, 121); + set_uint(unpack_struct_array[1][0][0].val, 49, 121); + set_uint(unpack_struct_array[2][0][0].val, 50, 121); + set_uint(unpack_struct_array[3][0][0].val, 51, 121); + e_unpack_struct_0d(&unpack_struct_array[3][2][1]); + e_unpack_struct_1d(&unpack_struct_array[2][1][0]); + e_unpack_struct_2d(&unpack_struct_array[1][0][0]); + e_unpack_struct_3d(&unpack_struct_array[0][0][0]); + } +#endif +} diff --git a/test_regress/t/t_dpi_arg_input_unpack.pl b/test_regress/t/t_dpi_arg_input_unpack.pl new file mode 100755 index 000000000..364897b82 --- /dev/null +++ b/test_regress/t/t_dpi_arg_input_unpack.pl @@ -0,0 +1,44 @@ +#!/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 Geza Lore. 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); + +if ($Self->{nc}) { + # For NC, compile twice, first just to generate DPI headers + compile( + nc_flags2 => ["+ncdpiheader+$Self->{obj_dir}/dpi-exp.h", + "+ncdpiimpheader+$Self->{obj_dir}/dpi-imp.h"] + ); +} + +compile( + v_flags2 => ["t/t_dpi_arg_input_unpack.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # NC: Gdd the obj_dir to the C include path + nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], + # ModelSim: Generate DPI header, add obj_dir to the C include path + ms_flags2 => ["-dpiheader $Self->{obj_dir}/dpi.h", + "-ccflags -I$Self->{obj_dir}"], + ); + +if ($Self->{vlt_all}) { + files_identical( + "$Self->{obj_dir}/Vt_dpi_arg_input_unpack__Dpi.h", + "t/t_dpi_arg_input_unpack__Dpi.out" + ); +} + +execute( + check_finished => 1, + ms_pli => 0 + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_arg_input_unpack.v b/test_regress/t/t_dpi_arg_input_unpack.v new file mode 100644 index 000000000..0a698e905 --- /dev/null +++ b/test_regress/t/t_dpi_arg_input_unpack.v @@ -0,0 +1,770 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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 + +`ifdef VCS + `define NO_TIME +`endif + +`ifdef NC + `define NO_TIME + `define NO_INTEGER + `define NO_SHORTREAL +`endif + +`ifdef MS +`endif + +`ifdef VERILATOR + `define NO_SHORTREAL + `define NO_UNPACK_STRUCT + `define NULL 64'd0 +`else + `define NULL null +`endif + +`define CHECK_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ + end else begin \ + $display("Mismatch %s expected:%d actual:%d at %d", `"act`", \ + int'(exp), int'(act), `__LINE__); \ + $stop; \ + end + +`define CHECK_0D(val) `CHECK_VAL((val), 42) +`define CHECK_1D(val) `CHECK_VAL(val[0], 43); \ +`CHECK_VAL(val[1], 44) +`define CHECK_2D(val) `CHECK_VAL(val[0][1], 45); \ +`CHECK_VAL(val[1][1], 46); \ +`CHECK_VAL(val[2][1], 47) +`define CHECK_3D(val) `CHECK_VAL(val[0][0][0], 48); \ +`CHECK_VAL(val[1][0][0], 49); \ +`CHECK_VAL(val[2][0][0], 50); \ +`CHECK_VAL(val[3][0][0], 51) + +`define SET_VALUES(val) \ +val[3][2][1] = 42; \ +val[2][1][0] = 43; val[2][1][1] = 44; \ +val[1][0][1] = 45; val[1][1][1] = 46; val[1][2][1] = 47; \ +val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 + +module t; + + localparam ENABLE_VERBOSE_MESSAGE = 0; + + // Legal input argument types for DPI functions + + //====================================================================== + // Type definitions + //====================================================================== + + typedef byte byte_array_t[4][3][2]; + typedef byte unsigned byte_unsigned_array_t[4][3][2]; + typedef shortint shortint_array_t[4][3][2]; + typedef shortint unsigned shortint_unsigned_array_t[4][3][2]; + typedef int int_array_t[4][3][2]; + typedef int unsigned int_unsigned_array_t[4][3][2]; + typedef longint longint_array_t[4][3][2]; + typedef longint unsigned longint_unsigned_array_t[4][3][2]; +`ifndef NO_TIME + typedef time time_array_t[4][3][2]; +`endif +`ifndef NO_INTEGER + typedef integer integer_array_t[4][3][2]; +`endif + typedef real real_array_t[4][3][2]; +`ifndef NO_SHORTREAL + typedef shortreal shortreal_array_t[4][3][2]; +`endif + typedef chandle chandle_array_t[4][3][2]; + typedef string string_array_t[4][3][2]; + typedef bit [6:0] bit7_array_t[4][3][2]; + typedef bit [120:0] bit121_array_t[4][3][2]; + typedef logic [6:0] logic7_array_t[4][3][2]; + typedef logic [120:0] logic121_array_t[4][3][2]; + + typedef struct packed { + logic [6:0] val; + } pack_struct_t; + typedef pack_struct_t pack_struct_array_t[4][3][2]; +`ifndef NO_UNPACK_STRUCT + typedef struct { + logic [120:0] val; + } unpack_struct_t; + typedef unpack_struct_t unpack_struct_array_t[4][3][2]; +`endif + + //====================================================================== + // Imports + //====================================================================== + + // Returns non-null pointer + import "DPI-C" function chandle get_non_null(); + + import "DPI-C" function void i_byte_0d(input byte val); + import "DPI-C" function void i_byte_1d(input byte val[2]); + import "DPI-C" function void i_byte_2d(input byte val[3][2]); + import "DPI-C" function void i_byte_3d(input byte_array_t val); + + import "DPI-C" function void i_byte_unsigned_0d(input byte unsigned val); + import "DPI-C" function void i_byte_unsigned_1d(input byte unsigned val[2]); + import "DPI-C" function void i_byte_unsigned_2d(input byte unsigned val[3][2]); + import "DPI-C" function void i_byte_unsigned_3d(input byte_unsigned_array_t val); + + import "DPI-C" function void i_shortint_0d(input shortint val); + import "DPI-C" function void i_shortint_1d(input shortint val[2]); + import "DPI-C" function void i_shortint_2d(input shortint val[3][2]); + import "DPI-C" function void i_shortint_3d(input shortint_array_t val); + + import "DPI-C" function void i_shortint_unsigned_0d(input shortint unsigned val); + import "DPI-C" function void i_shortint_unsigned_1d(input shortint unsigned val[2]); + import "DPI-C" function void i_shortint_unsigned_2d(input shortint unsigned val[3][2]); + import "DPI-C" function void i_shortint_unsigned_3d(input shortint_unsigned_array_t val); + + import "DPI-C" function void i_int_0d(input int val); + import "DPI-C" function void i_int_1d(input int val[2]); + import "DPI-C" function void i_int_2d(input int val[3][2]); + import "DPI-C" function void i_int_3d(input int_array_t val); + + import "DPI-C" function void i_int_unsigned_0d(input int unsigned val); + import "DPI-C" function void i_int_unsigned_1d(input int unsigned val[2]); + import "DPI-C" function void i_int_unsigned_2d(input int unsigned val[3][2]); + import "DPI-C" function void i_int_unsigned_3d(input int_unsigned_array_t val); + + import "DPI-C" function void i_longint_0d(input longint val); + import "DPI-C" function void i_longint_1d(input longint val[2]); + import "DPI-C" function void i_longint_2d(input longint val[3][2]); + import "DPI-C" function void i_longint_3d(input longint_array_t val); + + import "DPI-C" function void i_longint_unsigned_0d(input longint unsigned val); + import "DPI-C" function void i_longint_unsigned_1d(input longint unsigned val[2]); + import "DPI-C" function void i_longint_unsigned_2d(input longint unsigned val[3][2]); + import "DPI-C" function void i_longint_unsigned_3d(input longint_unsigned_array_t val); + +`ifndef NO_TIME + import "DPI-C" function void i_time_0d(input time val); + import "DPI-C" function void i_time_1d(input time val[2]); + import "DPI-C" function void i_time_2d(input time val[3][2]); + import "DPI-C" function void i_time_3d(input time_array_t val); +`endif + +`ifndef NO_INTEGER + import "DPI-C" function void i_integer_0d(input integer val); + import "DPI-C" function void i_integer_1d(input integer val[2]); + import "DPI-C" function void i_integer_2d(input integer val[3][2]); + import "DPI-C" function void i_integer_3d(input integer_array_t val); +`endif + + import "DPI-C" function void i_real_0d(input real val); + import "DPI-C" function void i_real_1d(input real val[2]); + import "DPI-C" function void i_real_2d(input real val[3][2]); + import "DPI-C" function void i_real_3d(input real_array_t val); + +`ifndef NO_SHORTREAL + import "DPI-C" function void i_shortreal_0d(input shortreal val); + import "DPI-C" function void i_shortreal_1d(input shortreal val[2]); + import "DPI-C" function void i_shortreal_2d(input shortreal val[3][2]); + import "DPI-C" function void i_shortreal_3d(input shortreal_array_t val); +`endif + + import "DPI-C" function void i_chandle_0d(input chandle val); + import "DPI-C" function void i_chandle_1d(input chandle val[2]); + import "DPI-C" function void i_chandle_2d(input chandle val[3][2]); + import "DPI-C" function void i_chandle_3d(input chandle_array_t val); + + import "DPI-C" function void i_string_0d(input string val); + import "DPI-C" function void i_string_1d(input string val[2]); + import "DPI-C" function void i_string_2d(input string val[3][2]); + import "DPI-C" function void i_string_3d(input string_array_t val); + + import "DPI-C" function void i_bit7_0d(input bit[6:0] val); + import "DPI-C" function void i_bit7_1d(input bit[6:0] val[2]); + import "DPI-C" function void i_bit7_2d(input bit[6:0] val[3][2]); + import "DPI-C" function void i_bit7_3d(input bit7_array_t val); + + import "DPI-C" function void i_bit121_0d(input bit[120:0] val); + import "DPI-C" function void i_bit121_1d(input bit[120:0] val[2]); + import "DPI-C" function void i_bit121_2d(input bit[120:0] val[3][2]); + import "DPI-C" function void i_bit121_3d(input bit121_array_t val); + + import "DPI-C" function void i_logic7_0d(input logic[6:0] val); + import "DPI-C" function void i_logic7_1d(input logic[6:0] val[2]); + import "DPI-C" function void i_logic7_2d(input logic[6:0] val[3][2]); + import "DPI-C" function void i_logic7_3d(input logic7_array_t val); + + import "DPI-C" function void i_logic121_0d(input logic[120:0] val); + import "DPI-C" function void i_logic121_1d(input logic[120:0] val[2]); + import "DPI-C" function void i_logic121_2d(input logic[120:0] val[3][2]); + import "DPI-C" function void i_logic121_3d(input logic121_array_t val); + + import "DPI-C" function void i_pack_struct_0d(input pack_struct_t val); + import "DPI-C" function void i_pack_struct_1d(input pack_struct_t val[2]); + import "DPI-C" function void i_pack_struct_2d(input pack_struct_t val[3][2]); + import "DPI-C" function void i_pack_struct_3d(input pack_struct_array_t val); + +`ifndef NO_UNPACK_STRUCT + import "DPI-C" function void i_unpack_struct_0d(input unpack_struct_t val); + import "DPI-C" function void i_unpack_struct_1d(input unpack_struct_t val[2]); + import "DPI-C" function void i_unpack_struct_2d(input unpack_struct_t val[3][2]); + import "DPI-C" function void i_unpack_struct_3d(input unpack_struct_array_t val); +`endif + + + //====================================================================== + // Exports + //====================================================================== + + export "DPI-C" function e_byte_0d; + export "DPI-C" function e_byte_1d; + export "DPI-C" function e_byte_2d; + export "DPI-C" function e_byte_3d; + + export "DPI-C" function e_byte_unsigned_0d; + export "DPI-C" function e_byte_unsigned_1d; + export "DPI-C" function e_byte_unsigned_2d; + export "DPI-C" function e_byte_unsigned_3d; + + export "DPI-C" function e_shortint_0d; + export "DPI-C" function e_shortint_1d; + export "DPI-C" function e_shortint_2d; + export "DPI-C" function e_shortint_3d; + + export "DPI-C" function e_shortint_unsigned_0d; + export "DPI-C" function e_shortint_unsigned_1d; + export "DPI-C" function e_shortint_unsigned_2d; + export "DPI-C" function e_shortint_unsigned_3d; + + export "DPI-C" function e_int_0d; + export "DPI-C" function e_int_1d; + export "DPI-C" function e_int_2d; + export "DPI-C" function e_int_3d; + + export "DPI-C" function e_int_unsigned_0d; + export "DPI-C" function e_int_unsigned_1d; + export "DPI-C" function e_int_unsigned_2d; + export "DPI-C" function e_int_unsigned_3d; + + export "DPI-C" function e_longint_0d; + export "DPI-C" function e_longint_1d; + export "DPI-C" function e_longint_2d; + export "DPI-C" function e_longint_3d; + + export "DPI-C" function e_longint_unsigned_0d; + export "DPI-C" function e_longint_unsigned_1d; + export "DPI-C" function e_longint_unsigned_2d; + export "DPI-C" function e_longint_unsigned_3d; + +`ifndef NO_TIME + export "DPI-C" function e_time_0d; + export "DPI-C" function e_time_1d; + export "DPI-C" function e_time_2d; + export "DPI-C" function e_time_3d; +`endif + +`ifndef NO_INTEGER + export "DPI-C" function e_integer_0d; + export "DPI-C" function e_integer_1d; + export "DPI-C" function e_integer_2d; + export "DPI-C" function e_integer_3d; +`endif + + export "DPI-C" function e_real_0d; + export "DPI-C" function e_real_1d; + export "DPI-C" function e_real_2d; + export "DPI-C" function e_real_3d; + +`ifndef NO_SHORTREAL + export "DPI-C" function e_shortreal_0d; + export "DPI-C" function e_shortreal_1d; + export "DPI-C" function e_shortreal_2d; + export "DPI-C" function e_shortreal_3d; +`endif + + export "DPI-C" function e_chandle_0d; + export "DPI-C" function e_chandle_1d; + export "DPI-C" function e_chandle_2d; + export "DPI-C" function e_chandle_3d; + + export "DPI-C" function e_string_0d; + export "DPI-C" function e_string_1d; + export "DPI-C" function e_string_2d; + export "DPI-C" function e_string_3d; + + export "DPI-C" function e_bit7_0d; + export "DPI-C" function e_bit7_1d; + export "DPI-C" function e_bit7_2d; + export "DPI-C" function e_bit7_3d; + + export "DPI-C" function e_bit121_0d; + export "DPI-C" function e_bit121_1d; + export "DPI-C" function e_bit121_2d; + export "DPI-C" function e_bit121_3d; + + export "DPI-C" function e_logic7_0d; + export "DPI-C" function e_logic7_1d; + export "DPI-C" function e_logic7_2d; + export "DPI-C" function e_logic7_3d; + + export "DPI-C" function e_logic121_0d; + export "DPI-C" function e_logic121_1d; + export "DPI-C" function e_logic121_2d; + export "DPI-C" function e_logic121_3d; + + export "DPI-C" function e_pack_struct_0d; + export "DPI-C" function e_pack_struct_1d; + export "DPI-C" function e_pack_struct_2d; + export "DPI-C" function e_pack_struct_3d; + +`ifndef NO_UNPACK_STRUCT + export "DPI-C" function e_unpack_struct_0d; + export "DPI-C" function e_unpack_struct_1d; + export "DPI-C" function e_unpack_struct_2d; + export "DPI-C" function e_unpack_struct_3d; +`endif + + //====================================================================== + // Definitions of exported functions + //====================================================================== + function void e_byte_0d(input byte val); `CHECK_0D(val); endfunction + function void e_byte_1d(input byte val[2]); `CHECK_1D(val); endfunction + function void e_byte_2d(input byte val[3][2]); `CHECK_2D(val); endfunction + function void e_byte_3d(input byte_array_t val); `CHECK_3D(val); endfunction + + function void e_byte_unsigned_0d(input byte unsigned val); `CHECK_0D(val); endfunction + function void e_byte_unsigned_1d(input byte unsigned val[2]); `CHECK_1D(val); endfunction + function void e_byte_unsigned_2d(input byte unsigned val[3][2]); `CHECK_2D(val); endfunction + function void e_byte_unsigned_3d(input byte_unsigned_array_t val); `CHECK_3D(val); endfunction + + function void e_shortint_0d(input shortint val); `CHECK_0D(val); endfunction + function void e_shortint_1d(input shortint val[2]); `CHECK_1D(val); endfunction + function void e_shortint_2d(input shortint val[3][2]); `CHECK_2D(val); endfunction + function void e_shortint_3d(input shortint_array_t val); `CHECK_3D(val); endfunction + + function void e_shortint_unsigned_0d(input shortint unsigned val); `CHECK_0D(val); endfunction + function void e_shortint_unsigned_1d(input shortint unsigned val[2]); `CHECK_1D(val); endfunction + function void e_shortint_unsigned_2d(input shortint unsigned val[3][2]); `CHECK_2D(val); endfunction + function void e_shortint_unsigned_3d(input shortint_unsigned_array_t val); `CHECK_3D(val); endfunction + + function void e_int_0d(input int val); `CHECK_0D(val); endfunction + function void e_int_1d(input int val[2]); `CHECK_1D(val); endfunction + function void e_int_2d(input int val[3][2]); `CHECK_2D(val); endfunction + function void e_int_3d(input int_array_t val); `CHECK_3D(val); endfunction + + function void e_int_unsigned_0d(input int unsigned val); `CHECK_0D(val); endfunction + function void e_int_unsigned_1d(input int unsigned val[2]); `CHECK_1D(val); endfunction + function void e_int_unsigned_2d(input int unsigned val[3][2]); `CHECK_2D(val); endfunction + function void e_int_unsigned_3d(input int_unsigned_array_t val); `CHECK_3D(val); endfunction + + function void e_longint_0d(input longint val); `CHECK_0D(val); endfunction + function void e_longint_1d(input longint val[2]); `CHECK_1D(val); endfunction + function void e_longint_2d(input longint val[3][2]); `CHECK_2D(val); endfunction + function void e_longint_3d(input longint_array_t val); `CHECK_3D(val); endfunction + + function void e_longint_unsigned_0d(input longint unsigned val); `CHECK_0D(val); endfunction + function void e_longint_unsigned_1d(input longint unsigned val[2]); `CHECK_1D(val); endfunction + function void e_longint_unsigned_2d(input longint unsigned val[3][2]); `CHECK_2D(val); endfunction + function void e_longint_unsigned_3d(input longint_unsigned_array_t val); `CHECK_3D(val); endfunction + +`ifndef NO_TIME + function void e_time_0d(input time val); `CHECK_0D(val); endfunction + function void e_time_1d(input time val[2]); `CHECK_1D(val); endfunction + function void e_time_2d(input time val[3][2]); `CHECK_2D(val); endfunction + function void e_time_3d(input time_array_t val); `CHECK_3D(val); endfunction +`endif + +`ifndef NO_INTEGER + function void e_integer_0d(input integer val); `CHECK_0D(val); endfunction + function void e_integer_1d(input integer val[2]); `CHECK_1D(val); endfunction + function void e_integer_2d(input integer val[3][2]); `CHECK_2D(val); endfunction + function void e_integer_3d(input integer_array_t val); `CHECK_3D(val); endfunction +`endif + + function void e_real_0d(input real val); `CHECK_0D(val); endfunction + function void e_real_1d(input real val[2]); `CHECK_1D(val); endfunction + function void e_real_2d(input real val[3][2]); `CHECK_2D(val); endfunction + function void e_real_3d(input real_array_t val); `CHECK_3D(val); endfunction + +`ifndef NO_SHORTREAL + function void e_shortreal_0d(input shortreal val); `CHECK_0D(val); endfunction + function void e_shortreal_1d(input shortreal val[2]); `CHECK_1D(val); endfunction + function void e_shortreal_2d(input shortreal val[3][2]); `CHECK_2D(val); endfunction + function void e_shortreal_3d(input shortreal_array_t val); `CHECK_3D(val); endfunction +`endif + + function void e_chandle_0d(input chandle val); + if (val == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + endfunction + function void e_chandle_1d(input chandle val[2]); + if (val[0] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + if (val[1] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + endfunction + function void e_chandle_2d(input chandle val[3][2]); + if (val[0][1] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + if (val[1][1] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + if (val[2][1] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + endfunction + function void e_chandle_3d(input chandle_array_t val); + if (val[0][0][0] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + if (val[1][0][0] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + if (val[2][0][0] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + if (val[3][0][0] == null) begin + $display("Mismatch non null is expected, but not."); + $stop; + end + endfunction + + function void e_string_0d(input string val); + if (val != "42") begin + $display("Mismatch expected:%s actual:%s", "42", val); + $stop; + end + endfunction + function void e_string_1d(input string val[2]); + if (val[0] != "43") begin + $display("Mismatch expected:%s actual:%s", "43", val[0]); + $stop; + end + if (val[1] != "44") begin + $display("Mismatch expected:%s actual:%s", "44", val[1]); + $stop; + end + endfunction + function void e_string_2d(input string val[3][2]); + if (val[0][1] != "45") begin + $display("Mismatch expected:%s actual:%s", "45", val[0][1]); + $stop; + end + if (val[1][1] != "46") begin + $display("Mismatch expected:%s actual:%s", "46", val[1][1]); + $stop; + end + if (val[2][1] != "47") begin + $display("Mismatch expected:%s actual:%s", "47", val[2][1]); + $stop; + end + endfunction + function void e_string_3d(input string_array_t val); + if (val[0][0][0] != "48") begin + $display("Mismatch expected:%s actual:%s", "48", val[0][0][0]); + $stop; + end + if (val[1][0][0] != "49") begin + $display("Mismatch expected:%s actual:%s", "49", val[1][0][0]); + $stop; + end + if (val[2][0][0] != "50") begin + $display("Mismatch expected:%s actual:%s", "50", val[2][0][0]); + $stop; + end + if (val[3][0][0] != "51") begin + $display("Mismatch expected:%s actual:%s", "51", val[3][0][0]); + $stop; + end + endfunction + + function void e_bit7_0d(input bit[6:0] val); `CHECK_0D(val); endfunction + function void e_bit7_1d(input bit[6:0] val[2]); `CHECK_1D(val); endfunction + function void e_bit7_2d(input bit[6:0] val[3][2]); `CHECK_2D(val); endfunction + function void e_bit7_3d(input bit7_array_t val); `CHECK_3D(val); endfunction + + function void e_bit121_0d(input bit[120:0] val); `CHECK_0D(val); endfunction + function void e_bit121_1d(input bit[120:0] val[2]); `CHECK_1D(val); endfunction + function void e_bit121_2d(input bit[120:0] val[3][2]); `CHECK_2D(val); endfunction + function void e_bit121_3d(input bit121_array_t val); `CHECK_3D(val); endfunction + + function void e_logic7_0d(input logic[6:0] val); `CHECK_0D(val); endfunction + function void e_logic7_1d(input logic[6:0] val[2]); `CHECK_1D(val); endfunction + function void e_logic7_2d(input logic[6:0] val[3][2]); `CHECK_2D(val); endfunction + function void e_logic7_3d(input logic7_array_t val); `CHECK_3D(val); endfunction + + function void e_logic121_0d(input logic[120:0] val); `CHECK_0D(val); endfunction + function void e_logic121_1d(input logic[120:0] val[2]); `CHECK_1D(val); endfunction + function void e_logic121_2d(input logic[120:0] val[3][2]); `CHECK_2D(val); endfunction + function void e_logic121_3d(input logic121_array_t val); `CHECK_3D(val); endfunction + + function void e_pack_struct_0d(input pack_struct_t val); `CHECK_0D(val); endfunction + function void e_pack_struct_1d(input pack_struct_t val[2]); `CHECK_1D(val); endfunction + function void e_pack_struct_2d(input pack_struct_t val[3][2]); `CHECK_2D(val); endfunction + function void e_pack_struct_3d(input pack_struct_array_t val); `CHECK_3D(val); endfunction + +`ifndef NO_UNPACK_STRUCT + function void e_unpack_struct_0d(input unpack_struct_t val); + if (val.val != 42) begin + $display("Mismatch expected:%s actual:%s", "42", val.val); + $stop; + end + endfunction + function void e_unpack_struct_1d(input unpack_struct_t val[2]); + if (val[0].val != 43) begin + $display("Mismatch expected:%s actual:%s", "43", val[0].val); + $stop; + end + if (val[1].val != 44) begin + $display("Mismatch expected:%s actual:%s", "44", val[1].val); + $stop; + end + endfunction + function void e_unpack_struct_2d(input unpack_struct_t val[3][2]); + if (val[0][1].val != 45) begin + $display("Mismatch expected:%s actual:%s", "45", val[0][1].val); + $stop; + end + if (val[1][1].val != 46) begin + $display("Mismatch expected:%s actual:%s", "46", val[1][1].val); + $stop; + end + if (val[2][1].val != 47) begin + $display("Mismatch expected:%s actual:%s", "47", val[2][1].val); + $stop; + end + endfunction + function void e_unpack_struct_3d(input unpack_struct_array_t val); + if (val[0][0][0].val != 48) begin + $display("Mismatch expected:%s actual:%s", "48", val[0][0][0].val); + $stop; + end + if (val[1][0][0].val != 49) begin + $display("Mismatch expected:%s actual:%s", "49", val[1][0][0].val); + $stop; + end + if (val[2][0][0].val != 50) begin + $display("Mismatch expected:%s actual:%s", "50", val[2][0][0].val); + $stop; + end + if (val[3][0][0].val != 51) begin + $display("Mismatch expected:%s actual:%s", "51", val[3][0][0].val); + $stop; + end + endfunction +`endif + + //====================================================================== + // Invoke all imported functions + //====================================================================== + + import "DPI-C" context function void check_exports(); + + initial begin + byte_array_t byte_array; + byte_unsigned_array_t byte_unsigned_array; + shortint_array_t shortint_array; + shortint_unsigned_array_t shortint_unsigned_array; + int_array_t int_array; + int_unsigned_array_t int_unsigned_array; + longint_array_t longint_array; + longint_unsigned_array_t longint_unsigned_array; +`ifndef NO_TIME + time_array_t time_array; +`endif +`ifndef NO_INTEGER + integer_array_t integer_array; +`endif + real_array_t real_array; +`ifndef NO_SHORTREAL + shortreal_array_t shortreal_array; +`endif + chandle_array_t chandle_array; + string_array_t string_array; + bit7_array_t bit7_array; + bit121_array_t bit121_array; + logic7_array_t logic7_array; + logic121_array_t logic121_array; + pack_struct_array_t pack_struct_array; +`ifndef NO_UNPACK_STRUCT + unpack_struct_array_t unpack_struct_array; +`endif + + `SET_VALUES(byte_array); + i_byte_0d(byte_array[3][2][1]); + i_byte_1d(byte_array[2][1]); + i_byte_2d(byte_array[1]); + i_byte_3d(byte_array); + + `SET_VALUES(byte_unsigned_array); + i_byte_unsigned_0d(byte_unsigned_array[3][2][1]); + i_byte_unsigned_1d(byte_unsigned_array[2][1]); + i_byte_unsigned_2d(byte_unsigned_array[1]); + i_byte_unsigned_3d(byte_unsigned_array); + + `SET_VALUES(shortint_array); + i_shortint_0d(shortint_array[3][2][1]); + i_shortint_1d(shortint_array[2][1]); + i_shortint_2d(shortint_array[1]); + i_shortint_3d(shortint_array); + + `SET_VALUES(shortint_unsigned_array); + i_shortint_unsigned_0d(shortint_unsigned_array[3][2][1]); + i_shortint_unsigned_1d(shortint_unsigned_array[2][1]); + i_shortint_unsigned_2d(shortint_unsigned_array[1]); + i_shortint_unsigned_3d(shortint_unsigned_array); + + `SET_VALUES(int_array); + i_int_0d(int_array[3][2][1]); + i_int_1d(int_array[2][1]); + i_int_2d(int_array[1]); + i_int_3d(int_array); + + `SET_VALUES(int_unsigned_array); + i_int_unsigned_0d(int_unsigned_array[3][2][1]); + i_int_unsigned_1d(int_unsigned_array[2][1]); + i_int_unsigned_2d(int_unsigned_array[1]); + i_int_unsigned_3d(int_unsigned_array); + + `SET_VALUES(longint_array); + i_longint_0d(longint_array[3][2][1]); + i_longint_1d(longint_array[2][1]); + i_longint_2d(longint_array[1]); + i_longint_3d(longint_array); + + `SET_VALUES(longint_unsigned_array); + i_longint_unsigned_0d(longint_unsigned_array[3][2][1]); + i_longint_unsigned_1d(longint_unsigned_array[2][1]); + i_longint_unsigned_2d(longint_unsigned_array[1]); + i_longint_unsigned_3d(longint_unsigned_array); + +`ifndef NO_TIME + `SET_VALUES(time_array); + i_time_0d(time_array[3][2][1]); + i_time_1d(time_array[2][1]); + i_time_2d(time_array[1]); + i_time_3d(time_array); +`endif + +`ifndef NO_INTEGER + `SET_VALUES(integer_array); + i_integer_0d(integer_array[3][2][1]); + i_integer_1d(integer_array[2][1]); + i_integer_2d(integer_array[1]); + i_integer_3d(integer_array); +`endif + + `SET_VALUES(real_array); + i_real_0d(real_array[3][2][1]); + i_real_1d(real_array[2][1]); + i_real_2d(real_array[1]); + i_real_3d(real_array); + +`ifndef NO_SHORTREAL + `SET_VALUES(shortreal_array); + i_shortreal_0d(shortreal_array[3][2][1]); + i_shortreal_1d(shortreal_array[2][1]); + i_shortreal_2d(shortreal_array[1]); + i_shortreal_3d(shortreal_array); +`endif + + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) + chandle_array[i][j][k] = null; + + chandle_array[3][2][1] = get_non_null(); + i_chandle_0d(chandle_array[3][2][1]); + chandle_array[2][1][0] = get_non_null(); + chandle_array[2][1][1] = get_non_null(); + i_chandle_1d(chandle_array[2][1]); + chandle_array[1][0][1] = get_non_null(); + chandle_array[1][1][1] = get_non_null(); + chandle_array[1][2][1] = get_non_null(); + i_chandle_2d(chandle_array[1]); + chandle_array[0][0][0] = get_non_null(); + chandle_array[1][0][0] = get_non_null(); + chandle_array[2][0][0] = get_non_null(); + chandle_array[3][0][0] = get_non_null(); + i_chandle_3d(chandle_array); + + string_array[3][2][1] = "42"; + string_array[2][1][0] = "43"; string_array[2][1][1] = "44"; + string_array[1][0][1] = "45"; string_array[1][1][1] = "46"; string_array[1][2][1] = "47"; + string_array[0][0][0] = "48"; string_array[1][0][0] = "49"; string_array[2][0][0] = "50"; string_array[3][0][0] = "51"; + i_string_0d(string_array[3][2][1]); + i_string_1d(string_array[2][1]); + i_string_2d(string_array[1]); + i_string_3d(string_array); + + `SET_VALUES(bit7_array); + i_bit7_0d(bit7_array[3][2][1]); + i_bit7_1d(bit7_array[2][1]); + i_bit7_2d(bit7_array[1]); + i_bit7_3d(bit7_array); + + `SET_VALUES(bit121_array); + i_bit121_0d(bit121_array[3][2][1]); + i_bit121_1d(bit121_array[2][1]); + i_bit121_2d(bit121_array[1]); + i_bit121_3d(bit121_array); + + `SET_VALUES(logic7_array); + i_logic7_0d(logic7_array[3][2][1]); + i_logic7_1d(logic7_array[2][1]); + i_logic7_2d(logic7_array[1]); + i_logic7_3d(logic7_array); + + `SET_VALUES(logic121_array); + i_logic121_0d(logic121_array[3][2][1]); + i_logic121_1d(logic121_array[2][1]); + i_logic121_2d(logic121_array[1]); + i_logic121_3d(logic121_array); + + `SET_VALUES(pack_struct_array); + i_pack_struct_0d(pack_struct_array[3][2][1]); + i_pack_struct_1d(pack_struct_array[2][1]); + i_pack_struct_2d(pack_struct_array[1]); + i_pack_struct_3d(pack_struct_array); + +`ifndef NO_UNPACK_STRUCT + unpack_struct_array[3][2][1].val = 42; + unpack_struct_array[2][1][0].val = 43; + unpack_struct_array[2][1][1].val = 44; + + unpack_struct_array[1][0][1].val = 45; + unpack_struct_array[1][1][1].val = 46; + unpack_struct_array[1][2][1].val = 47; + + unpack_struct_array[0][0][0].val = 48; + unpack_struct_array[1][0][0].val = 49; + unpack_struct_array[2][0][0].val = 50; + unpack_struct_array[3][0][0].val = 51; + i_unpack_struct_0d(unpack_struct_array[3][2][1]); + i_unpack_struct_1d(unpack_struct_array[2][1]); + i_unpack_struct_2d(unpack_struct_array[1]); + i_unpack_struct_3d(unpack_struct_array); +`endif + + check_exports(); + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_dpi_arg_input_unpack__Dpi.out b/test_regress/t/t_dpi_arg_input_unpack__Dpi.out new file mode 100644 index 000000000..dd53f2061 --- /dev/null +++ b/test_regress/t/t_dpi_arg_input_unpack__Dpi.out @@ -0,0 +1,313 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Prototypes for DPI import and export functions. +// +// Verilator includes this file in all generated .cpp files that use DPI functions. +// Manually include this file where DPI .c import functions are declared to ensure +// the C functions match the expectations of the DPI imports. + +#include "svdpi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + // DPI EXPORTS + // DPI export at t/t_dpi_arg_input_unpack.v:501:18 + extern void e_bit121_0d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:502:18 + extern void e_bit121_1d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:503:18 + extern void e_bit121_2d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:504:18 + extern void e_bit121_3d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:496:18 + extern void e_bit7_0d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:497:18 + extern void e_bit7_1d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:498:18 + extern void e_bit7_2d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:499:18 + extern void e_bit7_3d(const svBitVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:332:18 + extern void e_byte_0d(char val); + // DPI export at t/t_dpi_arg_input_unpack.v:333:18 + extern void e_byte_1d(const char* val); + // DPI export at t/t_dpi_arg_input_unpack.v:334:18 + extern void e_byte_2d(const char* val); + // DPI export at t/t_dpi_arg_input_unpack.v:335:18 + extern void e_byte_3d(const char* val); + // DPI export at t/t_dpi_arg_input_unpack.v:337:18 + extern void e_byte_unsigned_0d(unsigned char val); + // DPI export at t/t_dpi_arg_input_unpack.v:338:18 + extern void e_byte_unsigned_1d(const unsigned char* val); + // DPI export at t/t_dpi_arg_input_unpack.v:339:18 + extern void e_byte_unsigned_2d(const unsigned char* val); + // DPI export at t/t_dpi_arg_input_unpack.v:340:18 + extern void e_byte_unsigned_3d(const unsigned char* val); + // DPI export at t/t_dpi_arg_input_unpack.v:398:18 + extern void e_chandle_0d(void* val); + // DPI export at t/t_dpi_arg_input_unpack.v:404:18 + extern void e_chandle_1d(const void** val); + // DPI export at t/t_dpi_arg_input_unpack.v:414:18 + extern void e_chandle_2d(const void** val); + // DPI export at t/t_dpi_arg_input_unpack.v:428:18 + extern void e_chandle_3d(const void** val); + // DPI export at t/t_dpi_arg_input_unpack.v:352:18 + extern void e_int_0d(int val); + // DPI export at t/t_dpi_arg_input_unpack.v:353:18 + extern void e_int_1d(const int* val); + // DPI export at t/t_dpi_arg_input_unpack.v:354:18 + extern void e_int_2d(const int* val); + // DPI export at t/t_dpi_arg_input_unpack.v:355:18 + extern void e_int_3d(const int* val); + // DPI export at t/t_dpi_arg_input_unpack.v:357:18 + extern void e_int_unsigned_0d(unsigned int val); + // DPI export at t/t_dpi_arg_input_unpack.v:358:18 + extern void e_int_unsigned_1d(const unsigned int* val); + // DPI export at t/t_dpi_arg_input_unpack.v:359:18 + extern void e_int_unsigned_2d(const unsigned int* val); + // DPI export at t/t_dpi_arg_input_unpack.v:360:18 + extern void e_int_unsigned_3d(const unsigned int* val); + // DPI export at t/t_dpi_arg_input_unpack.v:380:18 + extern void e_integer_0d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:381:18 + extern void e_integer_1d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:382:18 + extern void e_integer_2d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:383:18 + extern void e_integer_3d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:511:18 + extern void e_logic121_0d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:512:18 + extern void e_logic121_1d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:513:18 + extern void e_logic121_2d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:514:18 + extern void e_logic121_3d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:506:18 + extern void e_logic7_0d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:507:18 + extern void e_logic7_1d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:508:18 + extern void e_logic7_2d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:509:18 + extern void e_logic7_3d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:362:18 + extern void e_longint_0d(long long val); + // DPI export at t/t_dpi_arg_input_unpack.v:363:18 + extern void e_longint_1d(const long long* val); + // DPI export at t/t_dpi_arg_input_unpack.v:364:18 + extern void e_longint_2d(const long long* val); + // DPI export at t/t_dpi_arg_input_unpack.v:365:18 + extern void e_longint_3d(const long long* val); + // DPI export at t/t_dpi_arg_input_unpack.v:367:18 + extern void e_longint_unsigned_0d(unsigned long long val); + // DPI export at t/t_dpi_arg_input_unpack.v:368:18 + extern void e_longint_unsigned_1d(const unsigned long long* val); + // DPI export at t/t_dpi_arg_input_unpack.v:369:18 + extern void e_longint_unsigned_2d(const unsigned long long* val); + // DPI export at t/t_dpi_arg_input_unpack.v:370:18 + extern void e_longint_unsigned_3d(const unsigned long long* val); + // DPI export at t/t_dpi_arg_input_unpack.v:516:18 + extern void e_pack_struct_0d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:517:18 + extern void e_pack_struct_1d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:518:18 + extern void e_pack_struct_2d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:519:18 + extern void e_pack_struct_3d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:386:18 + extern void e_real_0d(double val); + // DPI export at t/t_dpi_arg_input_unpack.v:387:18 + extern void e_real_1d(const double* val); + // DPI export at t/t_dpi_arg_input_unpack.v:388:18 + extern void e_real_2d(const double* val); + // DPI export at t/t_dpi_arg_input_unpack.v:389:18 + extern void e_real_3d(const double* val); + // DPI export at t/t_dpi_arg_input_unpack.v:342:18 + extern void e_shortint_0d(short val); + // DPI export at t/t_dpi_arg_input_unpack.v:343:18 + extern void e_shortint_1d(const short* val); + // DPI export at t/t_dpi_arg_input_unpack.v:344:18 + extern void e_shortint_2d(const short* val); + // DPI export at t/t_dpi_arg_input_unpack.v:345:18 + extern void e_shortint_3d(const short* val); + // DPI export at t/t_dpi_arg_input_unpack.v:347:18 + extern void e_shortint_unsigned_0d(unsigned short val); + // DPI export at t/t_dpi_arg_input_unpack.v:348:18 + extern void e_shortint_unsigned_1d(const unsigned short* val); + // DPI export at t/t_dpi_arg_input_unpack.v:349:18 + extern void e_shortint_unsigned_2d(const unsigned short* val); + // DPI export at t/t_dpi_arg_input_unpack.v:350:18 + extern void e_shortint_unsigned_3d(const unsigned short* val); + // DPI export at t/t_dpi_arg_input_unpack.v:447:18 + extern void e_string_0d(const char* val); + // DPI export at t/t_dpi_arg_input_unpack.v:453:18 + extern void e_string_1d(const char** val); + // DPI export at t/t_dpi_arg_input_unpack.v:463:18 + extern void e_string_2d(const char** val); + // DPI export at t/t_dpi_arg_input_unpack.v:477:18 + extern void e_string_3d(const char** val); + // DPI export at t/t_dpi_arg_input_unpack.v:373:18 + extern void e_time_0d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:374:18 + extern void e_time_1d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:375:18 + extern void e_time_2d(const svLogicVecVal* val); + // DPI export at t/t_dpi_arg_input_unpack.v:376:18 + extern void e_time_3d(const svLogicVecVal* val); + + // DPI IMPORTS + // DPI import at t/t_dpi_arg_input_unpack.v:576:41 + extern void check_exports(); + // DPI import at t/t_dpi_arg_input_unpack.v:106:36 + extern void* get_non_null(); + // DPI import at t/t_dpi_arg_input_unpack.v:189:33 + extern void i_bit121_0d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:190:33 + extern void i_bit121_1d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:191:33 + extern void i_bit121_2d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:192:33 + extern void i_bit121_3d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:184:33 + extern void i_bit7_0d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:185:33 + extern void i_bit7_1d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:186:33 + extern void i_bit7_2d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:187:33 + extern void i_bit7_3d(const svBitVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:108:33 + extern void i_byte_0d(char val); + // DPI import at t/t_dpi_arg_input_unpack.v:109:33 + extern void i_byte_1d(const char* val); + // DPI import at t/t_dpi_arg_input_unpack.v:110:33 + extern void i_byte_2d(const char* val); + // DPI import at t/t_dpi_arg_input_unpack.v:111:33 + extern void i_byte_3d(const char* val); + // DPI import at t/t_dpi_arg_input_unpack.v:113:33 + extern void i_byte_unsigned_0d(unsigned char val); + // DPI import at t/t_dpi_arg_input_unpack.v:114:33 + extern void i_byte_unsigned_1d(const unsigned char* val); + // DPI import at t/t_dpi_arg_input_unpack.v:115:33 + extern void i_byte_unsigned_2d(const unsigned char* val); + // DPI import at t/t_dpi_arg_input_unpack.v:116:33 + extern void i_byte_unsigned_3d(const unsigned char* val); + // DPI import at t/t_dpi_arg_input_unpack.v:174:33 + extern void i_chandle_0d(void* val); + // DPI import at t/t_dpi_arg_input_unpack.v:175:33 + extern void i_chandle_1d(const void** val); + // DPI import at t/t_dpi_arg_input_unpack.v:176:33 + extern void i_chandle_2d(const void** val); + // DPI import at t/t_dpi_arg_input_unpack.v:177:33 + extern void i_chandle_3d(const void** val); + // DPI import at t/t_dpi_arg_input_unpack.v:128:33 + extern void i_int_0d(int val); + // DPI import at t/t_dpi_arg_input_unpack.v:129:33 + extern void i_int_1d(const int* val); + // DPI import at t/t_dpi_arg_input_unpack.v:130:33 + extern void i_int_2d(const int* val); + // DPI import at t/t_dpi_arg_input_unpack.v:131:33 + extern void i_int_3d(const int* val); + // DPI import at t/t_dpi_arg_input_unpack.v:133:33 + extern void i_int_unsigned_0d(unsigned int val); + // DPI import at t/t_dpi_arg_input_unpack.v:134:33 + extern void i_int_unsigned_1d(const unsigned int* val); + // DPI import at t/t_dpi_arg_input_unpack.v:135:33 + extern void i_int_unsigned_2d(const unsigned int* val); + // DPI import at t/t_dpi_arg_input_unpack.v:136:33 + extern void i_int_unsigned_3d(const unsigned int* val); + // DPI import at t/t_dpi_arg_input_unpack.v:156:33 + extern void i_integer_0d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:157:33 + extern void i_integer_1d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:158:33 + extern void i_integer_2d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:159:33 + extern void i_integer_3d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:199:33 + extern void i_logic121_0d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:200:33 + extern void i_logic121_1d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:201:33 + extern void i_logic121_2d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:202:33 + extern void i_logic121_3d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:194:33 + extern void i_logic7_0d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:195:33 + extern void i_logic7_1d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:196:33 + extern void i_logic7_2d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:197:33 + extern void i_logic7_3d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:138:33 + extern void i_longint_0d(long long val); + // DPI import at t/t_dpi_arg_input_unpack.v:139:33 + extern void i_longint_1d(const long long* val); + // DPI import at t/t_dpi_arg_input_unpack.v:140:33 + extern void i_longint_2d(const long long* val); + // DPI import at t/t_dpi_arg_input_unpack.v:141:33 + extern void i_longint_3d(const long long* val); + // DPI import at t/t_dpi_arg_input_unpack.v:143:33 + extern void i_longint_unsigned_0d(unsigned long long val); + // DPI import at t/t_dpi_arg_input_unpack.v:144:33 + extern void i_longint_unsigned_1d(const unsigned long long* val); + // DPI import at t/t_dpi_arg_input_unpack.v:145:33 + extern void i_longint_unsigned_2d(const unsigned long long* val); + // DPI import at t/t_dpi_arg_input_unpack.v:146:33 + extern void i_longint_unsigned_3d(const unsigned long long* val); + // DPI import at t/t_dpi_arg_input_unpack.v:204:33 + extern void i_pack_struct_0d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:205:33 + extern void i_pack_struct_1d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:206:33 + extern void i_pack_struct_2d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:207:33 + extern void i_pack_struct_3d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:162:33 + extern void i_real_0d(double val); + // DPI import at t/t_dpi_arg_input_unpack.v:163:33 + extern void i_real_1d(const double* val); + // DPI import at t/t_dpi_arg_input_unpack.v:164:33 + extern void i_real_2d(const double* val); + // DPI import at t/t_dpi_arg_input_unpack.v:165:33 + extern void i_real_3d(const double* val); + // DPI import at t/t_dpi_arg_input_unpack.v:118:33 + extern void i_shortint_0d(short val); + // DPI import at t/t_dpi_arg_input_unpack.v:119:33 + extern void i_shortint_1d(const short* val); + // DPI import at t/t_dpi_arg_input_unpack.v:120:33 + extern void i_shortint_2d(const short* val); + // DPI import at t/t_dpi_arg_input_unpack.v:121:33 + extern void i_shortint_3d(const short* val); + // DPI import at t/t_dpi_arg_input_unpack.v:123:33 + extern void i_shortint_unsigned_0d(unsigned short val); + // DPI import at t/t_dpi_arg_input_unpack.v:124:33 + extern void i_shortint_unsigned_1d(const unsigned short* val); + // DPI import at t/t_dpi_arg_input_unpack.v:125:33 + extern void i_shortint_unsigned_2d(const unsigned short* val); + // DPI import at t/t_dpi_arg_input_unpack.v:126:33 + extern void i_shortint_unsigned_3d(const unsigned short* val); + // DPI import at t/t_dpi_arg_input_unpack.v:179:33 + extern void i_string_0d(const char* val); + // DPI import at t/t_dpi_arg_input_unpack.v:180:33 + extern void i_string_1d(const char** val); + // DPI import at t/t_dpi_arg_input_unpack.v:181:33 + extern void i_string_2d(const char** val); + // DPI import at t/t_dpi_arg_input_unpack.v:182:33 + extern void i_string_3d(const char** val); + // DPI import at t/t_dpi_arg_input_unpack.v:149:33 + extern void i_time_0d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:150:33 + extern void i_time_1d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:151:33 + extern void i_time_2d(const svLogicVecVal* val); + // DPI import at t/t_dpi_arg_input_unpack.v:152:33 + extern void i_time_3d(const svLogicVecVal* val); + +#ifdef __cplusplus +} +#endif diff --git a/test_regress/t/t_dpi_arg_output_unpack.cpp b/test_regress/t/t_dpi_arg_output_unpack.cpp new file mode 100644 index 000000000..417e29cb1 --- /dev/null +++ b/test_regress/t/t_dpi_arg_output_unpack.cpp @@ -0,0 +1,655 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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 +// +//************************************************************************* + +#include +#include +#include +#include +#include + +// clang-format off +#if defined(NCSC) +// Used by NC's svdpi.h to pick up svLogicVecVal with _.aval and _.bval fields, +// rather than the IEEE 1800-2005 version which has _.a and _.b fields. +# define DPI_COMPATIBILITY_VERSION_1800v2012 +#endif + +#include "svdpi.h" + +#if defined(VERILATOR) // Verilator +# include "Vt_dpi_arg_output_unpack__Dpi.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +# define NO_SHORTREAL +# define NO_UNPACK_STRUCT +# define CONSTARG const +#elif defined(VCS) // VCS +# include "../vc_hdrs.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +# define NO_TIME +# define CONSTARG const +#elif defined(NCSC) // NC +# include "dpi-exp.h" +# include "dpi-imp.h" +typedef long long sv_longint_t; +typedef unsigned long long sv_longint_unsigned_t; +# define NO_TIME +# define NO_INTEGER +# define NO_SHORTREAL +// Sadly NC does not declare pass-by reference input arguments as const +# define CONSTARG +#elif defined(MS) // ModelSim +# include "dpi.h" +typedef int64_t sv_longint_t; +typedef uint64_t sv_longint_unsigned_t; +# define CONSTARG const +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +//====================================================================== +// Implementations of imported functions +//====================================================================== + +namespace { // unnamed namespace + +const bool VERBOSE_MESSAGE = false; + +#define stop() \ + do { \ + printf(__FILE__ ":%d Bad value\n", __LINE__); \ + abort(); \ + } while (0) + +void set_uint(svLogicVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + if (i < 64) + svPutBitselLogic(v0, i, (val >> i) & 1); + else + svPutBitselLogic(v0, i, 0); + } +} + +void set_uint(svBitVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + if (i < 64) + svPutBitselBit(v0, i, (val >> i) & 1); + else + svPutBitselBit(v0, i, 0); + } +} + +template void set_0d(T* v) { *v = 42; } +template void set_1d(T* v) { + v[0] = 43; + v[1] = 44; +} + +template void set_2d(T* v) { + v[0 * 2 + 1] = 45; + v[1 * 2 + 1] = 46; + v[2 * 2 + 1] = 47; +} +template void set_3d(T* v) { + v[(0 * 3 + 0) * 2 + 0] = 48; + v[(1 * 3 + 0) * 2 + 0] = 49; + v[(2 * 3 + 0) * 2 + 0] = 50; + v[(3 * 3 + 0) * 2 + 0] = 51; +} + +void set_0d(svLogicVecVal* v, int bitwidth) { set_uint(v, 42, bitwidth); } + +void set_1d(svLogicVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + set_uint(v + 0 * unit, 43, bitwidth); + set_uint(v + 1 * unit, 44, bitwidth); +} + +void set_2d(svLogicVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + set_uint(v + (0 * 2 + 1) * unit, 45, bitwidth); + set_uint(v + (1 * 2 + 1) * unit, 46, bitwidth); + set_uint(v + (2 * 2 + 1) * unit, 47, bitwidth); +} + +void set_3d(svLogicVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + set_uint(v + ((0 * 3 + 0) * 2 + 0) * unit, 48, bitwidth); + set_uint(v + ((1 * 3 + 0) * 2 + 0) * unit, 49, bitwidth); + set_uint(v + ((2 * 3 + 0) * 2 + 0) * unit, 50, bitwidth); + set_uint(v + ((3 * 3 + 0) * 2 + 0) * unit, 51, bitwidth); +} + +void set_0d(svBitVecVal* v, int bitwidth) { set_uint(v, 42, bitwidth); } + +void set_1d(svBitVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + set_uint(v + 0 * unit, 43, bitwidth); + set_uint(v + 1 * unit, 44, bitwidth); +} + +void set_2d(svBitVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + set_uint(v + (0 * 2 + 1) * unit, 45, bitwidth); + set_uint(v + (1 * 2 + 1) * unit, 46, bitwidth); + set_uint(v + (2 * 2 + 1) * unit, 47, bitwidth); +} + +void set_3d(svBitVecVal* v, int bitwidth) { + const int unit = (bitwidth + 31) / 32; + set_uint(v + ((0 * 3 + 0) * 2 + 0) * unit, 48, bitwidth); + set_uint(v + ((1 * 3 + 0) * 2 + 0) * unit, 49, bitwidth); + set_uint(v + ((2 * 3 + 0) * 2 + 0) * unit, 50, bitwidth); + set_uint(v + ((3 * 3 + 0) * 2 + 0) * unit, 51, bitwidth); +} + +template bool compare(const T& act, const T& exp) { + if (exp == act) { + if (VERBOSE_MESSAGE) { std::cout << "OK Exp:" << exp << " actual:" << act << std::endl; } + return true; + } else { + std::cout << "NG Exp:" << exp << " actual:" << act << std::endl; + return false; + } +} + +template bool check_0d(T v) { return compare(v, 42); } +template bool check_1d(const T (&v)[2]) { + return compare(v[0], 43) && compare(v[1], 44); +} +template bool check_2d(const T (&v)[3][2]) { + return compare(v[0][1], 45) && compare(v[1][1], 46) && compare(v[2][1], 47); +} +template bool check_3d(const T (&v)[4][3][2]) { + return compare(v[0][0][0], 48) && compare(v[1][0][0], 49) && compare(v[2][0][0], 50) + && compare(v[3][0][0], 51); +} + +bool compare(const svLogicVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + const bool act_bit = svGetBitselLogic(v0, i); + const bool exp_bit = (i < 64) ? ((val >> i) & 1) : false; + if (act_bit != exp_bit) { + std::cout << "Mismatch at bit:" << i << " exp:" << exp_bit << " act:" << act_bit; + return false; + } + } + if (VERBOSE_MESSAGE) { + std::cout << "OK " << val << " as expected (width:" << bitwidth << ")" << std::endl; + } + return true; +} + +bool compare(const svBitVecVal* v0, sv_longint_unsigned_t val, int bitwidth) { + for (int i = 0; i < bitwidth; ++i) { + const bool act_bit = svGetBitselBit(v0, i); + const bool exp_bit = (i < 64) ? ((val >> i) & 1) : false; + if (act_bit != exp_bit) { + std::cout << "Mismatch at bit:" << i << " exp:" << exp_bit << " act:" << act_bit; + return false; + } + } + if (VERBOSE_MESSAGE) { + std::cout << "OK " << val << " as expected (width:" << bitwidth << ")" << std::endl; + } + return true; +} + +template bool check_0d(const T (&v)[N], int bitwidth) { + return compare(v, 42, bitwidth); +} +template bool check_1d(const T (&v)[2][N], int bitwidth) { + return compare(v[0], 43, bitwidth) && compare(v[1], 44, bitwidth); +} +template bool check_2d(const T (&v)[3][2][N], int bitwidth) { + return compare(v[0][1], 45, bitwidth) && compare(v[1][1], 46, bitwidth) + && compare(v[2][1], 47, bitwidth); +} +template bool check_3d(const T (&v)[4][3][2][N], int bitwidth) { + return compare(v[0][0][0], 48, bitwidth) && compare(v[1][0][0], 49, bitwidth) + && compare(v[2][0][0], 50, bitwidth) && compare(v[3][0][0], 51, bitwidth); +} + +} // unnamed namespace + +void* get_non_null() { + static int v; + return &v; +} + +void i_byte_0d(char* v) { set_0d(v); } +void i_byte_1d(char* v) { set_1d(v); } +void i_byte_2d(char* v) { set_2d(v); } +void i_byte_3d(char* v) { set_3d(v); } + +void i_byte_unsigned_0d(unsigned char* v) { set_0d(v); } +void i_byte_unsigned_1d(unsigned char* v) { set_1d(v); } +void i_byte_unsigned_2d(unsigned char* v) { set_2d(v); } +void i_byte_unsigned_3d(unsigned char* v) { set_3d(v); } + +void i_shortint_0d(short* v) { set_0d(v); } +void i_shortint_1d(short* v) { set_1d(v); } +void i_shortint_2d(short* v) { set_2d(v); } +void i_shortint_3d(short* v) { set_3d(v); } + +void i_shortint_unsigned_0d(unsigned short* v) { set_0d(v); } +void i_shortint_unsigned_1d(unsigned short* v) { set_1d(v); } +void i_shortint_unsigned_2d(unsigned short* v) { set_2d(v); } +void i_shortint_unsigned_3d(unsigned short* v) { set_3d(v); } + +void i_int_0d(int* v) { set_0d(v); } +void i_int_1d(int* v) { set_1d(v); } +void i_int_2d(int* v) { set_2d(v); } +void i_int_3d(int* v) { set_3d(v); } + +void i_int_unsigned_0d(unsigned int* v) { set_0d(v); } +void i_int_unsigned_1d(unsigned int* v) { set_1d(v); } +void i_int_unsigned_2d(unsigned int* v) { set_2d(v); } +void i_int_unsigned_3d(unsigned int* v) { set_3d(v); } + +void i_longint_0d(sv_longint_t* v) { set_0d(v); } +void i_longint_1d(sv_longint_t* v) { set_1d(v); } +void i_longint_2d(sv_longint_t* v) { set_2d(v); } +void i_longint_3d(sv_longint_t* v) { set_3d(v); } + +void i_longint_unsigned_0d(sv_longint_unsigned_t* v) { set_0d(v); } +void i_longint_unsigned_1d(sv_longint_unsigned_t* v) { set_1d(v); } +void i_longint_unsigned_2d(sv_longint_unsigned_t* v) { set_2d(v); } +void i_longint_unsigned_3d(sv_longint_unsigned_t* v) { set_3d(v); } + +#ifndef NO_TIME +void i_time_0d(svLogicVecVal* v) { set_0d(v, 64); } +void i_time_1d(svLogicVecVal* v) { set_1d(v, 64); } +void i_time_2d(svLogicVecVal* v) { set_2d(v, 64); } +void i_time_3d(svLogicVecVal* v) { set_3d(v, 64); } +#endif + +#ifndef NO_INTEGER +void i_integer_0d(svLogicVecVal* v) { set_0d(v, 32); } +void i_integer_1d(svLogicVecVal* v) { set_1d(v, 32); } +void i_integer_2d(svLogicVecVal* v) { set_2d(v, 32); } +void i_integer_3d(svLogicVecVal* v) { set_3d(v, 32); } +#endif + +void i_real_0d(double* v) { set_0d(v); } +void i_real_1d(double* v) { set_1d(v); } +void i_real_2d(double* v) { set_2d(v); } +void i_real_3d(double* v) { set_3d(v); } + +#ifndef NO_SHORTREAL +void i_shortreal_0d(float* v) { set_0d(v); } +void i_shortreal_1d(float* v) { set_1d(v); } +void i_shortreal_2d(float* v) { set_2d(v); } +void i_shortreal_3d(float* v) { set_3d(v); } +#endif + +void i_chandle_0d(void** v) { v[0] = get_non_null(); } +void i_chandle_1d(void** v) { + v[0] = get_non_null(); + v[1] = get_non_null(); +} +void i_chandle_2d(void** v) { + v[2 * 0 + 1] = get_non_null(); + v[2 * 1 + 1] = get_non_null(); + v[2 * 2 + 1] = get_non_null(); +} +void i_chandle_3d(void** v) { + v[(0 * 3 + 0) * 2 + 0] = get_non_null(); + v[(1 * 3 + 0) * 2 + 0] = get_non_null(); + v[(2 * 3 + 0) * 2 + 0] = get_non_null(); + v[(3 * 3 + 0) * 2 + 0] = get_non_null(); +} + +void i_string_0d(const char** v) { + static const char s[] = "42"; + v[0] = s; +} +void i_string_1d(const char** v) { + static const char s0[] = "43"; + static const char s1[] = "44"; + v[0] = s0; + v[1] = s1; +} +void i_string_2d(const char** v) { + static const char empty[] = ""; + static const char s0[] = "45"; + static const char s1[] = "46"; + static const char s2[] = "47"; + for (int i = 0; i < 3 * 2; ++i) v[i] = empty; + v[2 * 0 + 1] = s0; + v[2 * 1 + 1] = s1; + v[2 * 2 + 1] = s2; +} +void i_string_3d(const char** v) { + static const char empty[] = ""; + static const char s0[] = "48"; + static const char s1[] = "49"; + static const char s2[] = "50"; + static const char s3[] = "51"; + for (int i = 0; i < 4 * 3 * 2; ++i) v[i] = empty; + v[(0 * 3 + 0) * 2 + 0] = s0; + v[(1 * 3 + 0) * 2 + 0] = s1; + v[(2 * 3 + 0) * 2 + 0] = s2; + v[(3 * 3 + 0) * 2 + 0] = s3; +} + +void i_bit7_0d(svBitVecVal* v) { set_0d(v, 7); } +void i_bit7_1d(svBitVecVal* v) { set_1d(v, 7); } +void i_bit7_2d(svBitVecVal* v) { set_2d(v, 7); } +void i_bit7_3d(svBitVecVal* v) { set_3d(v, 7); } + +void i_bit121_0d(svBitVecVal* v) { set_0d(v, 121); } +void i_bit121_1d(svBitVecVal* v) { set_1d(v, 121); } +void i_bit121_2d(svBitVecVal* v) { set_2d(v, 121); } +void i_bit121_3d(svBitVecVal* v) { set_3d(v, 121); } + +void i_logic7_0d(svLogicVecVal* v) { set_0d(v, 7); } +void i_logic7_1d(svLogicVecVal* v) { set_1d(v, 7); } +void i_logic7_2d(svLogicVecVal* v) { set_2d(v, 7); } +void i_logic7_3d(svLogicVecVal* v) { set_3d(v, 7); } + +void i_logic121_0d(svLogicVecVal* v) { set_0d(v, 121); } +void i_logic121_1d(svLogicVecVal* v) { set_1d(v, 121); } +void i_logic121_2d(svLogicVecVal* v) { set_2d(v, 121); } +void i_logic121_3d(svLogicVecVal* v) { set_3d(v, 121); } + +void i_pack_struct_0d(svLogicVecVal* v) { set_0d(v, 7); } +void i_pack_struct_1d(svLogicVecVal* v) { set_1d(v, 7); } +void i_pack_struct_2d(svLogicVecVal* v) { set_2d(v, 7); } +void i_pack_struct_3d(svLogicVecVal* v) { set_3d(v, 7); } + +#ifndef NO_UNPACK_STRUCT +void i_unpack_struct_0d(unpack_struct_t* v) { set_uint(v->val, 42, 121); } +void i_unpack_struct_1d(unpack_struct_t* v) { + set_uint(v[0].val, 43, 121); + set_uint(v[1].val, 44, 121); +} +void i_unpack_struct_2d(unpack_struct_t* v) { + set_uint(v[0 * 2 + 1].val, 45, 121); + set_uint(v[1 * 2 + 1].val, 46, 121); + set_uint(v[2 * 2 + 1].val, 47, 121); +} +void i_unpack_struct_3d(unpack_struct_t* v) { + set_uint(v[(0 * 3 + 0) * 2 + 0].val, 48, 121); + set_uint(v[(1 * 3 + 0) * 2 + 0].val, 49, 121); + set_uint(v[(2 * 3 + 0) * 2 + 0].val, 50, 121); + set_uint(v[(3 * 3 + 0) * 2 + 0].val, 51, 121); +} +#endif + +void check_exports() { + { + char byte_array[4][3][2]; + e_byte_0d(&byte_array[3][2][1]); + if (!check_0d(byte_array[3][2][1])) stop(); + e_byte_1d(&byte_array[2][1][0]); + if (!check_1d(byte_array[2][1])) stop(); + e_byte_2d(&byte_array[1][0][0]); + if (!check_2d(byte_array[1])) stop(); + e_byte_3d(&byte_array[0][0][0]); + if (!check_3d(byte_array)) stop(); + } + { + unsigned char byte_unsigned_array[4][3][2]; + e_byte_unsigned_0d(&byte_unsigned_array[3][2][1]); + if (!check_0d(byte_unsigned_array[3][2][1])) stop(); + e_byte_unsigned_1d(&byte_unsigned_array[2][1][0]); + if (!check_1d(byte_unsigned_array[2][1])) stop(); + e_byte_unsigned_2d(&byte_unsigned_array[1][0][0]); + if (!check_2d(byte_unsigned_array[1])) stop(); + e_byte_unsigned_3d(&byte_unsigned_array[0][0][0]); + if (!check_3d(byte_unsigned_array)) stop(); + } + { + short shortint_array[4][3][2]; + e_shortint_0d(&shortint_array[3][2][1]); + if (!check_0d(shortint_array[3][2][1])) stop(); + e_shortint_1d(&shortint_array[2][1][0]); + if (!check_1d(shortint_array[2][1])) stop(); + e_shortint_2d(&shortint_array[1][0][0]); + if (!check_2d(shortint_array[1])) stop(); + e_shortint_3d(&shortint_array[0][0][0]); + if (!check_3d(shortint_array)) stop(); + } + { + unsigned short shortint_unsigned_array[4][3][2]; + e_shortint_unsigned_0d(&shortint_unsigned_array[3][2][1]); + if (!check_0d(shortint_unsigned_array[3][2][1])) stop(); + e_shortint_unsigned_1d(&shortint_unsigned_array[2][1][0]); + if (!check_1d(shortint_unsigned_array[2][1])) stop(); + e_shortint_unsigned_2d(&shortint_unsigned_array[1][0][0]); + if (!check_2d(shortint_unsigned_array[1])) stop(); + e_shortint_unsigned_3d(&shortint_unsigned_array[0][0][0]); + if (!check_3d(shortint_unsigned_array)) stop(); + } + + { + int int_array[4][3][2]; + e_int_0d(&int_array[3][2][1]); + if (!check_0d(int_array[3][2][1])) stop(); + e_int_1d(&int_array[2][1][0]); + if (!check_1d(int_array[2][1])) stop(); + e_int_2d(&int_array[1][0][0]); + if (!check_2d(int_array[1])) stop(); + e_int_3d(&int_array[0][0][0]); + if (!check_3d(int_array)) stop(); + } + { + unsigned int int_unsigned_array[4][3][2]; + e_int_unsigned_0d(&int_unsigned_array[3][2][1]); + if (!check_0d(int_unsigned_array[3][2][1])) stop(); + e_int_unsigned_1d(&int_unsigned_array[2][1][0]); + if (!check_1d(int_unsigned_array[2][1])) stop(); + e_int_unsigned_2d(&int_unsigned_array[1][0][0]); + if (!check_2d(int_unsigned_array[1])) stop(); + e_int_unsigned_3d(&int_unsigned_array[0][0][0]); + if (!check_3d(int_unsigned_array)) stop(); + } + + { + sv_longint_t longint_array[4][3][2]; + e_longint_0d(&longint_array[3][2][1]); + if (!check_0d(longint_array[3][2][1])) stop(); + e_longint_1d(&longint_array[2][1][0]); + if (!check_1d(longint_array[2][1])) stop(); + e_longint_2d(&longint_array[1][0][0]); + if (!check_2d(longint_array[1])) stop(); + e_longint_3d(&longint_array[0][0][0]); + if (!check_3d(longint_array)) stop(); + } + { + sv_longint_unsigned_t longint_unsigned_array[4][3][2]; + e_longint_unsigned_0d(&longint_unsigned_array[3][2][1]); + if (!check_0d(longint_unsigned_array[3][2][1])) stop(); + e_longint_unsigned_1d(&longint_unsigned_array[2][1][0]); + if (!check_1d(longint_unsigned_array[2][1])) stop(); + e_longint_unsigned_2d(&longint_unsigned_array[1][0][0]); + if (!check_2d(longint_unsigned_array[1])) stop(); + e_longint_unsigned_3d(&longint_unsigned_array[0][0][0]); + if (!check_3d(longint_unsigned_array)) stop(); + } + +#ifndef NO_TIME + { + svLogicVecVal time_array[4][3][2][2]; + e_time_0d(time_array[3][2][1]); + if (!check_0d(time_array[3][2][1], 64)) stop(); + e_time_1d(time_array[2][1][0]); + if (!check_1d(time_array[2][1], 64)) stop(); + e_time_2d(time_array[1][0][0]); + if (!check_2d(time_array[1], 64)) stop(); + e_time_3d(time_array[0][0][0]); + if (!check_3d(time_array, 64)) stop(); + } +#endif + +#ifndef NO_INTEGER + { + svLogicVecVal integer_array[4][3][2][1]; + e_integer_0d(integer_array[3][2][1]); + if (!check_0d(integer_array[3][2][1], 32)) stop(); + e_integer_1d(integer_array[2][1][0]); + if (!check_1d(integer_array[2][1], 32)) stop(); + e_integer_2d(integer_array[1][0][0]); + if (!check_2d(integer_array[1], 32)) stop(); + e_integer_3d(integer_array[0][0][0]); + if (!check_3d(integer_array, 32)) stop(); + } +#endif + + { + double real_array[4][3][2]; + e_real_0d(&real_array[3][2][1]); + if (!check_0d(real_array[3][2][1])) stop(); + e_real_1d(&real_array[2][1][0]); + if (!check_1d(real_array[2][1])) stop(); + e_real_2d(&real_array[1][0][0]); + if (!check_2d(real_array[1])) stop(); + e_real_3d(&real_array[0][0][0]); + if (!check_3d(real_array)) stop(); + } +#ifndef NO_SHORTREAL + { + float shortreal_array[4][3][2]; + e_shortreal_0d(&shortreal_array[3][2][1]); + if (!check_0d(shortreal_array[3][2][1])) stop(); + e_shortreal_1d(&shortreal_array[2][1][0]); + if (!check_1d(shortreal_array[2][1])) stop(); + e_shortreal_2d(&shortreal_array[1][0][0]); + if (!check_2d(shortreal_array[1])) stop(); + e_shortreal_3d(&shortreal_array[0][0][0]); + if (!check_3d(shortreal_array)) stop(); + } +#endif + + { + void* chandle_array[4][3][2]; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) chandle_array[i][j][k] = NULL; + e_chandle_0d(&chandle_array[3][2][1]); + if (!chandle_array[3][2][1]) stop(); + e_chandle_1d(&chandle_array[2][1][0]); + if (!chandle_array[2][1][0]) stop(); + if (!chandle_array[2][1][1]) stop(); + e_chandle_2d(&chandle_array[1][0][0]); + if (!chandle_array[1][0][1]) stop(); + if (!chandle_array[1][1][1]) stop(); + if (!chandle_array[1][2][1]) stop(); + e_chandle_3d(&chandle_array[0][0][0]); + if (!chandle_array[0][0][0]) stop(); + if (!chandle_array[1][0][0]) stop(); + if (!chandle_array[2][0][0]) stop(); + if (!chandle_array[3][0][0]) stop(); + } + + { + const char* string_array[4][3][2]; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) string_array[i][j][k] = NULL; + e_string_0d(&string_array[3][2][1]); + if (!compare(string_array[3][2][1], "42")) stop(); + e_string_1d(&string_array[2][1][0]); + if (!compare(string_array[2][1][0], "43")) stop(); + if (!compare(string_array[2][1][1], "44")) stop(); + e_string_2d(&string_array[1][0][0]); + if (!compare(string_array[1][0][1], "45")) stop(); + if (!compare(string_array[1][1][1], "46")) stop(); + if (!compare(string_array[1][2][1], "47")) stop(); + e_string_3d(&string_array[0][0][0]); + if (!compare(string_array[0][0][0], "48")) stop(); + if (!compare(string_array[1][0][0], "49")) stop(); + if (!compare(string_array[2][0][0], "50")) stop(); + if (!compare(string_array[3][0][0], "51")) stop(); + } + + { + svBitVecVal bit7_array[4][3][2][1]; + e_bit7_0d(bit7_array[3][2][1]); + if (!check_0d(bit7_array[3][2][1], 7)) stop(); + e_bit7_1d(bit7_array[2][1][0]); + if (!check_1d(bit7_array[2][1], 7)) stop(); + e_bit7_2d(bit7_array[1][0][0]); + if (!check_2d(bit7_array[1], 7)) stop(); + e_bit7_3d(bit7_array[0][0][0]); + if (!check_3d(bit7_array, 7)) stop(); + } + + { + svBitVecVal bit121_array[4][3][2][4]; + e_bit121_0d(bit121_array[3][2][1]); + if (!check_0d(bit121_array[3][2][1], 121)) stop(); + e_bit121_1d(bit121_array[2][1][0]); + if (!check_1d(bit121_array[2][1], 121)) stop(); + e_bit121_2d(bit121_array[1][0][0]); + if (!check_2d(bit121_array[1], 121)) stop(); + e_bit121_3d(bit121_array[0][0][0]); + if (!check_3d(bit121_array, 121)) stop(); + } + { + svLogicVecVal logic7_array[4][3][2][1]; + e_logic7_0d(logic7_array[3][2][1]); + if (!check_0d(logic7_array[3][2][1], 7)) stop(); + e_logic7_1d(logic7_array[2][1][0]); + if (!check_1d(logic7_array[2][1], 7)) stop(); + e_logic7_2d(logic7_array[1][0][0]); + if (!check_2d(logic7_array[1], 7)) stop(); + e_logic7_3d(logic7_array[0][0][0]); + if (!check_3d(logic7_array, 7)) stop(); + } + + { + svLogicVecVal logic121_array[4][3][2][4]; + e_logic121_0d(logic121_array[3][2][1]); + if (!check_0d(logic121_array[3][2][1], 121)) stop(); + e_logic121_1d(logic121_array[2][1][0]); + if (!check_1d(logic121_array[2][1], 121)) stop(); + e_logic121_2d(logic121_array[1][0][0]); + if (!check_2d(logic121_array[1], 121)) stop(); + e_logic121_3d(logic121_array[0][0][0]); + if (!check_3d(logic121_array, 121)) stop(); + } + + { + svLogicVecVal pack_struct_array[4][3][2][1]; + e_pack_struct_0d(pack_struct_array[3][2][1]); + if (!check_0d(pack_struct_array[3][2][1], 7)) stop(); + e_pack_struct_1d(pack_struct_array[2][1][0]); + if (!check_1d(pack_struct_array[2][1], 7)) stop(); + e_pack_struct_2d(pack_struct_array[1][0][0]); + if (!check_2d(pack_struct_array[1], 7)) stop(); + e_pack_struct_3d(pack_struct_array[0][0][0]); + if (!check_3d(pack_struct_array, 7)) stop(); + } + +#ifndef NO_UNPACK_STRUCT + { + unpack_struct_t unpack_struct_array[4][3][2]; + e_unpack_struct_0d(&unpack_struct_array[3][2][1]); + if (!compare(unpack_struct_array[3][2][1].val, 42, 121)) stop(); + e_unpack_struct_1d(&unpack_struct_array[2][1][0]); + if (!compare(unpack_struct_array[2][1][0].val, 43, 121)) stop(); + if (!compare(unpack_struct_array[2][1][1].val, 44, 121)) stop(); + e_unpack_struct_2d(&unpack_struct_array[1][0][0]); + if (!compare(unpack_struct_array[1][0][1].val, 45, 121)) stop(); + if (!compare(unpack_struct_array[1][1][1].val, 46, 121)) stop(); + if (!compare(unpack_struct_array[1][2][1].val, 47, 121)) stop(); + e_unpack_struct_3d(&unpack_struct_array[0][0][0]); + if (!compare(unpack_struct_array[0][0][0].val, 48, 121)) stop(); + if (!compare(unpack_struct_array[1][0][0].val, 49, 121)) stop(); + if (!compare(unpack_struct_array[2][0][0].val, 50, 121)) stop(); + if (!compare(unpack_struct_array[3][0][0].val, 51, 121)) stop(); + } +#endif +} diff --git a/test_regress/t/t_dpi_arg_output_unpack.pl b/test_regress/t/t_dpi_arg_output_unpack.pl new file mode 100755 index 000000000..4a2f325ab --- /dev/null +++ b/test_regress/t/t_dpi_arg_output_unpack.pl @@ -0,0 +1,44 @@ +#!/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 Geza Lore. 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); + +if ($Self->{nc}) { + # For NC, compile twice, first just to generate DPI headers + compile( + nc_flags2 => ["+ncdpiheader+$Self->{obj_dir}/dpi-exp.h", + "+ncdpiimpheader+$Self->{obj_dir}/dpi-imp.h"] + ); +} + +compile( + v_flags2 => ["t/t_dpi_arg_output_unpack.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME"], + # NC: Gdd the obj_dir to the C include path + nc_flags2 => ["+ncscargs+-I$Self->{obj_dir}"], + # ModelSim: Generate DPI header, add obj_dir to the C include path + ms_flags2 => ["-dpiheader $Self->{obj_dir}/dpi.h", + "-ccflags -I$Self->{obj_dir}"], + ); + +if ($Self->{vlt_all}) { + files_identical( + "$Self->{obj_dir}/Vt_dpi_arg_output_unpack__Dpi.h", + "t/t_dpi_arg_output_unpack__Dpi.out" + ); +} + +execute( + check_finished => 1, + ms_pli => 0 + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_arg_output_unpack.v b/test_regress/t/t_dpi_arg_output_unpack.v new file mode 100644 index 000000000..f2fbcd7ee --- /dev/null +++ b/test_regress/t/t_dpi_arg_output_unpack.v @@ -0,0 +1,761 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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 + +`ifdef VCS + `define NO_TIME +`endif + +`ifdef NC + `define NO_TIME + `define NO_INTEGER + `define NO_SHORTREAL +`endif + +`ifdef MS +`endif + +`ifdef VERILATOR + `define NO_SHORTREAL + `define NO_UNPACK_STRUCT + `define NULL 64'd0 +`else + `define NULL null +`endif + +`define CHECK_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ + end else begin \ + $display("Mismatch %s expected:%d actual:%d at %d", `"act`", \ + int'(exp), \ + int'(act), `__LINE__); \ + $stop; \ + end + +`define CHECK_0D(val) `CHECK_VAL((val), 42) +`define CHECK_1D(val) `CHECK_VAL(val[0], 43); \ +`CHECK_VAL(val[1], 44) +`define CHECK_2D(val) `CHECK_VAL(val[0][1], 45); \ +`CHECK_VAL(val[1][1], 46); \ +`CHECK_VAL(val[2][1], 47) +`define CHECK_3D(val) `CHECK_VAL(val[0][0][0], 48); \ +`CHECK_VAL(val[1][0][0], 49); \ +`CHECK_VAL(val[2][0][0], 50); \ +`CHECK_VAL(val[3][0][0], 51) + +`define CHECK_CHANDLE_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":non-null as expected"); \ + end else begin \ + $display("Mismatch %s expected:%s but %s at %d", `"act`", \ + (exp) ? "null" : "non-null", (act) ? "null" : "non-null", `__LINE__); \ + $stop; \ + end + +`define CHECK_STRING_VAL(act, exp) if ((act) == (exp)) begin \ + if (ENABLE_VERBOSE_MESSAGE)$display(`"act`", ":", (act), " as expected"); \ + end else begin \ + $display("Mismatch %s expected:%s actual:%s at %d", \ + `"act`", (exp), (act), `__LINE__); \ + $stop; \ + end + +`define SET_VALUES(val) \ +val[3][2][1] = 42; \ +val[2][1][0] = 43; val[2][1][1] = 44; \ +val[1][0][1] = 45; val[1][1][1] = 46; val[1][2][1] = 47; \ +val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 + +module t; + + localparam ENABLE_VERBOSE_MESSAGE = 0; + + // Legal output argument types for DPI functions + + //====================================================================== + // Type definitions + //====================================================================== + + typedef byte byte_array_t[4][3][2]; + typedef byte unsigned byte_unsigned_array_t[4][3][2]; + typedef shortint shortint_array_t[4][3][2]; + typedef shortint unsigned shortint_unsigned_array_t[4][3][2]; + typedef int int_array_t[4][3][2]; + typedef int unsigned int_unsigned_array_t[4][3][2]; + typedef longint longint_array_t[4][3][2]; + typedef longint unsigned longint_unsigned_array_t[4][3][2]; +`ifndef NO_TIME + typedef time time_array_t[4][3][2]; +`endif +`ifndef NO_INTEGER + typedef integer integer_array_t[4][3][2]; +`endif + typedef real real_array_t[4][3][2]; +`ifndef NO_SHORTREAL + typedef shortreal shortreal_array_t[4][3][2]; +`endif + typedef chandle chandle_array_t[4][3][2]; + typedef string string_array_t[4][3][2]; + typedef bit [6:0] bit7_array_t[4][3][2]; + typedef bit [120:0] bit121_array_t[4][3][2]; + typedef logic [6:0] logic7_array_t[4][3][2]; + typedef logic [120:0] logic121_array_t[4][3][2]; + + typedef struct packed { + logic [6:0] val; + } pack_struct_t; + typedef pack_struct_t pack_struct_array_t[4][3][2]; +`ifndef NO_UNPACK_STRUCT + typedef struct { + logic [120:0] val; + } unpack_struct_t; + typedef unpack_struct_t unpack_struct_array_t[4][3][2]; +`endif + + //====================================================================== + // Imports + //====================================================================== + + // Returns non-null pointer + import "DPI-C" function chandle get_non_null(); + + import "DPI-C" function void i_byte_0d(output byte val); + import "DPI-C" function void i_byte_1d(output byte val[2]); + import "DPI-C" function void i_byte_2d(output byte val[3][2]); + import "DPI-C" function void i_byte_3d(output byte_array_t val); + + import "DPI-C" function void i_byte_unsigned_0d(output byte unsigned val); + import "DPI-C" function void i_byte_unsigned_1d(output byte unsigned val[2]); + import "DPI-C" function void i_byte_unsigned_2d(output byte unsigned val[3][2]); + import "DPI-C" function void i_byte_unsigned_3d(output byte_unsigned_array_t val); + + import "DPI-C" function void i_shortint_0d(output shortint val); + import "DPI-C" function void i_shortint_1d(output shortint val[2]); + import "DPI-C" function void i_shortint_2d(output shortint val[3][2]); + import "DPI-C" function void i_shortint_3d(output shortint_array_t val); + + import "DPI-C" function void i_shortint_unsigned_0d(output shortint unsigned val); + import "DPI-C" function void i_shortint_unsigned_1d(output shortint unsigned val[2]); + import "DPI-C" function void i_shortint_unsigned_2d(output shortint unsigned val[3][2]); + import "DPI-C" function void i_shortint_unsigned_3d(output shortint_unsigned_array_t val); + + import "DPI-C" function void i_int_0d(output int val); + import "DPI-C" function void i_int_1d(output int val[2]); + import "DPI-C" function void i_int_2d(output int val[3][2]); + import "DPI-C" function void i_int_3d(output int_array_t val); + + import "DPI-C" function void i_int_unsigned_0d(output int unsigned val); + import "DPI-C" function void i_int_unsigned_1d(output int unsigned val[2]); + import "DPI-C" function void i_int_unsigned_2d(output int unsigned val[3][2]); + import "DPI-C" function void i_int_unsigned_3d(output int_unsigned_array_t val); + + import "DPI-C" function void i_longint_0d(output longint val); + import "DPI-C" function void i_longint_1d(output longint val[2]); + import "DPI-C" function void i_longint_2d(output longint val[3][2]); + import "DPI-C" function void i_longint_3d(output longint_array_t val); + + import "DPI-C" function void i_longint_unsigned_0d(output longint unsigned val); + import "DPI-C" function void i_longint_unsigned_1d(output longint unsigned val[2]); + import "DPI-C" function void i_longint_unsigned_2d(output longint unsigned val[3][2]); + import "DPI-C" function void i_longint_unsigned_3d(output longint_unsigned_array_t val); + +`ifndef NO_TIME + import "DPI-C" function void i_time_0d(output time val); + import "DPI-C" function void i_time_1d(output time val[2]); + import "DPI-C" function void i_time_2d(output time val[3][2]); + import "DPI-C" function void i_time_3d(output time_array_t val); +`endif + +`ifndef NO_INTEGER + import "DPI-C" function void i_integer_0d(output integer val); + import "DPI-C" function void i_integer_1d(output integer val[2]); + import "DPI-C" function void i_integer_2d(output integer val[3][2]); + import "DPI-C" function void i_integer_3d(output integer_array_t val); +`endif + + import "DPI-C" function void i_real_0d(output real val); + import "DPI-C" function void i_real_1d(output real val[2]); + import "DPI-C" function void i_real_2d(output real val[3][2]); + import "DPI-C" function void i_real_3d(output real_array_t val); + +`ifndef NO_SHORTREAL + import "DPI-C" function void i_shortreal_0d(output shortreal val); + import "DPI-C" function void i_shortreal_1d(output shortreal val[2]); + import "DPI-C" function void i_shortreal_2d(output shortreal val[3][2]); + import "DPI-C" function void i_shortreal_3d(output shortreal_array_t val); +`endif + + import "DPI-C" function void i_chandle_0d(output chandle val); + import "DPI-C" function void i_chandle_1d(output chandle val[2]); + import "DPI-C" function void i_chandle_2d(output chandle val[3][2]); + import "DPI-C" function void i_chandle_3d(output chandle_array_t val); + + import "DPI-C" function void i_string_0d(output string val); + import "DPI-C" function void i_string_1d(output string val[2]); + import "DPI-C" function void i_string_2d(output string val[3][2]); + import "DPI-C" function void i_string_3d(output string_array_t val); + + import "DPI-C" function void i_bit7_0d(output bit[6:0] val); + import "DPI-C" function void i_bit7_1d(output bit[6:0] val[2]); + import "DPI-C" function void i_bit7_2d(output bit[6:0] val[3][2]); + import "DPI-C" function void i_bit7_3d(output bit7_array_t val); + + import "DPI-C" function void i_bit121_0d(output bit[120:0] val); + import "DPI-C" function void i_bit121_1d(output bit[120:0] val[2]); + import "DPI-C" function void i_bit121_2d(output bit[120:0] val[3][2]); + import "DPI-C" function void i_bit121_3d(output bit121_array_t val); + + import "DPI-C" function void i_logic7_0d(output logic[6:0] val); + import "DPI-C" function void i_logic7_1d(output logic[6:0] val[2]); + import "DPI-C" function void i_logic7_2d(output logic[6:0] val[3][2]); + import "DPI-C" function void i_logic7_3d(output logic7_array_t val); + + import "DPI-C" function void i_logic121_0d(output logic[120:0] val); + import "DPI-C" function void i_logic121_1d(output logic[120:0] val[2]); + import "DPI-C" function void i_logic121_2d(output logic[120:0] val[3][2]); + import "DPI-C" function void i_logic121_3d(output logic121_array_t val); + + import "DPI-C" function void i_pack_struct_0d(output pack_struct_t val); + import "DPI-C" function void i_pack_struct_1d(output pack_struct_t val[2]); + import "DPI-C" function void i_pack_struct_2d(output pack_struct_t val[3][2]); + import "DPI-C" function void i_pack_struct_3d(output pack_struct_array_t val); + +`ifndef NO_UNPACK_STRUCT + import "DPI-C" function void i_unpack_struct_0d(output unpack_struct_t val); + import "DPI-C" function void i_unpack_struct_1d(output unpack_struct_t val[2]); + import "DPI-C" function void i_unpack_struct_2d(output unpack_struct_t val[3][2]); + import "DPI-C" function void i_unpack_struct_3d(output unpack_struct_array_t val); +`endif + + //====================================================================== + // Exports + //====================================================================== + export "DPI-C" function e_byte_0d; + export "DPI-C" function e_byte_1d; + export "DPI-C" function e_byte_2d; + export "DPI-C" function e_byte_3d; + + export "DPI-C" function e_byte_unsigned_0d; + export "DPI-C" function e_byte_unsigned_1d; + export "DPI-C" function e_byte_unsigned_2d; + export "DPI-C" function e_byte_unsigned_3d; + + export "DPI-C" function e_shortint_0d; + export "DPI-C" function e_shortint_1d; + export "DPI-C" function e_shortint_2d; + export "DPI-C" function e_shortint_3d; + + export "DPI-C" function e_shortint_unsigned_0d; + export "DPI-C" function e_shortint_unsigned_1d; + export "DPI-C" function e_shortint_unsigned_2d; + export "DPI-C" function e_shortint_unsigned_3d; + + export "DPI-C" function e_int_0d; + export "DPI-C" function e_int_1d; + export "DPI-C" function e_int_2d; + export "DPI-C" function e_int_3d; + + export "DPI-C" function e_int_unsigned_0d; + export "DPI-C" function e_int_unsigned_1d; + export "DPI-C" function e_int_unsigned_2d; + export "DPI-C" function e_int_unsigned_3d; + + export "DPI-C" function e_longint_0d; + export "DPI-C" function e_longint_1d; + export "DPI-C" function e_longint_2d; + export "DPI-C" function e_longint_3d; + + export "DPI-C" function e_longint_unsigned_0d; + export "DPI-C" function e_longint_unsigned_1d; + export "DPI-C" function e_longint_unsigned_2d; + export "DPI-C" function e_longint_unsigned_3d; + +`ifndef NO_TIME + export "DPI-C" function e_time_0d; + export "DPI-C" function e_time_1d; + export "DPI-C" function e_time_2d; + export "DPI-C" function e_time_3d; +`endif + +`ifndef NO_INTEGER + export "DPI-C" function e_integer_0d; + export "DPI-C" function e_integer_1d; + export "DPI-C" function e_integer_2d; + export "DPI-C" function e_integer_3d; +`endif + + export "DPI-C" function e_real_0d; + export "DPI-C" function e_real_1d; + export "DPI-C" function e_real_2d; + export "DPI-C" function e_real_3d; + +`ifndef NO_SHORTREAL + export "DPI-C" function e_shortreal_0d; + export "DPI-C" function e_shortreal_1d; + export "DPI-C" function e_shortreal_2d; + export "DPI-C" function e_shortreal_3d; +`endif + + export "DPI-C" function e_chandle_0d; + export "DPI-C" function e_chandle_1d; + export "DPI-C" function e_chandle_2d; + export "DPI-C" function e_chandle_3d; + + export "DPI-C" function e_string_0d; + export "DPI-C" function e_string_1d; + export "DPI-C" function e_string_2d; + export "DPI-C" function e_string_3d; + + export "DPI-C" function e_bit7_0d; + export "DPI-C" function e_bit7_1d; + export "DPI-C" function e_bit7_2d; + export "DPI-C" function e_bit7_3d; + + export "DPI-C" function e_bit121_0d; + export "DPI-C" function e_bit121_1d; + export "DPI-C" function e_bit121_2d; + export "DPI-C" function e_bit121_3d; + + export "DPI-C" function e_logic7_0d; + export "DPI-C" function e_logic7_1d; + export "DPI-C" function e_logic7_2d; + export "DPI-C" function e_logic7_3d; + + export "DPI-C" function e_logic121_0d; + export "DPI-C" function e_logic121_1d; + export "DPI-C" function e_logic121_2d; + export "DPI-C" function e_logic121_3d; + + export "DPI-C" function e_pack_struct_0d; + export "DPI-C" function e_pack_struct_1d; + export "DPI-C" function e_pack_struct_2d; + export "DPI-C" function e_pack_struct_3d; + +`ifndef NO_UNPACK_STRUCT + export "DPI-C" function e_unpack_struct_0d; + export "DPI-C" function e_unpack_struct_1d; + export "DPI-C" function e_unpack_struct_2d; + export "DPI-C" function e_unpack_struct_3d; +`endif + //====================================================================== + // Definitions of exported functions + //====================================================================== +`define SET_0D(val) val = 42 +`define SET_1D(val) val[0] = 43; val[1] = 44 +`define SET_2D(val) val[0][1] = 45; val[1][1] = 46; val[2][1] = 47 +`define SET_3D(val) val[0][0][0] = 48; val[1][0][0] = 49; val[2][0][0] = 50; val[3][0][0] = 51 + + function void e_byte_0d(output byte val); `SET_0D(val); endfunction + function void e_byte_1d(output byte val[2]); `SET_1D(val); endfunction + function void e_byte_2d(output byte val[3][2]); `SET_2D(val); endfunction + function void e_byte_3d(output byte_array_t val); `SET_3D(val); endfunction + + function void e_byte_unsigned_0d(output byte unsigned val); `SET_0D(val); endfunction + function void e_byte_unsigned_1d(output byte unsigned val[2]); `SET_1D(val); endfunction + function void e_byte_unsigned_2d(output byte unsigned val[3][2]); `SET_2D(val); endfunction + function void e_byte_unsigned_3d(output byte_unsigned_array_t val); `SET_3D(val); endfunction + + function void e_shortint_0d(output shortint val); `SET_0D(val); endfunction + function void e_shortint_1d(output shortint val[2]); `SET_1D(val); endfunction + function void e_shortint_2d(output shortint val[3][2]); `SET_2D(val); endfunction + function void e_shortint_3d(output shortint_array_t val); `SET_3D(val); endfunction + + function void e_shortint_unsigned_0d(output shortint unsigned val); `SET_0D(val); endfunction + function void e_shortint_unsigned_1d(output shortint unsigned val[2]); `SET_1D(val); endfunction + function void e_shortint_unsigned_2d(output shortint unsigned val[3][2]); `SET_2D(val); endfunction + function void e_shortint_unsigned_3d(output shortint_unsigned_array_t val); `SET_3D(val); endfunction + + function void e_int_0d(output int val); `SET_0D(val); endfunction + function void e_int_1d(output int val[2]); `SET_1D(val); endfunction + function void e_int_2d(output int val[3][2]); `SET_2D(val); endfunction + function void e_int_3d(output int_array_t val); `SET_3D(val); endfunction + + function void e_int_unsigned_0d(output int unsigned val); `SET_0D(val); endfunction + function void e_int_unsigned_1d(output int unsigned val[2]); `SET_1D(val); endfunction + function void e_int_unsigned_2d(output int unsigned val[3][2]); `SET_2D(val); endfunction + function void e_int_unsigned_3d(output int_unsigned_array_t val); `SET_3D(val); endfunction + + function void e_longint_0d(output longint val); `SET_0D(val); endfunction + function void e_longint_1d(output longint val[2]); `SET_1D(val); endfunction + function void e_longint_2d(output longint val[3][2]); `SET_2D(val); endfunction + function void e_longint_3d(output longint_array_t val); `SET_3D(val); endfunction + + function void e_longint_unsigned_0d(output longint unsigned val); `SET_0D(val); endfunction + function void e_longint_unsigned_1d(output longint unsigned val[2]); `SET_1D(val); endfunction + function void e_longint_unsigned_2d(output longint unsigned val[3][2]); `SET_2D(val); endfunction + function void e_longint_unsigned_3d(output longint_unsigned_array_t val); `SET_3D(val); endfunction + +`ifndef NO_TIME + function void e_time_0d(output time val); `SET_0D(val); endfunction + function void e_time_1d(output time val[2]); `SET_1D(val); endfunction + function void e_time_2d(output time val[3][2]); `SET_2D(val); endfunction + function void e_time_3d(output time_array_t val); `SET_3D(val); endfunction +`endif + +`ifndef NO_INTEGER + function void e_integer_0d(output integer val); `SET_0D(val); endfunction + function void e_integer_1d(output integer val[2]); `SET_1D(val); endfunction + function void e_integer_2d(output integer val[3][2]); `SET_2D(val); endfunction + function void e_integer_3d(output integer_array_t val); `SET_3D(val); endfunction +`endif + + function void e_real_0d(output real val); `SET_0D(val); endfunction + function void e_real_1d(output real val[2]); `SET_1D(val); endfunction + function void e_real_2d(output real val[3][2]); `SET_2D(val); endfunction + function void e_real_3d(output real_array_t val); `SET_3D(val); endfunction + +`ifndef NO_SHORTREAL + function void e_shortreal_0d(output shortreal val); `SET_0D(val); endfunction + function void e_shortreal_1d(output shortreal val[2]); `SET_1D(val); endfunction + function void e_shortreal_2d(output shortreal val[3][2]); `SET_2D(val); endfunction + function void e_shortreal_3d(output shortreal_array_t val); `SET_3D(val); endfunction +`endif + + function void e_chandle_0d(output chandle val); + val = get_non_null(); + endfunction + function void e_chandle_1d(output chandle val[2]); + val[0] = get_non_null(); + val[1] = get_non_null(); + endfunction + function void e_chandle_2d(output chandle val[3][2]); + val[0][1] = get_non_null(); + val[1][1] = get_non_null(); + val[2][1] = get_non_null(); + endfunction + function void e_chandle_3d(output chandle_array_t val); + val[0][0][0] = get_non_null(); + val[1][0][0] = get_non_null(); + val[2][0][0] = get_non_null(); + val[3][0][0] = get_non_null(); + endfunction + + function void e_string_0d(output string val); + val = "42"; + endfunction + function void e_string_1d(output string val[2]); + val[0] = "43"; + val[1] = "44"; + endfunction + function void e_string_2d(output string val[3][2]); + val[0][1] = "45"; + val[1][1] = "46"; + val[2][1] = "47"; + endfunction + function void e_string_3d(output string_array_t val); + val[0][0][0] = "48"; + val[1][0][0] = "49"; + val[2][0][0] = "50"; + val[3][0][0] = "51"; + endfunction + + function void e_bit7_0d(output bit[6:0] val); `SET_0D(val); endfunction + function void e_bit7_1d(output bit[6:0] val[2]); `SET_1D(val); endfunction + function void e_bit7_2d(output bit[6:0] val[3][2]); `SET_2D(val); endfunction + function void e_bit7_3d(output bit7_array_t val); `SET_3D(val); endfunction + + function void e_bit121_0d(output bit[120:0] val); `SET_0D(val); endfunction + function void e_bit121_1d(output bit[120:0] val[2]); `SET_1D(val); endfunction + function void e_bit121_2d(output bit[120:0] val[3][2]); `SET_2D(val); endfunction + function void e_bit121_3d(output bit121_array_t val); `SET_3D(val); endfunction + + function void e_logic7_0d(output logic[6:0] val); `SET_0D(val); endfunction + function void e_logic7_1d(output logic[6:0] val[2]); `SET_1D(val); endfunction + function void e_logic7_2d(output logic[6:0] val[3][2]); `SET_2D(val); endfunction + function void e_logic7_3d(output logic7_array_t val); `SET_3D(val); endfunction + + function void e_logic121_0d(output logic[120:0] val); `SET_0D(val); endfunction + function void e_logic121_1d(output logic[120:0] val[2]); `SET_1D(val); endfunction + function void e_logic121_2d(output logic[120:0] val[3][2]); `SET_2D(val); endfunction + function void e_logic121_3d(output logic121_array_t val); `SET_3D(val); endfunction + + function void e_pack_struct_0d(output pack_struct_t val); `SET_0D(val); endfunction + function void e_pack_struct_1d(output pack_struct_t val[2]); `SET_1D(val); endfunction + function void e_pack_struct_2d(output pack_struct_t val[3][2]); `SET_2D(val); endfunction + function void e_pack_struct_3d(output pack_struct_array_t val); `SET_3D(val); endfunction + +`ifndef NO_UNPACK_STRUCT + function void e_unpack_struct_0d(output unpack_struct_t val); + val.val = 42; + endfunction + function void e_unpack_struct_1d(output unpack_struct_t val[2]); + val[0].val = 43; + val[1].val = 44; + endfunction + function void e_unpack_struct_2d(output unpack_struct_t val[3][2]); + val[0][1].val = 45; + val[1][1].val = 46; + val[2][1].val = 47; + endfunction + function void e_unpack_struct_3d(output unpack_struct_array_t val); + val[0][0][0].val = 48; + val[1][0][0].val = 49; + val[2][0][0].val = 50; + val[3][0][0].val = 51; + endfunction +`endif + + //====================================================================== + // Invoke all imported functions + //====================================================================== + + import "DPI-C" context function void check_exports(); + + initial begin + byte_array_t byte_array; + byte_unsigned_array_t byte_unsigned_array; + shortint_array_t shortint_array; + shortint_unsigned_array_t shortint_unsigned_array; + int_array_t int_array; + int_unsigned_array_t int_unsigned_array; + longint_array_t longint_array; + longint_unsigned_array_t longint_unsigned_array; +`ifndef NO_TIME + time_array_t time_array; +`endif +`ifndef NO_INTEGER + integer_array_t integer_array; +`endif + real_array_t real_array; +`ifndef NO_SHORTREAL + shortreal_array_t shortreal_array; +`endif + chandle_array_t chandle_array; + string_array_t string_array; + bit7_array_t bit7_array; + bit121_array_t bit121_array; + logic7_array_t logic7_array; + logic121_array_t logic121_array; + pack_struct_array_t pack_struct_array; +`ifndef NO_UNPACK_STRUCT + unpack_struct_array_t unpack_struct_array; +`endif + + i_byte_0d(byte_array[3][2][1]); + `CHECK_0D(byte_array[3][2][1]); + i_byte_1d(byte_array[2][1]); + `CHECK_1D(byte_array[2][1]); + i_byte_2d(byte_array[1]); + `CHECK_2D(byte_array[1]); + i_byte_3d(byte_array); + `CHECK_3D(byte_array); + + i_byte_unsigned_0d(byte_unsigned_array[3][2][1]); + `CHECK_0D(byte_unsigned_array[3][2][1]); + i_byte_unsigned_1d(byte_unsigned_array[2][1]); + `CHECK_1D(byte_unsigned_array[2][1]); + i_byte_unsigned_2d(byte_unsigned_array[1]); + `CHECK_2D(byte_unsigned_array[1]); + i_byte_unsigned_3d(byte_unsigned_array); + `CHECK_3D(byte_unsigned_array); + + i_shortint_0d(shortint_array[3][2][1]); + `CHECK_0D(shortint_array[3][2][1]); + i_shortint_1d(shortint_array[2][1]); + `CHECK_1D(shortint_array[2][1]); + i_shortint_2d(shortint_array[1]); + `CHECK_2D(shortint_array[1]); + i_shortint_3d(shortint_array); + `CHECK_3D(shortint_array); + + i_shortint_unsigned_0d(shortint_unsigned_array[3][2][1]); + `CHECK_0D(shortint_unsigned_array[3][2][1]); + i_shortint_unsigned_1d(shortint_unsigned_array[2][1]); + `CHECK_1D(shortint_unsigned_array[2][1]); + i_shortint_unsigned_2d(shortint_unsigned_array[1]); + `CHECK_2D(shortint_unsigned_array[1]); + i_shortint_unsigned_3d(shortint_unsigned_array); + `CHECK_3D(shortint_unsigned_array); + + i_int_0d(int_array[3][2][1]); + `CHECK_0D(int_array[3][2][1]); + i_int_1d(int_array[2][1]); + `CHECK_1D(int_array[2][1]); + i_int_2d(int_array[1]); + `CHECK_2D(int_array[1]); + i_int_3d(int_array); + `CHECK_3D(int_array); + + i_int_unsigned_0d(int_unsigned_array[3][2][1]); + `CHECK_0D(int_unsigned_array[3][2][1]); + i_int_unsigned_1d(int_unsigned_array[2][1]); + `CHECK_1D(int_unsigned_array[2][1]); + i_int_unsigned_2d(int_unsigned_array[1]); + `CHECK_2D(int_unsigned_array[1]); + i_int_unsigned_3d(int_unsigned_array); + `CHECK_3D(int_unsigned_array); + + i_longint_0d(longint_array[3][2][1]); + `CHECK_0D(longint_array[3][2][1]); + i_longint_1d(longint_array[2][1]); + `CHECK_1D(longint_array[2][1]); + i_longint_2d(longint_array[1]); + `CHECK_2D(longint_array[1]); + i_longint_3d(longint_array); + `CHECK_3D(longint_array); + + i_longint_unsigned_0d(longint_unsigned_array[3][2][1]); + `CHECK_0D(longint_unsigned_array[3][2][1]); + i_longint_unsigned_1d(longint_unsigned_array[2][1]); + `CHECK_1D(longint_unsigned_array[2][1]); + i_longint_unsigned_2d(longint_unsigned_array[1]); + `CHECK_2D(longint_unsigned_array[1]); + i_longint_unsigned_3d(longint_unsigned_array); + `CHECK_3D(longint_unsigned_array); + +`ifndef NO_TIME + i_time_0d(time_array[3][2][1]); + `CHECK_0D(time_array[3][2][1]); + i_time_1d(time_array[2][1]); + `CHECK_1D(time_array[2][1]); + i_time_2d(time_array[1]); + `CHECK_2D(time_array[1]); + i_time_3d(time_array); + `CHECK_3D(time_array); +`endif + +`ifndef NO_INTEGER + i_integer_0d(integer_array[3][2][1]); + `CHECK_0D(integer_array[3][2][1]); + i_integer_1d(integer_array[2][1]); + `CHECK_1D(integer_array[2][1]); + i_integer_2d(integer_array[1]); + `CHECK_2D(integer_array[1]); + i_integer_3d(integer_array); + `CHECK_3D(integer_array); +`endif + + i_real_0d(real_array[3][2][1]); + `CHECK_0D(real_array[3][2][1]); + i_real_1d(real_array[2][1]); + `CHECK_1D(real_array[2][1]); + i_real_2d(real_array[1]); + `CHECK_2D(real_array[1]); + i_real_3d(real_array); + `CHECK_3D(real_array); + +`ifndef NO_SHORTREAL + i_shortreal_0d(shortreal_array[3][2][1]); + `CHECK_0D(shortreal_array[3][2][1]); + i_shortreal_1d(shortreal_array[2][1]); + `CHECK_1D(shortreal_array[2][1]); + i_shortreal_2d(shortreal_array[1]); + `CHECK_2D(shortreal_array[1]); + i_shortreal_3d(shortreal_array); + `CHECK_3D(shortreal_array); +`endif + + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 2; ++k) + chandle_array[i][j][k] = null; + i_chandle_0d(chandle_array[3][2][1]); + `CHECK_CHANDLE_VAL(chandle_array[3][2][1], get_non_null()); + i_chandle_1d(chandle_array[2][1]); + `CHECK_CHANDLE_VAL(chandle_array[2][1][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[2][1][1], get_non_null()); + i_chandle_2d(chandle_array[1]); + `CHECK_CHANDLE_VAL(chandle_array[1][0][1], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[1][1][1], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[1][2][1], get_non_null()); + i_chandle_3d(chandle_array); + `CHECK_CHANDLE_VAL(chandle_array[0][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[1][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[2][0][0], get_non_null()); + `CHECK_CHANDLE_VAL(chandle_array[3][0][0], get_non_null()); + + i_string_0d(string_array[3][2][1]); + `CHECK_STRING_VAL(string_array[3][2][1], "42"); + i_string_1d(string_array[2][1]); + `CHECK_STRING_VAL(string_array[2][1][0], "43"); + `CHECK_STRING_VAL(string_array[2][1][1], "44"); + i_string_2d(string_array[1]); + `CHECK_STRING_VAL(string_array[1][0][1], "45"); + `CHECK_STRING_VAL(string_array[1][1][1], "46"); + `CHECK_STRING_VAL(string_array[1][2][1], "47"); + i_string_3d(string_array); + `CHECK_STRING_VAL(string_array[0][0][0], "48"); + `CHECK_STRING_VAL(string_array[1][0][0], "49"); + `CHECK_STRING_VAL(string_array[2][0][0], "50"); + `CHECK_STRING_VAL(string_array[3][0][0], "51"); + + i_bit7_0d(bit7_array[3][2][1]); + `CHECK_0D(bit7_array[3][2][1]); + i_bit7_1d(bit7_array[2][1]); + `CHECK_1D(bit7_array[2][1]); + i_bit7_2d(bit7_array[1]); + `CHECK_2D(bit7_array[1]); + i_bit7_3d(bit7_array); + `CHECK_3D(bit7_array); + + i_bit121_0d(bit121_array[3][2][1]); + `CHECK_0D(bit121_array[3][2][1]); + i_bit121_1d(bit121_array[2][1]); + `CHECK_1D(bit121_array[2][1]); + i_bit121_2d(bit121_array[1]); + `CHECK_2D(bit121_array[1]); + i_bit121_3d(bit121_array); + `CHECK_3D(bit121_array); + + i_logic7_0d(logic7_array[3][2][1]); + `CHECK_0D(logic7_array[3][2][1]); + i_logic7_1d(logic7_array[2][1]); + `CHECK_1D(logic7_array[2][1]); + i_logic7_2d(logic7_array[1]); + `CHECK_2D(logic7_array[1]); + i_logic7_3d(logic7_array); + `CHECK_3D(logic7_array); + + i_logic121_0d(logic121_array[3][2][1]); + `CHECK_0D(logic121_array[3][2][1]); + i_logic121_1d(logic121_array[2][1]); + `CHECK_1D(logic121_array[2][1]); + i_logic121_2d(logic121_array[1]); + `CHECK_2D(logic121_array[1]); + i_logic121_3d(logic121_array); + `CHECK_3D(logic121_array); + + i_pack_struct_0d(pack_struct_array[3][2][1]); + `CHECK_0D(pack_struct_array[3][2][1]); + i_pack_struct_1d(pack_struct_array[2][1]); + `CHECK_1D(pack_struct_array[2][1]); + i_pack_struct_2d(pack_struct_array[1]); + `CHECK_2D(pack_struct_array[1]); + i_pack_struct_3d(pack_struct_array); + `CHECK_3D(pack_struct_array); + + `SET_VALUES(pack_struct_array); + i_pack_struct_0d(pack_struct_array[3][2][1]); + i_pack_struct_1d(pack_struct_array[2][1]); + i_pack_struct_2d(pack_struct_array[1]); + i_pack_struct_3d(pack_struct_array); + +`ifndef NO_UNPACK_STRUCT + i_unpack_struct_0d(unpack_struct_array[3][2][1]); + `CHECK_VAL(unpack_struct_array[3][2][1].val, 42); + + i_unpack_struct_1d(unpack_struct_array[2][1]); + `CHECK_VAL(unpack_struct_array[2][1][0].val, 43); + `CHECK_VAL(unpack_struct_array[2][1][1].val, 44); + + i_unpack_struct_2d(unpack_struct_array[1]); + `CHECK_VAL(unpack_struct_array[1][0][1].val, 45); + `CHECK_VAL(unpack_struct_array[1][1][1].val, 46); + `CHECK_VAL(unpack_struct_array[1][2][1].val, 47); + + i_unpack_struct_3d(unpack_struct_array); + `CHECK_VAL(unpack_struct_array[0][0][0].val, 48); + `CHECK_VAL(unpack_struct_array[1][0][0].val, 49); + `CHECK_VAL(unpack_struct_array[2][0][0].val, 50); + `CHECK_VAL(unpack_struct_array[3][0][0].val, 51); +`endif + + check_exports(); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_dpi_arg_output_unpack__Dpi.out b/test_regress/t/t_dpi_arg_output_unpack__Dpi.out new file mode 100644 index 000000000..0c038cb14 --- /dev/null +++ b/test_regress/t/t_dpi_arg_output_unpack__Dpi.out @@ -0,0 +1,313 @@ +// Verilated -*- C++ -*- +// DESCRIPTION: Verilator output: Prototypes for DPI import and export functions. +// +// Verilator includes this file in all generated .cpp files that use DPI functions. +// Manually include this file where DPI .c import functions are declared to ensure +// the C functions match the expectations of the DPI imports. + +#include "svdpi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + // DPI EXPORTS + // DPI export at t/t_dpi_arg_output_unpack.v:460:18 + extern void e_bit121_0d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:461:18 + extern void e_bit121_1d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:462:18 + extern void e_bit121_2d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:463:18 + extern void e_bit121_3d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:455:18 + extern void e_bit7_0d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:456:18 + extern void e_bit7_1d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:457:18 + extern void e_bit7_2d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:458:18 + extern void e_bit7_3d(svBitVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:351:18 + extern void e_byte_0d(char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:352:18 + extern void e_byte_1d(char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:353:18 + extern void e_byte_2d(char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:354:18 + extern void e_byte_3d(char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:356:18 + extern void e_byte_unsigned_0d(unsigned char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:357:18 + extern void e_byte_unsigned_1d(unsigned char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:358:18 + extern void e_byte_unsigned_2d(unsigned char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:359:18 + extern void e_byte_unsigned_3d(unsigned char* val); + // DPI export at t/t_dpi_arg_output_unpack.v:417:18 + extern void e_chandle_0d(void** val); + // DPI export at t/t_dpi_arg_output_unpack.v:420:18 + extern void e_chandle_1d(void** val); + // DPI export at t/t_dpi_arg_output_unpack.v:424:18 + extern void e_chandle_2d(void** val); + // DPI export at t/t_dpi_arg_output_unpack.v:429:18 + extern void e_chandle_3d(void** val); + // DPI export at t/t_dpi_arg_output_unpack.v:371:18 + extern void e_int_0d(int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:372:18 + extern void e_int_1d(int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:373:18 + extern void e_int_2d(int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:374:18 + extern void e_int_3d(int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:376:18 + extern void e_int_unsigned_0d(unsigned int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:377:18 + extern void e_int_unsigned_1d(unsigned int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:378:18 + extern void e_int_unsigned_2d(unsigned int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:379:18 + extern void e_int_unsigned_3d(unsigned int* val); + // DPI export at t/t_dpi_arg_output_unpack.v:399:18 + extern void e_integer_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:400:18 + extern void e_integer_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:401:18 + extern void e_integer_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:402:18 + extern void e_integer_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:470:18 + extern void e_logic121_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:471:18 + extern void e_logic121_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:472:18 + extern void e_logic121_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:473:18 + extern void e_logic121_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:465:18 + extern void e_logic7_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:466:18 + extern void e_logic7_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:467:18 + extern void e_logic7_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:468:18 + extern void e_logic7_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:381:18 + extern void e_longint_0d(long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:382:18 + extern void e_longint_1d(long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:383:18 + extern void e_longint_2d(long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:384:18 + extern void e_longint_3d(long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:386:18 + extern void e_longint_unsigned_0d(unsigned long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:387:18 + extern void e_longint_unsigned_1d(unsigned long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:388:18 + extern void e_longint_unsigned_2d(unsigned long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:389:18 + extern void e_longint_unsigned_3d(unsigned long long* val); + // DPI export at t/t_dpi_arg_output_unpack.v:475:18 + extern void e_pack_struct_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:476:18 + extern void e_pack_struct_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:477:18 + extern void e_pack_struct_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:478:18 + extern void e_pack_struct_3d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:405:18 + extern void e_real_0d(double* val); + // DPI export at t/t_dpi_arg_output_unpack.v:406:18 + extern void e_real_1d(double* val); + // DPI export at t/t_dpi_arg_output_unpack.v:407:18 + extern void e_real_2d(double* val); + // DPI export at t/t_dpi_arg_output_unpack.v:408:18 + extern void e_real_3d(double* val); + // DPI export at t/t_dpi_arg_output_unpack.v:361:18 + extern void e_shortint_0d(short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:362:18 + extern void e_shortint_1d(short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:363:18 + extern void e_shortint_2d(short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:364:18 + extern void e_shortint_3d(short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:366:18 + extern void e_shortint_unsigned_0d(unsigned short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:367:18 + extern void e_shortint_unsigned_1d(unsigned short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:368:18 + extern void e_shortint_unsigned_2d(unsigned short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:369:18 + extern void e_shortint_unsigned_3d(unsigned short* val); + // DPI export at t/t_dpi_arg_output_unpack.v:436:18 + extern void e_string_0d(const char** val); + // DPI export at t/t_dpi_arg_output_unpack.v:439:18 + extern void e_string_1d(const char** val); + // DPI export at t/t_dpi_arg_output_unpack.v:443:18 + extern void e_string_2d(const char** val); + // DPI export at t/t_dpi_arg_output_unpack.v:448:18 + extern void e_string_3d(const char** val); + // DPI export at t/t_dpi_arg_output_unpack.v:392:18 + extern void e_time_0d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:393:18 + extern void e_time_1d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:394:18 + extern void e_time_2d(svLogicVecVal* val); + // DPI export at t/t_dpi_arg_output_unpack.v:395:18 + extern void e_time_3d(svLogicVecVal* val); + + // DPI IMPORTS + // DPI import at t/t_dpi_arg_output_unpack.v:505:41 + extern void check_exports(); + // DPI import at t/t_dpi_arg_output_unpack.v:123:36 + extern void* get_non_null(); + // DPI import at t/t_dpi_arg_output_unpack.v:206:33 + extern void i_bit121_0d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:207:33 + extern void i_bit121_1d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:208:33 + extern void i_bit121_2d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:209:33 + extern void i_bit121_3d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:201:33 + extern void i_bit7_0d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:202:33 + extern void i_bit7_1d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:203:33 + extern void i_bit7_2d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:204:33 + extern void i_bit7_3d(svBitVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:125:33 + extern void i_byte_0d(char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:126:33 + extern void i_byte_1d(char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:127:33 + extern void i_byte_2d(char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:128:33 + extern void i_byte_3d(char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:130:33 + extern void i_byte_unsigned_0d(unsigned char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:131:33 + extern void i_byte_unsigned_1d(unsigned char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:132:33 + extern void i_byte_unsigned_2d(unsigned char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:133:33 + extern void i_byte_unsigned_3d(unsigned char* val); + // DPI import at t/t_dpi_arg_output_unpack.v:191:33 + extern void i_chandle_0d(void** val); + // DPI import at t/t_dpi_arg_output_unpack.v:192:33 + extern void i_chandle_1d(void** val); + // DPI import at t/t_dpi_arg_output_unpack.v:193:33 + extern void i_chandle_2d(void** val); + // DPI import at t/t_dpi_arg_output_unpack.v:194:33 + extern void i_chandle_3d(void** val); + // DPI import at t/t_dpi_arg_output_unpack.v:145:33 + extern void i_int_0d(int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:146:33 + extern void i_int_1d(int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:147:33 + extern void i_int_2d(int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:148:33 + extern void i_int_3d(int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:150:33 + extern void i_int_unsigned_0d(unsigned int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:151:33 + extern void i_int_unsigned_1d(unsigned int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:152:33 + extern void i_int_unsigned_2d(unsigned int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:153:33 + extern void i_int_unsigned_3d(unsigned int* val); + // DPI import at t/t_dpi_arg_output_unpack.v:173:33 + extern void i_integer_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:174:33 + extern void i_integer_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:175:33 + extern void i_integer_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:176:33 + extern void i_integer_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:216:33 + extern void i_logic121_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:217:33 + extern void i_logic121_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:218:33 + extern void i_logic121_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:219:33 + extern void i_logic121_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:211:33 + extern void i_logic7_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:212:33 + extern void i_logic7_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:213:33 + extern void i_logic7_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:214:33 + extern void i_logic7_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:155:33 + extern void i_longint_0d(long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:156:33 + extern void i_longint_1d(long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:157:33 + extern void i_longint_2d(long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:158:33 + extern void i_longint_3d(long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:160:33 + extern void i_longint_unsigned_0d(unsigned long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:161:33 + extern void i_longint_unsigned_1d(unsigned long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:162:33 + extern void i_longint_unsigned_2d(unsigned long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:163:33 + extern void i_longint_unsigned_3d(unsigned long long* val); + // DPI import at t/t_dpi_arg_output_unpack.v:221:33 + extern void i_pack_struct_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:222:33 + extern void i_pack_struct_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:223:33 + extern void i_pack_struct_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:224:33 + extern void i_pack_struct_3d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:179:33 + extern void i_real_0d(double* val); + // DPI import at t/t_dpi_arg_output_unpack.v:180:33 + extern void i_real_1d(double* val); + // DPI import at t/t_dpi_arg_output_unpack.v:181:33 + extern void i_real_2d(double* val); + // DPI import at t/t_dpi_arg_output_unpack.v:182:33 + extern void i_real_3d(double* val); + // DPI import at t/t_dpi_arg_output_unpack.v:135:33 + extern void i_shortint_0d(short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:136:33 + extern void i_shortint_1d(short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:137:33 + extern void i_shortint_2d(short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:138:33 + extern void i_shortint_3d(short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:140:33 + extern void i_shortint_unsigned_0d(unsigned short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:141:33 + extern void i_shortint_unsigned_1d(unsigned short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:142:33 + extern void i_shortint_unsigned_2d(unsigned short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:143:33 + extern void i_shortint_unsigned_3d(unsigned short* val); + // DPI import at t/t_dpi_arg_output_unpack.v:196:33 + extern void i_string_0d(const char** val); + // DPI import at t/t_dpi_arg_output_unpack.v:197:33 + extern void i_string_1d(const char** val); + // DPI import at t/t_dpi_arg_output_unpack.v:198:33 + extern void i_string_2d(const char** val); + // DPI import at t/t_dpi_arg_output_unpack.v:199:33 + extern void i_string_3d(const char** val); + // DPI import at t/t_dpi_arg_output_unpack.v:166:33 + extern void i_time_0d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:167:33 + extern void i_time_1d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:168:33 + extern void i_time_2d(svLogicVecVal* val); + // DPI import at t/t_dpi_arg_output_unpack.v:169:33 + extern void i_time_3d(svLogicVecVal* val); + +#ifdef __cplusplus +} +#endif diff --git a/test_regress/t/t_dpi_unpack_bad.out b/test_regress/t/t_dpi_unpack_bad.out new file mode 100644 index 000000000..735465cf0 --- /dev/null +++ b/test_regress/t/t_dpi_unpack_bad.out @@ -0,0 +1,30 @@ +%Error-UNSUPPORTED: t/t_dpi_unpack_bad.v:21:20: Shape of the argument does not match the shape of the parameter ('logic[2:0]' v.s. 'logic[3:0]') + : ... In instance t + 21 | import_func0(sig0); + | ^~~~ +%Warning-WIDTH: t/t_dpi_unpack_bad.v:21:7: Operator TASKREF 'import_func0' expects 4 bits on the Function Argument, but Function Argument's VARREF 'sig0' generates 3 bits. + : ... In instance t + 21 | import_func0(sig0); + | ^~~~~~~~~~~~ + ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message. +%Error-UNSUPPORTED: t/t_dpi_unpack_bad.v:23:20: Shape of the argument does not match the shape of the parameter ('logic[2:0]$[0:2][0:1]' v.s. 'logic[2:0]$[0:2]') + : ... In instance t + 23 | import_func1(sig1); + | ^~~~ +%Error-UNSUPPORTED: t/t_dpi_unpack_bad.v:25:20: Shape of the argument does not match the shape of the parameter ('logic[2:0]$[0:2][0:1]' v.s. 'logic[2:0]$[0:2][0:2]') + : ... In instance t + 25 | import_func2(sig1); + | ^~~~ +%Error-UNSUPPORTED: t/t_dpi_unpack_bad.v:27:20: Shape of the argument does not match the shape of the parameter ('bit[2:0]' v.s. 'logic[2:0]') + : ... In instance t + 27 | import_func2(sig2); + | ^~~~ +%Error-UNSUPPORTED: t/t_dpi_unpack_bad.v:29:24: Argument is not an unpacked array while parameter 'in' is + : ... In instance t + 29 | import_func0(sig0[1]); + | ^ +%Warning-WIDTH: t/t_dpi_unpack_bad.v:29:7: Operator TASKREF 'import_func0' expects 4 bits on the Function Argument, but Function Argument's ARRAYSEL generates 3 bits. + : ... In instance t + 29 | import_func0(sig0[1]); + | ^~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_dpi_unpack_bad.pl b/test_regress/t/t_dpi_unpack_bad.pl new file mode 100755 index 000000000..1720150ad --- /dev/null +++ b/test_regress/t/t_dpi_unpack_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, +); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_unpack_bad.v b/test_regress/t/t_dpi_unpack_bad.v new file mode 100644 index 000000000..381fbe675 --- /dev/null +++ b/test_regress/t/t_dpi_unpack_bad.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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; + + logic [2:0] sig0[3]; + logic [2:0] sig1[3][2]; + bit [2:0] sig2[3][3]; + + import "DPI-C" function void import_func0(input logic [3:0] in [0:2]); + import "DPI-C" function void import_func1(input logic [2:0] in [0:2]); + import "DPI-C" function void import_func2(input logic [2:0] in [0:2][0:2]); + + initial begin + // packed width differs + import_func0(sig0); + // dimension differs + import_func1(sig1); + // unpacked extent differs + import_func2(sig1); + // bit v.s. logic mismatch + import_func2(sig2); + // packed var for unpacked port + import_func0(sig0[1]); + end +endmodule From c371a63d4139b4f9f04ececdf505cbb63a8e19e6 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 19 Nov 2020 08:22:02 -0500 Subject: [PATCH 28/91] Internals: Fix missing final. No functional change. --- src/V3AstNodes.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 11bc1dd17..3d1b60705 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -455,7 +455,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const { return arg; } -class dpiTypesToStringConverter { +class dpiTypesToStringConverter VL_NOT_FINAL { public: virtual string openArray(const AstVar*) const { return "const svOpenArrayHandle"; } virtual string bitLogicVector(const AstVar* varp, bool isBit) const { @@ -486,7 +486,7 @@ string AstVar::dpiArgType(bool named, bool forReturn) const { if (forReturn) { return dpiTypesToStringConverter{}.convert(this); } else { - class converter : public dpiTypesToStringConverter { + class converter final : public dpiTypesToStringConverter { virtual string bitLogicVector(const AstVar* varp, bool isBit) const override { return string(varp->isReadOnly() ? "const " : "") + dpiTypesToStringConverter::bitLogicVector(varp, isBit) + '*'; @@ -509,7 +509,7 @@ string AstVar::dpiArgType(bool named, bool forReturn) const { } string AstVar::dpiTmpVarType(const string& varName) const { - class converter : public dpiTypesToStringConverter { + class converter final : public dpiTypesToStringConverter { string m_name; string arraySuffix(const AstVar* varp, size_t n) const { if (AstUnpackArrayDType* unpackp From b684995292b8943c944850b7b9eef03ecbe18912 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 19 Nov 2020 21:32:33 -0500 Subject: [PATCH 29/91] Support $random and $urandom seeds. --- Changes | 2 ++ bin/verilator | 8 ++--- include/verilated.cpp | 57 ++++++++++++++++++------------ include/verilated.h | 5 +++ src/V3AstNodes.h | 44 +++++++++++------------ src/V3EmitC.cpp | 3 ++ src/V3Unknown.cpp | 9 ++--- src/V3Width.cpp | 12 +++---- src/verilog.y | 11 +++--- test_regress/t/t_debug_emitv.out | 4 ++- test_regress/t/t_debug_emitv.v | 2 ++ test_regress/t/t_sys_rand_seed.out | 13 ------- test_regress/t/t_sys_rand_seed.pl | 5 ++- test_regress/t/t_urandom.v | 2 -- 14 files changed, 92 insertions(+), 85 deletions(-) delete mode 100644 test_regress/t/t_sys_rand_seed.out diff --git a/Changes b/Changes index a89ef1124..2655ecdfa 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.105 devel +*** Support $random and $urandom seeds. + **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] **** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] diff --git a/bin/verilator b/bin/verilator index 213d90e34..3e67e11c9 100755 --- a/bin/verilator +++ b/bin/verilator @@ -4113,10 +4113,10 @@ similar. =item $random, $urandom, $urandom_range -$random and $urandom do not support the optional argument to set the seed. -Use +verilator+seed argument to set the seed. There is one random seed per -C thread, not per module for $random, nor per object for random stability -of $urandom/$urandom_range. +Use +verilator+seed argument to set the seed if there is no $random or +$urandom optional argument to set the seed. There is one random seed per C +thread, not per module for $random, nor per object for random stability of +$urandom/$urandom_range. =item $readmemb, $readmemh diff --git a/include/verilated.cpp b/include/verilated.cpp index 9f3f23b64..cbe5655fd 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -256,6 +256,7 @@ Verilated::Serialized::Serialized() { s_errorLimit = 1; s_randReset = 0; s_randSeed = 0; + s_randSeedEpoch = 1; s_timeunit = VL_TIME_UNIT; // Initial value until overriden by _Vconfigure s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure } @@ -279,6 +280,8 @@ void* Verilated::serialized2Ptr() VL_MT_UNSAFE { return &VerilatedImp::s_s.v.m_s static vluint32_t vl_sys_rand32() VL_MT_UNSAFE { // Return random 32-bits using system library. // Used only to construct seed for Verilator's PNRG. + static VerilatedMutex s_mutex; + const VerilatedLockGuard lock(s_mutex); // Otherwise rand is unsafe #if defined(_WIN32) && !defined(__CYGWIN__) // Windows doesn't have lrand48(), although Cygwin does. return (rand() << 16) ^ rand(); @@ -288,29 +291,18 @@ static vluint32_t vl_sys_rand32() VL_MT_UNSAFE { } vluint64_t vl_rand64() VL_MT_SAFE { - static VerilatedMutex s_mutex; - static VL_THREAD_LOCAL bool t_seeded = false; + static VL_THREAD_LOCAL vluint32_t t_seedEpoch = 0; static VL_THREAD_LOCAL vluint64_t t_state[2]; - if (VL_UNLIKELY(!t_seeded)) { - t_seeded = true; - { - const VerilatedLockGuard lock(s_mutex); // Otherwise vl_sys_rand32 is unsafe - if (Verilated::randSeed() != 0) { - t_state[0] = ((static_cast(Verilated::randSeed()) << 32) - ^ (static_cast(Verilated::randSeed()))); - t_state[1] = ((static_cast(Verilated::randSeed()) << 32) - ^ (static_cast(Verilated::randSeed()))); - } else { - t_state[0] = ((static_cast(vl_sys_rand32()) << 32) - ^ (static_cast(vl_sys_rand32()))); - t_state[1] = ((static_cast(vl_sys_rand32()) << 32) - ^ (static_cast(vl_sys_rand32()))); - } - // Fix state as algorithm is slow to randomize if many zeros - // This causes a loss of ~ 1 bit of seed entropy, no big deal - if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0]; - if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1]; - } + // For speed, we use a thread-local epoch number to know when to reseed + if (VL_UNLIKELY(t_seedEpoch != Verilated::randSeedEpoch())) { + // Set epoch before state, in case races with new seeding + t_seedEpoch = Verilated::randSeedEpoch(); + t_state[0] = Verilated::randSeedDefault64(); + t_state[1] = t_state[0]; + // Fix state as algorithm is slow to randomize if many zeros + // This causes a loss of ~ 1 bit of seed entropy, no big deal + if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0]; + if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1]; } // Xoroshiro128+ algorithm vluint64_t result = t_state[0] + t_state[1]; @@ -334,6 +326,11 @@ WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE { } // LCOV_EXCL_STOP +IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE { + Verilated::randSeed(static_cast(seed)); + return VL_RANDOM_I(obits); +} + IData VL_RAND_RESET_I(int obits) VL_MT_SAFE { if (Verilated::randReset() == 0) return 0; IData data = ~0; @@ -2223,6 +2220,22 @@ void Verilated::randReset(int val) VL_MT_SAFE { void Verilated::randSeed(int val) VL_MT_SAFE { const VerilatedLockGuard lock(m_mutex); s_s.s_randSeed = val; + vluint64_t newEpoch = s_s.s_randSeedEpoch + 1; + if (VL_UNLIKELY(newEpoch == 0)) newEpoch = 1; + // Obververs must see new epoch AFTER seed updated +#ifdef VL_THREADED + std::atomic_signal_fence(std::memory_order_release); +#endif + s_s.s_randSeedEpoch = newEpoch; +} +vluint64_t Verilated::randSeedDefault64() VL_MT_SAFE { + if (Verilated::randSeed() != 0) { + return ((static_cast(Verilated::randSeed()) << 32) + ^ (static_cast(Verilated::randSeed()))); + } else { + return ((static_cast(vl_sys_rand32()) << 32) + ^ (static_cast(vl_sys_rand32()))); + } } void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE { const VerilatedLockGuard lock(m_mutex); diff --git a/include/verilated.h b/include/verilated.h index fb2ca3671..06bcb7741 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -387,6 +387,7 @@ class Verilated final { int s_errorLimit; ///< Stop on error number int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random int s_randSeed; ///< Random seed: 0=random + int s_randSeedEpoch; ///< Number incrementing on each reseed, 0=illegal Serialized(); ~Serialized() = default; } s_s; @@ -443,6 +444,9 @@ public: static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value static void randSeed(int val) VL_MT_SAFE; static int randSeed() VL_MT_SAFE { return s_s.s_randSeed; } ///< Return randSeed value + static vluint32_t randSeedEpoch() VL_MT_SAFE { return s_s.s_randSeedEpoch; } + /// Random seed extended to 64 bits, and defaulted if user seed==0 + static vluint64_t randSeedDefault64() VL_MT_SAFE; /// Enable debug of internal verilated code static void debug(int level) VL_MT_SAFE; @@ -649,6 +653,7 @@ extern vluint64_t vl_rand64() VL_MT_SAFE; inline IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); } inline QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); } extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal +extern IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE; inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) { vluint64_t rnd = vl_rand64(); if (VL_LIKELY(hi > lo)) { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index d38a39675..f8632dc49 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -5348,22 +5348,33 @@ public: //====================================================================== // non-ary ops -class AstRand final : public AstNodeTermop { +class AstRand final : public AstNodeMath { + // $random/$random(seed) or $urandom/$urandom(seed) // Return a random number, based upon width() private: + bool m_urandom = false; // $urandom vs $random bool m_reset = false; // Random reset, versus always random public: - AstRand(FileLine* fl, AstNodeDType* dtp, bool reset) + class Reset {}; + AstRand(FileLine* fl, Reset, AstNodeDType* dtp, bool reset) : ASTGEN_SUPER(fl) , m_reset{reset} { dtypep(dtp); } - explicit AstRand(FileLine* fl) - : ASTGEN_SUPER(fl) {} + AstRand(FileLine* fl, AstNode* seedp, bool urandom) + : ASTGEN_SUPER(fl) + , m_urandom(urandom) { + setNOp1p(seedp); + } ASTNODE_NODE_FUNCS(Rand) - virtual string emitVerilog() override { return "%f$random"; } + virtual string emitVerilog() override { + return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)") + : (m_urandom ? "%f$urandom()" : "%f$random()"); + } virtual string emitC() override { - return (m_reset ? "VL_RAND_RESET_%nq(%nw, %P)" : "VL_RANDOM_%nq(%nw, %P)"); + return m_reset + ? "VL_RAND_RESET_%nq(%nw, %P)" + : seedp() ? "VL_RANDOM_SEEDED_%nq%lq(%nw, %P, %li)" : "VL_RANDOM_%nq(%nw, %P)"; } virtual bool cleanOut() const override { return true; } virtual bool isGateOptimizable() const override { return false; } @@ -5371,24 +5382,9 @@ public: virtual int instrCount() const override { return instrCountPli(); } virtual V3Hash sameHash() const override { return V3Hash(); } virtual bool same(const AstNode* samep) const override { return true; } -}; - -class AstURandom final : public AstNodeTermop { - // $urandom -public: - explicit AstURandom(FileLine* fl) - : ASTGEN_SUPER(fl) { - dtypeSetUInt32(); // Says IEEE - } - ASTNODE_NODE_FUNCS(URandom) - virtual string emitVerilog() override { return "%f$urandom"; } - virtual string emitC() override { return "VL_RANDOM_%nq(%nw)"; } - virtual bool cleanOut() const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return instrCountPli(); } - virtual V3Hash sameHash() const override { return V3Hash(); } - virtual bool same(const AstNode* samep) const override { return true; } + AstNode* seedp() const { return op1p(); } + bool reset() const { return m_reset; } + bool urandom() const { return m_urandom; } }; class AstURandomRange final : public AstNodeBiop { diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 0345ceb44..465036379 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -836,6 +836,9 @@ public: putsQuoted(nodep->timeunit().ascii()); puts(");\n"); } + virtual void visit(AstRand* nodep) override { + emitOpName(nodep, nodep->emitC(), nodep->seedp(), nullptr, nullptr); + } virtual void visit(AstTime* nodep) override { puts("VL_TIME_UNITED_Q("); if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$time has no units"); diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index dbfa9a101..8c952c9a0 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -288,10 +288,11 @@ private: new AstAssign( nodep->fileline(), new AstVarRef(nodep->fileline(), newvarp, VAccess::WRITE), - new AstOr( - nodep->fileline(), new AstConst(nodep->fileline(), numb1), - new AstAnd(nodep->fileline(), new AstConst(nodep->fileline(), numbx), - new AstRand(nodep->fileline(), nodep->dtypep(), true))))); + new AstOr(nodep->fileline(), new AstConst(nodep->fileline(), numb1), + new AstAnd(nodep->fileline(), + new AstConst(nodep->fileline(), numbx), + new AstRand(nodep->fileline(), AstRand::Reset{}, + nodep->dtypep(), true))))); // Add inits in front of other statement. // In the future, we should stuff the initp into the module's constructor. AstNode* afterp = m_modp->stmtsp()->unlinkFrBackWithNext(); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 556a0cc9c..32590cf9d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1143,12 +1143,12 @@ private: virtual void visit(AstRand* nodep) override { if (m_vup->prelim()) { - nodep->dtypeSetSigned32(); // Says the spec - } - } - virtual void visit(AstURandom* nodep) override { - if (m_vup->prelim()) { - nodep->dtypeSetUInt32(); // Says the spec + if (nodep->urandom()) { + nodep->dtypeSetUInt32(); // Says the spec + } else { + nodep->dtypeSetSigned32(); // Says the spec + } + if (nodep->seedp()) iterateCheckSigned32(nodep, "seed", nodep->seedp(), BOTH); } } virtual void visit(AstURandomRange* nodep) override { diff --git a/src/verilog.y b/src/verilog.y index 4e3fcf687..8ca424f3c 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3711,9 +3711,8 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_PAST '(' expr ',' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $past expr2 and clock arguments"); } | yD_PAST '(' expr ',' expr ',' expr ',' expr')' { $$ = $3; BBUNSUP($1, "Unsupported: $past expr2 and clock arguments"); } | yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); } - // // Seeding is unsupported as would be slow to invalidate all per-thread RNGs - | yD_RANDOM '(' expr ')' { $$ = new AstRand($1); BBUNSUP($1, "Unsupported: Seed on $random. Suggest use +verilator+seed+ runtime flag"); } - | yD_RANDOM parenE { $$ = new AstRand($1); } + | yD_RANDOM '(' expr ')' { $$ = new AstRand($1, $3, false); } + | yD_RANDOM parenE { $$ = new AstRand($1, nullptr, false); } | yD_REALTIME parenE { $$ = new AstTimeD($1, VTimescale(VTimescale::NONE)); } | yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); } | yD_REWIND '(' idClassSel ')' { $$ = new AstFSeek($1, $3, new AstConst($1, 0), new AstConst($1, 0)); } @@ -3742,9 +3741,9 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_TYPENAME '(' exprOrDataType ')' { $$ = new AstAttrOf($1, AstAttrType::TYPENAME, $3); } | yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first | yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); } - | yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); } - | yD_URANDOM '(' expr ')' { $$ = new AstURandom($1); BBUNSUP($1, "Unsupported: Seed on $urandom. Suggest use +verilator+seed+ runtime flag"); } - | yD_URANDOM parenE { $$ = new AstURandom($1); } + | yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1, $3); } + | yD_URANDOM '(' expr ')' { $$ = new AstRand($1, $3, true); } + | yD_URANDOM parenE { $$ = new AstRand($1, nullptr, true); } | yD_URANDOM_RANGE '(' expr ',' expr ')' { $$ = new AstURandomRange($1, $3, $5); } | yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1, $3, $5); } ; diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out index 3507dee82..dc1d81c5a 100644 --- a/test_regress/t/t_debug_emitv.out +++ b/test_regress/t/t_debug_emitv.out @@ -175,7 +175,9 @@ module Vt_debug_emitv; if ((32'sh5 != t.i)) begin $stop; end - t.sum = $urandom; + t.sum = + ???? // RAND + 32'sha; end /*verilator public_flat_rw @(posedge clk)@(negedge clk) t.pubflat*/ diff --git a/test_regress/t/t_debug_emitv.v b/test_regress/t/t_debug_emitv.v index b5c7c5875..5764cedcf 100644 --- a/test_regress/t/t_debug_emitv.v +++ b/test_regress/t/t_debug_emitv.v @@ -146,7 +146,9 @@ module t (/*AUTOARG*/ if (i != 5) $stop; sum = $random; + sum = $random(10); sum = $urandom; + sum = $urandom(10); end endmodule diff --git a/test_regress/t/t_sys_rand_seed.out b/test_regress/t/t_sys_rand_seed.out deleted file mode 100644 index a9ae64425..000000000 --- a/test_regress/t/t_sys_rand_seed.out +++ /dev/null @@ -1,13 +0,0 @@ -%Error-UNSUPPORTED: t/t_sys_rand_seed.v:13:16: Unsupported: Seed on $random. Suggest use +verilator+seed+ runtime flag - 13 | valuea = $random(10); - | ^~~~~~~ -%Error-UNSUPPORTED: t/t_sys_rand_seed.v:14:16: Unsupported: Seed on $random. Suggest use +verilator+seed+ runtime flag - 14 | valueb = $random(10); - | ^~~~~~~ -%Error-UNSUPPORTED: t/t_sys_rand_seed.v:16:16: Unsupported: Seed on $urandom. Suggest use +verilator+seed+ runtime flag - 16 | valuea = $urandom(10); - | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_sys_rand_seed.v:17:16: Unsupported: Seed on $urandom. Suggest use +verilator+seed+ runtime flag - 17 | valueb = $urandom(10); - | ^~~~~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_sys_rand_seed.pl b/test_regress/t/t_sys_rand_seed.pl index 391ec23fd..b46d46042 100755 --- a/test_regress/t/t_sys_rand_seed.pl +++ b/test_regress/t/t_sys_rand_seed.pl @@ -11,12 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( - fails => $Self->{vlt_all}, - expect_filename => $Self->{golden_filename}, ); execute( - ) if !$Self->{vlt_all}; + check_finished => 1, + ); ok(1); 1; diff --git a/test_regress/t/t_urandom.v b/test_regress/t/t_urandom.v index 3a894c6ae..f20529134 100644 --- a/test_regress/t/t_urandom.v +++ b/test_regress/t/t_urandom.v @@ -42,7 +42,6 @@ module t(/*AUTOARG*/); if (v1 != 0 && v1 != 1) $stop; end -`ifndef VERILATOR // Seed stability // Note UVM doesn't use $urandom seeding v1 = $urandom(1); @@ -50,7 +49,6 @@ module t(/*AUTOARG*/); if (v1 != v2) $stop; v2 = $urandom(1); if (v1 != v2) $stop; -`endif `ifdef PROC // Seed stability via process.srandom From 103ba1fb6dd9285d16938f01c7bead5272ac6e3e Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 20 Nov 2020 21:48:11 -0500 Subject: [PATCH 30/91] Commentary --- bin/verilator | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/verilator b/bin/verilator index 3e67e11c9..b059d87e7 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1996,14 +1996,15 @@ section below for descriptions of some of the files that were created. (Verilator included a default compile rule and link rule, since we used --exe and passed a .cpp file on the Verilator command line. Verilator also -then used C to build a final executable. You can also write your own -compile rules, and run make yourself as we'll show in the SYSTEMC section.) +then used C to build a final executable, since we used --build. You +can also write your own compile rules, and run make yourself as we'll show +in the SYSTEMC section. -And now we run it +And now we run it: obj_dir/Vour -And we get as output +And we get as output: Hello World - our.v:2: Verilog $finish From e85a2e860efce1d488c58fa143b575f5f583314c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 23 Nov 2020 23:18:58 -0500 Subject: [PATCH 31/91] Support 'with item.index'. --- Changes | 2 + include/verilated_heavy.h | 106 ++++++++++++++++++----------- src/V3AstNodes.h | 26 ++++--- src/V3EmitC.cpp | 8 ++- src/V3LinkDot.cpp | 32 +++++++-- src/V3Width.cpp | 47 +++++++------ test_regress/t/t_assoc_method.v | 5 ++ test_regress/t/t_dynarray_method.v | 3 + test_regress/t/t_queue_method.v | 5 ++ 9 files changed, 157 insertions(+), 77 deletions(-) diff --git a/Changes b/Changes index 2655ecdfa..68b2adad0 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support $random and $urandom seeds. +*** Support 'with item.index'. + **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] **** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 3346cd2be..c5409364a 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -250,14 +250,18 @@ public: void sort() { std::sort(m_deque.begin(), m_deque.end()); } template void sort(Func with_func) { // with_func returns arbitrary type to use for the sort comparison - std::sort(m_deque.begin(), m_deque.end(), - [=](const T_Value& a, const T_Value& b) { return with_func(a) < with_func(b); }); + std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) { + // index number is meaninless with sort, as it changes + return with_func(0, a) < with_func(0, b); + }); } void rsort() { std::sort(m_deque.rbegin(), m_deque.rend()); } template void rsort(Func with_func) { // with_func returns arbitrary type to use for the sort comparison - std::sort(m_deque.rbegin(), m_deque.rend(), - [=](const T_Value& a, const T_Value& b) { return with_func(a) < with_func(b); }); + std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) { + // index number is meaninless with sort, as it changes + return with_func(0, a) < with_func(0, b); + }); } void reverse() { std::reverse(m_deque.begin(), m_deque.end()); } void shuffle() { std::shuffle(m_deque.begin(), m_deque.end(), VlURNG()); } @@ -289,39 +293,54 @@ public: } template VlQueue find(Func with_func) const { VlQueue out; - for (const auto& i : m_deque) - if (with_func(i)) out.push_back(i); + IData index = 0; + for (const auto& i : m_deque) { + if (with_func(index, i)) out.push_back(i); + ++index; + } return out; } template VlQueue find_index(Func with_func) const { VlQueue out; IData index = 0; for (const auto& i : m_deque) { - if (with_func(i)) out.push_back(index); + if (with_func(index, i)) out.push_back(index); ++index; } return out; } template VlQueue find_first(Func with_func) const { - const auto it = std::find_if(m_deque.begin(), m_deque.end(), with_func); - if (it == m_deque.end()) return VlQueue{}; - return VlQueue::cons(*it); + // Can't use std::find_if as need index number + IData index = 0; + for (const auto& i : m_deque) { + if (with_func(index, i)) return VlQueue::cons(i); + ++index; + } + return VlQueue{}; } template VlQueue find_first_index(Func with_func) const { - const auto it = std::find_if(m_deque.begin(), m_deque.end(), with_func); - if (it == m_deque.end()) return VlQueue{}; - return VlQueue::cons(std::distance(m_deque.begin(), it)); + IData index = 0; + for (const auto& i : m_deque) { + if (with_func(index, i)) return VlQueue::cons(index); + ++index; + } + return VlQueue{}; } template VlQueue find_last(Func with_func) const { - const auto it = std::find_if(m_deque.rbegin(), m_deque.rend(), with_func); - if (it == m_deque.rend()) return VlQueue{}; - return VlQueue::cons(*it); + IData index = m_deque.size() - 1; + for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) { + if (with_func(index, *it)) return VlQueue::cons(*it); + --index; + } + return VlQueue{}; } template VlQueue find_last_index(Func with_func) const { - const auto it = std::find_if(m_deque.rbegin(), m_deque.rend(), with_func); - if (it == m_deque.rend()) return VlQueue{}; - // Return index must be relative to beginning - return VlQueue::cons(m_deque.size() - 1 - std::distance(m_deque.rbegin(), it)); + IData index = m_deque.size() - 1; + for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) { + if (with_func(index, *it)) return VlQueue::cons(index); + --index; + } + return VlQueue{}; } // Reduction operators @@ -343,7 +362,8 @@ public: } template T_Value r_sum(Func with_func) const { T_Value out(0); // Type must have assignment operator - for (const auto& i : m_deque) out += with_func(i); + IData index = 0; + for (const auto& i : m_deque) out += with_func(index++, i); return out; } T_Value r_product() const { @@ -357,9 +377,11 @@ public: template T_Value r_product(Func with_func) const { if (m_deque.empty()) return T_Value(0); auto it = m_deque.begin(); - T_Value out{with_func(*it)}; + IData index = 0; + T_Value out{with_func(index, *it)}; ++it; - for (; it != m_deque.end(); ++it) out *= with_func(*it); + ++index; + for (; it != m_deque.end(); ++it) out *= with_func(index++, *it); return out; } T_Value r_and() const { @@ -373,9 +395,11 @@ public: template T_Value r_and(Func with_func) const { if (m_deque.empty()) return T_Value(0); auto it = m_deque.begin(); - T_Value out{with_func(*it)}; + IData index = 0; + T_Value out{with_func(index, *it)}; ++it; - for (; it != m_deque.end(); ++it) out &= with_func(*it); + ++index; + for (; it != m_deque.end(); ++it) out &= with_func(index, *it); return out; } T_Value r_or() const { @@ -385,7 +409,8 @@ public: } template T_Value r_or(Func with_func) const { T_Value out(0); // Type must have assignment operator - for (const auto& i : m_deque) out |= with_func(i); + IData index = 0; + for (const auto& i : m_deque) out |= with_func(index++, i); return out; } T_Value r_xor() const { @@ -395,7 +420,8 @@ public: } template T_Value r_xor(Func with_func) const { T_Value out(0); // Type must have assignment operator - for (const auto& i : m_deque) out ^= with_func(i); + IData index = 0; + for (const auto& i : m_deque) out ^= with_func(index++, i); return out; } @@ -588,19 +614,19 @@ public: template VlQueue find(Func with_func) const { VlQueue out; for (const auto& i : m_map) - if (with_func(i.second)) out.push_back(i.second); + if (with_func(i.first, i.second)) out.push_back(i.second); return out; } template VlQueue find_index(Func with_func) const { VlQueue out; for (const auto& i : m_map) - if (with_func(i.second)) out.push_back(i.first); + if (with_func(i.first, i.second)) out.push_back(i.first); return out; } template VlQueue find_first(Func with_func) const { const auto it = std::find_if(m_map.begin(), m_map.end(), [=](const std::pair& i) { - return with_func(i.second); + return with_func(i.first, i.second); }); if (it == m_map.end()) return VlQueue{}; return VlQueue::cons(it->second); @@ -608,7 +634,7 @@ public: template VlQueue find_first_index(Func with_func) const { const auto it = std::find_if(m_map.begin(), m_map.end(), [=](const std::pair& i) { - return with_func(i.second); + return with_func(i.first, i.second); }); if (it == m_map.end()) return VlQueue{}; return VlQueue::cons(it->first); @@ -616,7 +642,7 @@ public: template VlQueue find_last(Func with_func) const { const auto it = std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair& i) { - return with_func(i.second); + return with_func(i.first, i.second); }); if (it == m_map.rend()) return VlQueue{}; return VlQueue::cons(it->second); @@ -624,7 +650,7 @@ public: template VlQueue find_last_index(Func with_func) const { const auto it = std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair& i) { - return with_func(i.second); + return with_func(i.first, i.second); }); if (it == m_map.rend()) return VlQueue{}; return VlQueue::cons(it->first); @@ -657,7 +683,7 @@ public: } template T_Value r_sum(Func with_func) const { T_Value out(0); // Type must have assignment operator - for (const auto& i : m_map) out += with_func(i.second); + for (const auto& i : m_map) out += with_func(i.first, i.second); return out; } T_Value r_product() const { @@ -671,9 +697,9 @@ public: template T_Value r_product(Func with_func) const { if (m_map.empty()) return T_Value(0); auto it = m_map.begin(); - T_Value out{with_func(it->second)}; + T_Value out{with_func(it->first, it->second)}; ++it; - for (; it != m_map.end(); ++it) out *= with_func(it->second); + for (; it != m_map.end(); ++it) out *= with_func(it->first, it->second); return out; } T_Value r_and() const { @@ -687,9 +713,9 @@ public: template T_Value r_and(Func with_func) const { if (m_map.empty()) return T_Value(0); auto it = m_map.begin(); - T_Value out{with_func(it->second)}; + T_Value out{with_func(it->first, it->second)}; ++it; - for (; it != m_map.end(); ++it) out &= with_func(it->second); + for (; it != m_map.end(); ++it) out &= with_func(it->first, it->second); return out; } T_Value r_or() const { @@ -699,7 +725,7 @@ public: } template T_Value r_or(Func with_func) const { T_Value out(0); // Type must have assignment operator - for (const auto& i : m_map) out |= with_func(i.second); + for (const auto& i : m_map) out |= with_func(i.first, i.second); return out; } T_Value r_xor() const { @@ -709,7 +735,7 @@ public: } template T_Value r_xor(Func with_func) const { T_Value out(0); // Type must have assignment operator - for (const auto& i : m_map) out ^= with_func(i.second); + for (const auto& i : m_map) out ^= with_func(i.first, i.second); return out; } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index f8632dc49..9384f4e08 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -3107,11 +3107,13 @@ class AstLambdaArgRef final : public AstNodeMath { // optimizations and AstVar's are painful to remove. private: string m_name; // Name of variable + bool m_index; // Index, not value public: - AstLambdaArgRef(FileLine* fl, const string& name) + AstLambdaArgRef(FileLine* fl, const string& name, bool index) : ASTGEN_SUPER(fl) - , m_name{name} {} + , m_name{name} + , m_index(index) {} ASTNODE_NODE_FUNCS(LambdaArgRef) virtual V3Hash sameHash() const override { return V3Hash(); } virtual bool same(const AstNode* samep) const override { return true; } @@ -3122,31 +3124,37 @@ public: virtual int instrCount() const override { return widthInstrs(); } virtual string name() const override { return m_name; } // * = Var name virtual void name(const string& name) override { m_name = name; } + bool index() const { return m_index; } }; class AstWith final : public AstNodeStmt { // Used as argument to method, then to AstCMethodHard // dtypep() contains the with lambda's return dtype // Parents: funcref (similar to AstArg) - // Children: VAR that declares the index variable + // Children: LambdaArgRef that declares the item variable + // Children: LambdaArgRef that declares the item.index variable // Children: math (equation establishing the with) public: - AstWith(FileLine* fl, AstLambdaArgRef* argrefp, AstNode* exprp) + AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp, + AstNode* exprp) : ASTGEN_SUPER(fl) { - addOp1p(argrefp); - addNOp2p(exprp); + addOp1p(indexArgRefp); + addOp2p(valueArgRefp); + addNOp3p(exprp); } ASTNODE_NODE_FUNCS(With) virtual V3Hash sameHash() const override { return V3Hash(); } virtual bool same(const AstNode* samep) const override { return true; } virtual bool hasDType() const override { return true; } virtual const char* broken() const override { - BROKEN_RTN(!argrefp()); // varp needed to know lambda's arg dtype + BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype + BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype return nullptr; } // - AstLambdaArgRef* argrefp() const { return VN_CAST(op1p(), LambdaArgRef); } - AstNode* exprp() const { return op2p(); } + AstLambdaArgRef* indexArgRefp() const { return VN_CAST(op1p(), LambdaArgRef); } + AstLambdaArgRef* valueArgRefp() const { return VN_CAST(op2p(), LambdaArgRef); } + AstNode* exprp() const { return op3p(); } }; //###################################################################### diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 465036379..35b1c4162 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -430,8 +430,12 @@ public: virtual void visit(AstWith* nodep) override { // With uses a C++11 lambda putbs("[=]("); - if (auto* argrefp = nodep->argrefp()) { - putbs(argrefp->dtypep()->cType(nodep->argrefp()->nameProtect(), false, false)); + if (auto* argrefp = nodep->indexArgRefp()) { + putbs(argrefp->dtypep()->cType(argrefp->nameProtect(), false, false)); + puts(","); + } + if (auto* argrefp = nodep->valueArgRefp()) { + putbs(argrefp->dtypep()->cType(argrefp->nameProtect(), false, false)); } // Probably fragile, V3Task may need to convert to a AstCReturn puts(") { return "); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index d84b344db..e93d0815a 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1281,9 +1281,10 @@ class LinkDotFindVisitor final : public AstNVisitor { VL_DO_DANGLING(argp->unlinkFrBackWithNext()->deleteTree(), argp); } // Type depends on the method used, let V3Width figure it out later - auto* argrefp = new AstLambdaArgRef(argFl, name); - auto* newp - = new AstWith(nodep->fileline(), argrefp, nodep->exprp()->unlinkFrBackWithNext()); + auto* indexArgRefp = new AstLambdaArgRef(argFl, name + "__DOT__index", true); + auto* valueArgRefp = new AstLambdaArgRef(argFl, name, false); + auto* newp = new AstWith(nodep->fileline(), indexArgRefp, valueArgRefp, + nodep->exprp()->unlinkFrBackWithNext()); funcrefp->addPinsp(newp); nodep->replaceWith(funcrefp->unlinkFrBack()); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -1298,9 +1299,11 @@ class LinkDotFindVisitor final : public AstNVisitor { m_curSymp = m_statep->insertBlock(m_curSymp, "__Vwith" + cvtToStr(m_modWithNum), nodep, m_packagep); m_curSymp->fallbackp(oldCurSymp); - UASSERT_OBJ(nodep->argrefp(), nodep, "Missing lambda argref"); + UASSERT_OBJ(nodep->indexArgRefp(), nodep, "Missing lambda argref"); + UASSERT_OBJ(nodep->valueArgRefp(), nodep, "Missing lambda argref"); // Insert argref's name into symbol table - m_statep->insertSym(m_curSymp, nodep->argrefp()->name(), nodep->argrefp(), nullptr); + m_statep->insertSym(m_curSymp, nodep->valueArgRefp()->name(), nodep->valueArgRefp(), + nullptr); } } @@ -2034,6 +2037,7 @@ private: && (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) { m_ds.m_unlinkedScopep = nodep->lhsp(); } + if (VN_IS(nodep->lhsp(), LambdaArgRef)) { m_ds.m_unlinkedScopep = nodep->lhsp(); } if (!m_ds.m_dotErr) { // Once something wrong, give up // Top 'final' dot RHS is final RHS, else it's a // DOT(DOT(x,*here*),real-rhs) which we consider a RHS @@ -2089,7 +2093,16 @@ private: nodep->v3warn(E_UNSUPPORTED, "Unsupported: super"); m_ds.m_dotErr = true; } - if (m_ds.m_dotPos == DP_MEMBER) { + if (m_ds.m_dotPos == DP_FINAL && VN_IS(m_ds.m_unlinkedScopep, LambdaArgRef) + && nodep->name() == "index") { + // 'with' statement's 'item.index' + iterateChildren(nodep); + auto newp = new AstLambdaArgRef(nodep->fileline(), + m_ds.m_unlinkedScopep->name() + "__DOT__index", true); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + return; + } else if (m_ds.m_dotPos == DP_MEMBER) { // Found a Var, everything following is membership. {scope}.{var}.HERE {member} AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack(); AstNode* newp @@ -2301,7 +2314,7 @@ private: } } else if (AstLambdaArgRef* argrefp = VN_CAST(foundp->nodep(), LambdaArgRef)) { if (allowVar) { - AstNode* newp = new AstLambdaArgRef(nodep->fileline(), argrefp->name()); + AstNode* newp = new AstLambdaArgRef(nodep->fileline(), argrefp->name(), false); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); ok = true; @@ -2730,6 +2743,11 @@ private: } m_ds.m_dotSymp = m_curSymp = oldCurSymp; } + virtual void visit(AstLambdaArgRef* nodep) override { + UINFO(5, " " << nodep << endl); + // No checknodot(nodep), visit(AstScope) will check for LambdaArgRef + iterateChildren(nodep); + } virtual void visit(AstClass* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 32590cf9d..a79bb2834 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -201,7 +201,7 @@ private: AstCell* m_cellp = nullptr; // Current cell for arrayed instantiations AstNodeFTask* m_ftaskp = nullptr; // Current function/task AstNodeProcedure* m_procedurep = nullptr; // Current final/always - AstLambdaArgRef* m_lambdaArgRefp = nullptr; // Argument to above lambda + AstWith* m_withp = nullptr; // Current 'with' statement AstFunc* m_funcp = nullptr; // Current function AstAttrOf* m_attrp = nullptr; // Current attribute bool m_doGenerate; // Do errors later inside generate statement @@ -2373,10 +2373,12 @@ private: } } AstWith* methodWithArgument(AstMethodCall* nodep, bool required, bool arbReturn, - AstNodeDType* returnDtp, AstNodeDType* argDtp) { + AstNodeDType* returnDtp, AstNodeDType* indexDtp, + AstNodeDType* valueDtp) { UASSERT_OBJ(arbReturn || returnDtp, nodep, "Null return type"); if (AstWith* withp = VN_CAST(nodep->pinsp(), With)) { - withp->argrefp()->dtypep(argDtp); + withp->indexArgRefp()->dtypep(indexDtp); + withp->valueArgRefp()->dtypep(valueDtp); userIterate(withp, WidthVP(returnDtp, BOTH).p()); withp->unlinkFrBack(); return withp; @@ -2570,7 +2572,7 @@ private: || nodep->name() == "sum" || nodep->name() == "product") { // All value return AstWith* withp = methodWithArgument(nodep, false, false, adtypep->subDTypep(), - adtypep->subDTypep()); + adtypep->keyDTypep(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2592,7 +2594,7 @@ private: } else if (nodep->name() == "find" || nodep->name() == "find_first" || nodep->name() == "find_last") { AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), - adtypep->subDTypep()); + adtypep->keyDTypep(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2602,7 +2604,7 @@ private: } else if (nodep->name() == "find_index" || nodep->name() == "find_first_index" || nodep->name() == "find_last_index") { AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), - adtypep->subDTypep()); + adtypep->keyDTypep(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2663,7 +2665,7 @@ private: || nodep->name() == "sum" || nodep->name() == "product") { // All value return AstWith* withp = methodWithArgument(nodep, false, false, adtypep->subDTypep(), - adtypep->subDTypep()); + nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2674,7 +2676,8 @@ private: || nodep->name() == "sort" || nodep->name() == "rsort") { AstWith* withp = nullptr; if (nodep->name() == "sort" || nodep->name() == "rsort") { - withp = methodWithArgument(nodep, false, true, nullptr, adtypep->subDTypep()); + withp = methodWithArgument(nodep, false, true, nullptr, nodep->findUInt32DType(), + adtypep->subDTypep()); } methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); @@ -2696,7 +2699,7 @@ private: } else if (nodep->name() == "find" || nodep->name() == "find_first" || nodep->name() == "find_last" || nodep->name() == "find_index") { AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), - adtypep->subDTypep()); + nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2706,7 +2709,7 @@ private: } else if (nodep->name() == "find_index" || nodep->name() == "find_first_index" || nodep->name() == "find_last_index") { AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), - adtypep->subDTypep()); + nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2794,7 +2797,7 @@ private: } else if (nodep->name() == "and" || nodep->name() == "or" || nodep->name() == "xor" || nodep->name() == "sum" || nodep->name() == "product") { AstWith* withp = methodWithArgument(nodep, false, false, adtypep->subDTypep(), - adtypep->subDTypep()); + nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2805,7 +2808,8 @@ private: || nodep->name() == "sort" || nodep->name() == "rsort") { AstWith* withp = nullptr; if (nodep->name() == "sort" || nodep->name() == "rsort") { - withp = methodWithArgument(nodep, false, true, nullptr, adtypep->subDTypep()); + withp = methodWithArgument(nodep, false, true, nullptr, nodep->findUInt32DType(), + adtypep->subDTypep()); } methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); @@ -2827,7 +2831,7 @@ private: } else if (nodep->name() == "find" || nodep->name() == "find_first" || nodep->name() == "find_last") { AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), - adtypep->subDTypep()); + nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2837,7 +2841,7 @@ private: } else if (nodep->name() == "find_index" || nodep->name() == "find_first_index" || nodep->name() == "find_last_index") { AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), - adtypep->subDTypep()); + nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -4422,10 +4426,11 @@ private: virtual void visit(AstWith* nodep) override { // Should otherwise be underneath a method call AstNodeDType* vdtypep = m_vup->dtypeNullSkipRefp(); - VL_RESTORER(m_lambdaArgRefp); + VL_RESTORER(m_withp); { - m_lambdaArgRefp = nodep->argrefp(); - userIterateChildren(nodep->argrefp(), nullptr); + m_withp = nodep; + userIterateChildren(nodep->indexArgRefp(), nullptr); + userIterateChildren(nodep->valueArgRefp(), nullptr); if (vdtypep) { userIterateAndNext(nodep->exprp(), WidthVP(nodep->dtypep(), PRELIM).p()); } else { // 'sort with' allows arbitrary type @@ -4437,8 +4442,12 @@ private: } } virtual void visit(AstLambdaArgRef* nodep) override { - UASSERT_OBJ(m_lambdaArgRefp, nodep, "LambdaArgRef not underneath with lambda"); - nodep->dtypeFrom(m_lambdaArgRefp); + UASSERT_OBJ(m_withp, nodep, "LambdaArgRef not underneath 'with' lambda"); + if (nodep->index()) { + nodep->dtypeFrom(m_withp->indexArgRefp()); + } else { + nodep->dtypeFrom(m_withp->valueArgRefp()); + } } virtual void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. That's faster diff --git a/test_regress/t/t_assoc_method.v b/test_regress/t/t_assoc_method.v index 29c8372e1..684e90c68 100644 --- a/test_regress/t/t_assoc_method.v +++ b/test_regress/t/t_assoc_method.v @@ -67,6 +67,11 @@ module t (/*AUTOARG*/); qi = q.find_last_index with (item == 20); v = $sformatf("%p", qi); `checks(v, "'{}"); + qi = q.find_index with (item.index == 12); + v = $sformatf("%p", qi); `checks(v, "'{'hc} "); + qi = q.find with (item.index == 12); + v = $sformatf("%p", qi); `checks(v, "'{'h2} "); + qv = q.min; v = $sformatf("%p", qv); `checks(v, "'{'h1} "); qv = q.max; diff --git a/test_regress/t/t_dynarray_method.v b/test_regress/t/t_dynarray_method.v index 21a778dc5..3142782b5 100644 --- a/test_regress/t/t_dynarray_method.v +++ b/test_regress/t/t_dynarray_method.v @@ -100,6 +100,9 @@ module t (/*AUTOARG*/); qi = d.find_last_index with (item == 20); `checkh(qi.size, 0); + qi = d.find_index with (item.index == 2); + v = $sformatf("%p", qi); `checks(v, "'{'h2} "); + qv = d.min; v = $sformatf("%p", qv); `checks(v, "'{'h1} "); qv = d.max; diff --git a/test_regress/t/t_queue_method.v b/test_regress/t/t_queue_method.v index d5429c88d..3e8dfbf1a 100644 --- a/test_regress/t/t_queue_method.v +++ b/test_regress/t/t_queue_method.v @@ -95,6 +95,11 @@ module t (/*AUTOARG*/); qi = q.find_last_index with (item == 20); `checkh(qi.size, 0); + qi = q.find_index with (item.index == 2); + v = $sformatf("%p", qi); `checks(v, "'{'h2} "); + qi = q.find_index with (item.index == item); + v = $sformatf("%p", qi); `checks(v, "'{'h2, 'h3, 'h4} "); + qv = q.min; v = $sformatf("%p", qv); `checks(v, "'{'h1} "); qv = q.max; From 35374f09b4ac09e74ab1d1eaaa6cbb70f2a99b4c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 18:15:49 -0500 Subject: [PATCH 32/91] Add error on class extending itself --- src/V3LinkDot.cpp | 23 +++++++++++++--------- test_regress/t/t_class_extends_rec_bad.out | 4 ++++ test_regress/t/t_class_extends_rec_bad.pl | 19 ++++++++++++++++++ test_regress/t/t_class_extends_rec_bad.v | 13 ++++++++++++ 4 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 test_regress/t/t_class_extends_rec_bad.out create mode 100755 test_regress/t/t_class_extends_rec_bad.pl create mode 100644 test_regress/t/t_class_extends_rec_bad.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index e93d0815a..9eede8663 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2774,15 +2774,20 @@ private: if (AstClass* classp = VN_CAST(foundp->nodep(), Class)) { UINFO(8, "Import to " << nodep << " from export class " << classp << endl); - AstClassRefDType* newp - = new AstClassRefDType{nodep->fileline(), classp}; - cextp->childDTypep(newp); - classp->isExtended(true); - nodep->isExtended(true); - VSymEnt* srcp = m_statep->getNodeSym(classp); - m_curSymp->importFromClass(m_statep->symsp(), srcp); - VL_DO_DANGLING(cpackagerefp->unlinkFrBack()->deleteTree(), - cpackagerefp); + if (classp == nodep) { + cextp->v3error("Attempting to extend class " + << nodep->prettyNameQ() << " from itself"); + } else { + AstClassRefDType* newp + = new AstClassRefDType{nodep->fileline(), classp}; + cextp->childDTypep(newp); + classp->isExtended(true); + nodep->isExtended(true); + VSymEnt* srcp = m_statep->getNodeSym(classp); + m_curSymp->importFromClass(m_statep->symsp(), srcp); + VL_DO_DANGLING(cpackagerefp->unlinkFrBack()->deleteTree(), + cpackagerefp); + } ok = true; } } diff --git a/test_regress/t/t_class_extends_rec_bad.out b/test_regress/t/t_class_extends_rec_bad.out new file mode 100644 index 000000000..c5ffe68ce --- /dev/null +++ b/test_regress/t/t_class_extends_rec_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_class_extends_rec_bad.v:7:31: Attempting to extend class 'RecursiveExtCls' from itself + 7 | class RecursiveExtCls extends RecursiveExtCls; + | ^~~~~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_extends_rec_bad.pl b/test_regress/t/t_class_extends_rec_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_class_extends_rec_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_extends_rec_bad.v b/test_regress/t/t_class_extends_rec_bad.v new file mode 100644 index 000000000..2470977f8 --- /dev/null +++ b/test_regress/t/t_class_extends_rec_bad.v @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class RecursiveExtCls extends RecursiveExtCls; + int i; +endclass + +module t (/*AUTOARG*/); + RecursiveExtCls cls = new; +endmodule From dc306cf371bd5ece54d3965ca7a9938f957ca6ad Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 18:35:12 -0500 Subject: [PATCH 33/91] Internal debug: avoid segflt with gdb "pnt" --- src/.gdbinit | 6 +++--- src/V3Ast.cpp | 48 ++++++++++++++++++++++++++++++------------------ src/V3Ast.h | 6 +++--- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/.gdbinit b/src/.gdbinit index 17532d0d2..8e973680f 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -7,21 +7,21 @@ # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 define pn - call $arg0->dumpGdb() + call AstNode::dumpGdb($arg0) end document pn Verilator: Print single AstNode NODEP end define pnt - call $arg0->dumpTreeGdb() + call AstNode::dumpTreeGdb($arg0) end document pnt Verilator: Print AstNode NODEP's tree end define dtf - call AstNode::dumpTreeFileGdb(0) + call AstNode::dumpTreeFileGdb($arg0, 0) end document dtf Verilator: Dump AstNode tree to file diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 234dd49d9..9e2b9843b 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -1029,28 +1029,40 @@ void AstNode::checkTree() { } // cppcheck-suppress unusedFunction // Debug only -void AstNode::dumpGdb() { // For GDB only // LCOV_EXCL_LINE - dumpGdbHeader(); // LCOV_EXCL_LINE +void AstNode::dumpGdb(const AstNode* nodep) { // For GDB only // LCOV_EXCL_LINE + if (!nodep) { + cout << "" << endl; + return; + } + nodep->dumpGdbHeader(); cout << " "; - dump(cout); - cout << endl; // LCOV_EXCL_LINE -} + nodep->dump(cout); + cout << endl; +} // LCOV_EXCL_STOP // cppcheck-suppress unusedFunction // Debug only -void AstNode::dumpGdbHeader() const { // For GDB only // LCOV_EXCL_LINE - dumpPtrs(cout); // LCOV_EXCL_LINE - cout << " Fileline = " << fileline() << endl; // LCOV_EXCL_LINE -} +void AstNode::dumpGdbHeader() const { // For GDB only // LCOV_EXCL_START + dumpPtrs(cout); + cout << " Fileline = " << fileline() << endl; +} // LCOV_EXCL_STOP // cppcheck-suppress unusedFunction // Debug only -void AstNode::dumpTreeGdb() { // For GDB only // LCOV_EXCL_LINE - dumpGdbHeader(); // LCOV_EXCL_LINE - dumpTree(cout); // LCOV_EXCL_LINE -} +void AstNode::dumpTreeGdb(const AstNode* nodep) { // For GDB only // LCOV_EXCL_START + if (!nodep) { + cout << "" << endl; + return; + } + nodep->dumpGdbHeader(); + nodep->dumpTree(cout); +} // LCOV_EXCL_STOP // cppcheck-suppress unusedFunction // Debug only -void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only // LCOV_EXCL_LINE - string filename - = filenamep ? filenamep : v3Global.debugFilename("debug.tree", 98); // LCOV_EXCL_LINE - v3Global.rootp()->dumpTreeFile(filename); // LCOV_EXCL_LINE -} +void AstNode::dumpTreeFileGdb(const AstNode* nodep, // LCOV_EXCL_START + const char* filenamep) { // For GDB only + if (!nodep) { + cout << "" << endl; + return; + } + string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree", 98); + v3Global.rootp()->dumpTreeFile(filename); +} // LCOV_EXCL_STOP // cppcheck-suppress unusedFunction // Debug only void AstNode::checkIter() const { diff --git a/src/V3Ast.h b/src/V3Ast.h index 5326f1515..01ff69a85 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1761,7 +1761,7 @@ public: string warnOther() const { return fileline()->warnOther(); } virtual void dump(std::ostream& str = std::cout) const; - void dumpGdb(); // For GDB only + static void dumpGdb(const AstNode* nodep); // For GDB only void dumpGdbHeader() const; // METHODS - Tree modifications @@ -1811,12 +1811,12 @@ public: void dumpTree(const string& indent, int maxDepth = 0) const { dumpTree(cout, indent, maxDepth); } - void dumpTreeGdb(); // For GDB only + static void dumpTreeGdb(const AstNode* nodep); // For GDB only void dumpTreeAndNext(std::ostream& os = std::cout, const string& indent = " ", int maxDepth = 0) const; void dumpTreeFile(const string& filename, bool append = false, bool doDump = true, bool doCheck = true); - static void dumpTreeFileGdb(const char* filenamep = nullptr); + static void dumpTreeFileGdb(const AstNode* nodep, const char* filenamep = nullptr); // METHODS - queries // Changes control flow, disable some optimizations From cf09a9b6d260bc7f35fc4aa3cb3d5c7a76917d2e Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 18:45:36 -0500 Subject: [PATCH 34/91] Commentary --- docs/internals.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/internals.adoc b/docs/internals.adoc index fdf08a899..557d33b5e 100644 --- a/docs/internals.adoc +++ b/docs/internals.adoc @@ -959,9 +959,9 @@ Then, when the watch fires, to break at every following change to that node: To print a node: pn nodep - # or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit + # or: call dumpGdb(nodep) # aliased to "pn" in src/.gdbinit pnt nodep - # or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit + # or: call dumpTreeGdb(nodep) # aliased to "pnt" in src/.gdbinit When GDB halts, it is useful to understand that the backtrace will commonly show the iterator functions between each invocation of `visit` in the From fd21a41acd44ef4b1e0f85c49e6971dfb7ed0fbe Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 21:28:04 -0500 Subject: [PATCH 35/91] Internals: Minor cleanups before class fix (#2654). No functional change intended. --- src/V3AstNodes.cpp | 10 +++++----- src/V3AstNodes.h | 2 +- src/V3CCtors.cpp | 6 ++---- src/V3Dead.cpp | 25 +++++++++++-------------- src/V3LinkDot.cpp | 5 ++--- src/V3SplitVar.cpp | 6 ++---- 6 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 3d1b60705..7db866c99 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1526,11 +1526,13 @@ void AstVarScope::dump(std::ostream& str) const { str << " ->UNLINKED"; } } -void AstNodeVarRef::dump(std::ostream& str) const { this->AstNodeMath::dump(str); } -void AstVarXRef::dump(std::ostream& str) const { - this->AstNodeVarRef::dump(str); +void AstNodeVarRef::dump(std::ostream& str) const { + this->AstNodeMath::dump(str); if (packagep()) str << " pkg=" << nodeAddr(packagep()); str << " " << access().arrow() << " "; +} +void AstVarXRef::dump(std::ostream& str) const { + this->AstNodeVarRef::dump(str); str << ".=" << dotted() << " "; if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - "; if (varScopep()) { @@ -1543,8 +1545,6 @@ void AstVarXRef::dump(std::ostream& str) const { } void AstVarRef::dump(std::ostream& str) const { this->AstNodeVarRef::dump(str); - if (packagep()) str << " pkg=" << nodeAddr(packagep()); - str << " " << access().arrow() << " "; if (varScopep()) { varScopep()->dump(str); } else if (varp()) { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 9384f4e08..924b46c6f 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1256,7 +1256,7 @@ public: AstNodeModule* packagep() const { return m_packagep; } void packagep(AstNodeModule* nodep) { m_packagep = nodep; } AstNode* typeofp() const { return op2p(); } - AstNode* classOrPackagep() const { return op3p(); } + AstNode* classOrPackageOpp() const { return op3p(); } AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } }; diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index 1dc6b9b04..65b98c3b1 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -42,8 +42,8 @@ private: AstNodeModule* m_modp; // Current module AstCFunc* m_tlFuncp; // Top level function being built AstCFunc* m_funcp; // Current function - int m_numStmts; // Number of statements output - int m_funcNum; // Function number being built + int m_numStmts = 0; // Number of statements output + int m_funcNum = 0; // Function number being built public: void add(AstNode* nodep) { @@ -76,8 +76,6 @@ public: m_argsp = argsp; m_callargsp = callargsp; m_modp = nodep; - m_numStmts = 0; - m_funcNum = 0; m_tlFuncp = new AstCFunc(nodep->fileline(), basename, nullptr, "void"); m_tlFuncp->declPrivate(true); m_tlFuncp->isStatic(false); diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 648d4d641..0136a8166 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -30,9 +30,8 @@ // Note on packagep: After the V3Scope/V3LinkDotScoped stage, package links // are no longer used, but their presence prevents us from removing empty // packages. As the links as no longer used after V3Scope, we remove them -// here after scoping to allow more dead node -// removal. -// ************************************************************************* +// here after scoping to allow more dead node removal. +//************************************************************************* #include "config_build.h" #include "verilatedos.h" @@ -83,7 +82,7 @@ private: typedef std::multimap AssignMap; // STATE - AstNodeModule* m_modp; // Current module + AstNodeModule* m_modp = nullptr; // Current module // List of all encountered to avoid another loop through tree std::vector m_varsp; std::vector m_dtypesp; @@ -93,10 +92,10 @@ private: std::vector m_classesp; AssignMap m_assignMap; // List of all simple assignments for each variable - bool m_elimUserVars; // Allow removal of user's vars - bool m_elimDTypes; // Allow removal of DTypes - bool m_elimCells; // Allow removal of Cells - bool m_sideEffect; // Side effects discovered in assign RHS + const bool m_elimUserVars; // Allow removal of user's vars + const bool m_elimDTypes; // Allow removal of DTypes + const bool m_elimCells; // Allow removal of Cells + bool m_sideEffect = false; // Side effects discovered in assign RHS // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -438,12 +437,10 @@ private: public: // CONSTRUCTORS DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes, - bool elimCells) { - m_modp = nullptr; - m_elimCells = elimCells; - m_elimUserVars = elimUserVars; - m_elimDTypes = elimDTypes; - m_sideEffect = false; + bool elimCells) + : m_elimUserVars{elimUserVars} + , m_elimDTypes{elimDTypes} + , m_elimCells{elimCells} { // Prepare to remove some datatypes nodep->typeTablep()->clearCache(); // Operate on whole netlist diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 9eede8663..720443f2b 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -777,6 +777,7 @@ class LinkDotFindVisitor final : public AstNVisitor { bool standalonePkg = !m_modSymp && (m_statep->forPrearray() && VN_IS(nodep, Package)); bool doit = (m_modSymp || standalonePkg); VL_RESTORER(m_scope); + VL_RESTORER(m_packagep); VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); VL_RESTORER(m_paramNum); @@ -833,8 +834,6 @@ class LinkDotFindVisitor final : public AstNVisitor { // Can't remove now, as our backwards iterator will throw up UINFO(5, "Module not under any CELL or top - dead module: " << nodep << endl); } - // Prep for next - m_packagep = nullptr; } virtual void visit(AstClass* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit"); @@ -2824,7 +2823,7 @@ private: virtual void visit(AstRefDType* nodep) override { // Resolve its reference if (nodep->user3SetOnce()) return; - if (AstNode* cpackagep = nodep->classOrPackagep()) { + if (AstNode* cpackagep = nodep->classOrPackageOpp()) { if (AstClassOrPackageRef* cpackagerefp = VN_CAST(cpackagep, ClassOrPackageRef)) { if (cpackagerefp->packagep()) { nodep->packagep(cpackagerefp->packagep()); diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index fd191ec24..e3663a476 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -959,7 +959,7 @@ public: class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { typedef std::map PackedVarRefMap; AstNetlist* m_netp; - AstNodeModule* m_modp; // Current module (just for log) + AstNodeModule* m_modp = nullptr; // Current module (just for log) int m_numSplit; // Total number of split variables // key:variable to be split. value:location where the variable is referenced. PackedVarRefMap m_refs; @@ -1207,9 +1207,7 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { public: // When reusing the information from SplitUnpackedVarVisitor SplitPackedVarVisitor(AstNetlist* nodep, SplitVarRefsMap& refs) - : m_netp{nodep} - , m_modp{nullptr} - , m_numSplit{0} { + : m_netp{nodep} { // If you want ignore refs and walk the tne entire AST, // just call iterateChildren(m_modp) and split() for each module for (auto& i : refs) { From dc1f44840d6f7a66fdaa596c6e0e4a982ab17741 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 21:34:11 -0500 Subject: [PATCH 36/91] Internals: Fix not clearing packagep on some assignments. Should affect assertions only. --- src/V3Dead.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 0136a8166..e0e4fab26 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -106,6 +106,9 @@ private: } if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc(); } + void checkVarRef(AstNodeVarRef* nodep) { + if (nodep->packagep() && m_elimCells) { nodep->packagep(nullptr); } + } void checkDType(AstNodeDType* nodep) { if (!nodep->generic() // Don't remove generic types && m_elimDTypes // dtypes stick around until post-widthing @@ -159,20 +162,16 @@ private: } virtual void visit(AstNodeVarRef* nodep) override { + // Note NodeAssign skips calling this in some cases iterateChildren(nodep); checkAll(nodep); + checkVarRef(nodep); if (nodep->varScopep()) { nodep->varScopep()->user1Inc(); nodep->varScopep()->varp()->user1Inc(); } if (nodep->varp()) nodep->varp()->user1Inc(); - if (nodep->packagep()) { - if (m_elimCells) { - nodep->packagep(nullptr); - } else { - nodep->packagep()->user1Inc(); - } - } + if (nodep->packagep()) nodep->packagep()->user1Inc(); } virtual void visit(AstNodeFTaskRef* nodep) override { iterateChildren(nodep); @@ -276,19 +275,22 @@ private: // See if simple assignments to variables may be eliminated because // that variable is never used. // Similar code in V3Life - m_sideEffect = false; - iterateAndNextNull(nodep->rhsp()); - checkAll(nodep); - // Has to be direct assignment without any EXTRACTing. - AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); - if (varrefp && !m_sideEffect - && varrefp->varScopep()) { // For simplicity, we only remove post-scoping - m_assignMap.insert(make_pair(varrefp->varScopep(), nodep)); - checkAll(varrefp); // Must track reference to dtype() - } else { // Track like any other statement - iterateAndNextNull(nodep->lhsp()); + VL_RESTORER(m_sideEffect); + { + m_sideEffect = false; + iterateAndNextNull(nodep->rhsp()); + checkAll(nodep); + // Has to be direct assignment without any EXTRACTing. + AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); + if (varrefp && !m_sideEffect + && varrefp->varScopep()) { // For simplicity, we only remove post-scoping + m_assignMap.insert(make_pair(varrefp->varScopep(), nodep)); + checkAll(varrefp); // Must track reference to dtype() + checkVarRef(varrefp); + } else { // Track like any other statement + iterateAndNextNull(nodep->lhsp()); + } } - checkAll(nodep); } //----- From b0cb43b2f221d03716fb4b279ad5fcbcc4a2af3f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 21:41:32 -0500 Subject: [PATCH 37/91] Fix not iterating some extended classes depending on declaration order. --- src/V3Width.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index a79bb2834..ae0c2731f 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2203,6 +2203,9 @@ private: } virtual void visit(AstClass* nodep) override { if (nodep->didWidthAndSet()) return; + // Must do extends first, as we may in functions under this class + // start following a tree of extends that takes us to other classes + userIterateAndNext(nodep->extendsp(), nullptr); userIterateChildren(nodep, nullptr); // First size all members nodep->repairCache(); } From e1c45440fc745a9ed5cd92d3cc3c20e6a243f46d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 21:56:03 -0500 Subject: [PATCH 38/91] Internals: Rename packagep(). No functional change. --- src/V3Ast.h | 18 +++---- src/V3AstNodes.cpp | 4 +- src/V3AstNodes.h | 38 +++++++-------- src/V3CUse.cpp | 2 +- src/V3Class.cpp | 2 +- src/V3Dead.cpp | 32 ++++++------- src/V3Inline.cpp | 2 +- src/V3Inst.cpp | 2 +- src/V3LinkDot.cpp | 115 +++++++++++++++++++++++---------------------- src/V3Scope.cpp | 6 +-- src/V3SplitVar.cpp | 2 +- src/V3SymTable.h | 12 ++--- src/V3Width.cpp | 8 ++-- src/verilog.y | 6 +-- 14 files changed, 126 insertions(+), 123 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index 01ff69a85..405d3ad73 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2298,7 +2298,7 @@ private: VAccess m_access; // Left hand side assignment AstVar* m_varp; // [AfterLink] Pointer to variable itself AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy - AstNodeModule* m_packagep = nullptr; // Package hierarchy + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy string m_name; // Name of variable string m_hiername; // Scope converted into name-> for emitting bool m_hierThis = false; // Hiername points to "this" function @@ -2336,8 +2336,8 @@ public: void hiername(const string& hn) { m_hiername = hn; } bool hierThis() const { return m_hierThis; } void hierThis(bool flag) { m_hierThis = flag; } - AstNodeModule* packagep() const { return m_packagep; } - void packagep(AstNodeModule* nodep) { m_packagep = nodep; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } // Know no children, and hot function, so skip iterator for speed // See checkTreeIter also that asserts no children // cppcheck-suppress functionConst @@ -2723,8 +2723,8 @@ public: void addFvarp(AstNode* nodep) { addNOp1p(nodep); } bool isFunction() const { return fvarp() != nullptr; } // op2 = Class/package scope - AstNode* packagep() const { return op2p(); } - void packagep(AstNode* nodep) { setNOp2p(nodep); } + AstNode* classOrPackagep() const { return op2p(); } + void classOrPackagep(AstNode* nodep) { setNOp2p(nodep); } // op3 = Statements/Ports/Vars AstNode* stmtsp() const { return op3p(); } // op3 = List of statements void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } @@ -2774,7 +2774,7 @@ class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt { // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. private: AstNodeFTask* m_taskp = nullptr; // [AfterLink] Pointer to task referenced - AstNodeModule* m_packagep = nullptr; // Package hierarchy + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy string m_name; // Name of variable string m_dotted; // Dotted part of scope the name()ed task/func is under or "" string m_inlinedDots; // Dotted hierarchy flattened out @@ -2808,8 +2808,8 @@ public: void taskp(AstNodeFTask* taskp) { m_taskp = taskp; } virtual void name(const string& name) override { m_name = name; } void dotted(const string& name) { m_dotted = name; } - AstNodeModule* packagep() const { return m_packagep; } - void packagep(AstNodeModule* nodep) { m_packagep = nodep; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } bool pli() const { return m_pli; } void pli(bool flag) { m_pli = flag; } // op1 = namep @@ -2994,7 +2994,7 @@ inline VNumRange AstNodeArrayDType::declRange() const { inline const char* AstNodeFTaskRef::broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); - BROKEN_RTN(m_packagep && !m_packagep->brokeExists()); + BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); return nullptr; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 7db866c99..87f66d414 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1528,7 +1528,7 @@ void AstVarScope::dump(std::ostream& str) const { } void AstNodeVarRef::dump(std::ostream& str) const { this->AstNodeMath::dump(str); - if (packagep()) str << " pkg=" << nodeAddr(packagep()); + if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep()); str << " " << access().arrow() << " "; } void AstVarXRef::dump(std::ostream& str) const { @@ -1620,7 +1620,7 @@ void AstActive::dump(std::ostream& str) const { } void AstNodeFTaskRef::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); - if (packagep()) { str << " pkg=" << nodeAddr(packagep()); } + if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep()); str << " -> "; if (dotted() != "") { str << ".=" << dotted() << " "; } if (taskp()) { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 924b46c6f..7396120c8 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -303,7 +303,7 @@ class AstClass final : public AstNodeModule { typedef std::map MemberNameMap; // MEMBERS MemberNameMap m_members; // Members or method children - AstClassPackage* m_packagep = nullptr; // Class package this is under + AstClassPackage* m_classOrPackagep = nullptr; // Class package this is under bool m_virtual = false; // Virtual class bool m_extended = false; // Is extension or extended by other classes void insertCache(AstNode* nodep); @@ -318,12 +318,12 @@ public: virtual void dump(std::ostream& str) const override; virtual const char* broken() const override { BROKEN_BASE_RTN(AstNodeModule::broken()); - BROKEN_RTN(m_packagep && !m_packagep->brokeExists()); + BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); return nullptr; } // op1/op2/op3 in AstNodeModule - AstClassPackage* packagep() const { return m_packagep; } - void packagep(AstClassPackage* classpackagep) { m_packagep = classpackagep; } + AstClassPackage* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstClassPackage* classpackagep) { m_classOrPackagep = classpackagep; } AstNode* membersp() const { return stmtsp(); } // op2 = List of statements void addMembersp(AstNode* nodep) { insertCache(nodep); @@ -990,7 +990,7 @@ class AstClassRefDType final : public AstNodeDType { // Reference to a class private: AstClass* m_classp; // data type pointed to, BELOW the AstTypedef - AstNodeModule* m_packagep = nullptr; // Package hierarchy + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy public: AstClassRefDType(FileLine* fl, AstClass* classp) : ASTGEN_SUPER(fl) @@ -1008,13 +1008,13 @@ public: } virtual bool same(const AstNode* samep) const override { const AstClassRefDType* asamep = static_cast(samep); - return (m_classp == asamep->m_classp && m_packagep == asamep->m_packagep); + return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep); } virtual bool similarDType(AstNodeDType* samep) const override { return this == samep || same(samep); } virtual V3Hash sameHash() const override { - return V3Hash(V3Hash(m_classp), V3Hash(m_packagep)); + return V3Hash(V3Hash(m_classp), V3Hash(m_classOrPackagep)); } virtual void dump(std::ostream& str = std::cout) const override; virtual void dumpSmall(std::ostream& str) const override; @@ -1028,8 +1028,8 @@ public: virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } virtual void virtRefDTypep(AstNodeDType* nodep) override {} virtual AstNodeDType* subDTypep() const override { return nullptr; } - AstNodeModule* packagep() const { return m_packagep; } - void packagep(AstNodeModule* nodep) { m_packagep = nodep; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } AstClass* classp() const { return m_classp; } void classp(AstClass* nodep) { m_classp = nodep; } }; @@ -1167,7 +1167,7 @@ private: // Post-width typedefs are removed and point to type directly AstNodeDType* m_refDTypep = nullptr; // data type pointed to, BELOW the AstTypedef string m_name; // Name of an AstTypedef - AstNodeModule* m_packagep = nullptr; // Package hierarchy + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy public: AstRefDType(FileLine* fl, const string& name) : ASTGEN_SUPER(fl) @@ -1197,13 +1197,13 @@ public: virtual bool same(const AstNode* samep) const override { const AstRefDType* asamep = static_cast(samep); return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep - && m_name == asamep->m_name && m_packagep == asamep->m_packagep); + && m_name == asamep->m_name && m_classOrPackagep == asamep->m_classOrPackagep); } virtual bool similarDType(AstNodeDType* samep) const override { return skipRefp()->similarDType(samep->skipRefp()); } virtual V3Hash sameHash() const override { - return V3Hash(V3Hash(m_typedefp), V3Hash(m_packagep)); + return V3Hash(V3Hash(m_typedefp), V3Hash(m_classOrPackagep)); } virtual void dump(std::ostream& str = std::cout) const override; virtual string name() const override { return m_name; } @@ -1253,8 +1253,8 @@ public: void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const override { return refDTypep(); } virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - AstNodeModule* packagep() const { return m_packagep; } - void packagep(AstNodeModule* nodep) { m_packagep = nodep; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } AstNode* typeofp() const { return op2p(); } AstNode* classOrPackageOpp() const { return op3p(); } AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } @@ -1395,12 +1395,12 @@ public: class AstEnumItemRef final : public AstNodeMath { private: AstEnumItem* m_itemp; // [AfterLink] Pointer to item - AstNodeModule* m_packagep; // Package hierarchy + AstNodeModule* m_classOrPackagep; // Package hierarchy public: - AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* packagep) + AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* classOrPackagep) : ASTGEN_SUPER(fl) , m_itemp{itemp} - , m_packagep{packagep} { + , m_classOrPackagep{classOrPackagep} { dtypeFrom(m_itemp); } ASTNODE_NODE_FUNCS(EnumItemRef) @@ -1422,8 +1422,8 @@ public: virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } - AstNodeModule* packagep() const { return m_packagep; } - void packagep(AstNodeModule* nodep) { m_packagep = nodep; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } }; class AstEnumDType final : public AstNodeDType { diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index 3bf389464..f9c835462 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -84,7 +84,7 @@ class CUseDTypeVisitor final : public AstNVisitor { if (nodep->user2SetOnce()) return; // Process once if (!m_impOnly) m_stater.newUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name()); // No class.h, it's inside the class package's h file - m_stater.newUse(nodep, VUseType::IMP_INCLUDE, nodep->classp()->packagep()->name()); + m_stater.newUse(nodep, VUseType::IMP_INCLUDE, nodep->classp()->classOrPackagep()->name()); // Need to include extends() when we implement, but no need for pointers to know VL_RESTORER(m_impOnly); { diff --git a/src/V3Class.cpp b/src/V3Class.cpp index 69c25783c..bd4e7a612 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -56,7 +56,7 @@ private: // Note origName is the same as the class origName so errors look correct AstClassPackage* packagep = new AstClassPackage(nodep->fileline(), nodep->origName()); packagep->name(nodep->name() + "__Vclpkg"); - nodep->packagep(packagep); + nodep->classOrPackagep(packagep); packagep->classp(nodep); v3Global.rootp()->addModulep(packagep); // Add package to hierarchy diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index e0e4fab26..db12822c4 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -107,7 +107,7 @@ private: if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc(); } void checkVarRef(AstNodeVarRef* nodep) { - if (nodep->packagep() && m_elimCells) { nodep->packagep(nullptr); } + if (nodep->classOrPackagep() && m_elimCells) nodep->classOrPackagep(nullptr); } void checkDType(AstNodeDType* nodep) { if (!nodep->generic() // Don't remove generic types @@ -130,7 +130,7 @@ private: checkAll(nodep); if (AstClass* classp = VN_CAST(nodep, Class)) { if (classp->extendsp()) classp->extendsp()->user1Inc(); - if (classp->packagep()) classp->packagep()->user1Inc(); + if (classp->classOrPackagep()) classp->classOrPackagep()->user1Inc(); m_classesp.push_back(classp); // TODO we don't reclaim dead classes yet - graph implementation instead? classp->user1Inc(); @@ -171,16 +171,16 @@ private: nodep->varScopep()->varp()->user1Inc(); } if (nodep->varp()) nodep->varp()->user1Inc(); - if (nodep->packagep()) nodep->packagep()->user1Inc(); + if (nodep->classOrPackagep()) nodep->classOrPackagep()->user1Inc(); } virtual void visit(AstNodeFTaskRef* nodep) override { iterateChildren(nodep); checkAll(nodep); - if (nodep->packagep()) { + if (nodep->classOrPackagep()) { if (m_elimCells) { - nodep->packagep(nullptr); + nodep->classOrPackagep(nullptr); } else { - nodep->packagep()->user1Inc(); + nodep->classOrPackagep()->user1Inc(); } } } @@ -194,11 +194,11 @@ private: checkAll(nodep); UASSERT_OBJ(!(m_elimCells && nodep->typedefp()), nodep, "RefDType should point to data type before typedefs removed"); - if (nodep->packagep()) { + if (nodep->classOrPackagep()) { if (m_elimCells) { - nodep->packagep(nullptr); + nodep->classOrPackagep(nullptr); } else { - nodep->packagep()->user1Inc(); + nodep->classOrPackagep()->user1Inc(); } } } @@ -206,11 +206,11 @@ private: iterateChildren(nodep); checkDType(nodep); checkAll(nodep); - if (nodep->packagep()) { + if (nodep->classOrPackagep()) { if (m_elimCells) { - nodep->packagep(nullptr); + nodep->classOrPackagep(nullptr); } else { - nodep->packagep()->user1Inc(); + nodep->classOrPackagep()->user1Inc(); } } if (nodep->classp()) nodep->classp()->user1Inc(); @@ -223,11 +223,11 @@ private: virtual void visit(AstEnumItemRef* nodep) override { iterateChildren(nodep); checkAll(nodep); - if (nodep->packagep()) { + if (nodep->classOrPackagep()) { if (m_elimCells) { - nodep->packagep(nullptr); + nodep->classOrPackagep(nullptr); } else { - nodep->packagep()->user1Inc(); + nodep->classOrPackagep()->user1Inc(); } } checkAll(nodep); @@ -372,7 +372,7 @@ private: if (AstClass* nodep = itr) { // nullptr if deleted earlier if (nodep->user1() == 0) { if (nodep->extendsp()) nodep->extendsp()->user1Inc(-1); - if (nodep->packagep()) nodep->packagep()->user1Inc(-1); + if (nodep->classOrPackagep()) nodep->classOrPackagep()->user1Inc(-1); VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); itr = nullptr; retry = true; diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 681d123ef..829cf1e6c 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -153,7 +153,7 @@ private: virtual void visit(AstNodeFTaskRef* nodep) override { // Cleanup link until V3LinkDot can correct it // MethodCalls not currently supported by inliner, so keep linked - if (!nodep->packagep() && !VN_IS(nodep, MethodCall)) nodep->taskp(nullptr); + if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) nodep->taskp(nullptr); iterateChildren(nodep); } virtual void visit(AstAlways* nodep) override { diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 4ef17a730..c9bb8acc8 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -383,7 +383,7 @@ private: varrefp->name() + "__BRA__" + index + "__KET__", "", VAccess::WRITE); newp->dtypep(nodep->modVarp()->dtypep()); - newp->packagep(varrefp->packagep()); + newp->classOrPackagep(varrefp->classOrPackagep()); arrselp->addNextHere(newp); VL_DO_DANGLING(arrselp->unlinkFrBack()->deleteTree(), arrselp); } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 720443f2b..b54e741aa 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -355,7 +355,7 @@ public: return symp; } VSymEnt* insertBlock(VSymEnt* abovep, const string& name, AstNode* nodep, - AstNodeModule* packagep) { + AstNodeModule* classOrPackagep) { // A fake point in the hierarchy, corresponding to a begin or function/task block // After we remove begins these will go away // Note we fallback to the symbol table of the parent, as we want to find variables there @@ -365,7 +365,7 @@ public: UINFO(9, " INSERTblk se" << cvtToHex(symp) << " above=se" << cvtToHex(abovep) << " node=" << nodep << endl); symp->parentp(abovep); - symp->packagep(packagep); + symp->classOrPackagep(classOrPackagep); symp->fallbackp(abovep); nodep->user1p(symp); if (name != "") { checkDuplicate(abovep, nodep, name); } @@ -374,14 +374,14 @@ public: return symp; } VSymEnt* insertSym(VSymEnt* abovep, const string& name, AstNode* nodep, - AstNodeModule* packagep) { + AstNodeModule* classOrPackagep) { UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9, " INSERTsym se" << cvtToHex(symp) << " name='" << name << "' above=se" << cvtToHex(abovep) << " node=" << nodep << endl); // We don't remember the ent associated with each node, because we // need a unique scope entry for each instantiation - symp->packagep(packagep); + symp->classOrPackagep(classOrPackagep); symp->parentp(abovep); symp->fallbackp(abovep); nodep->user1p(symp); @@ -708,7 +708,7 @@ LinkDotState* LinkDotState::s_errorThisp = nullptr; class LinkDotFindVisitor final : public AstNVisitor { // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table - AstNodeModule* m_packagep = nullptr; // Current package + AstNodeModule* m_classOrPackagep = nullptr; // Current package VSymEnt* m_modSymp = nullptr; // Symbol Entry for current module VSymEnt* m_curSymp = nullptr; // Symbol Entry for current table, where to lookup/insert string m_scope; // Scope text @@ -729,7 +729,7 @@ class LinkDotFindVisitor final : public AstNVisitor { newp->isConstructor(true); nodep->addMembersp(newp); UINFO(8, "Made implicit new for " << nodep->name() << ": " << nodep << endl); - m_statep->insertBlock(m_curSymp, newp->name(), newp, m_packagep); + m_statep->insertBlock(m_curSymp, newp->name(), newp, m_classOrPackagep); } bool isHierBlockWrapper(const string& name) const { @@ -777,7 +777,7 @@ class LinkDotFindVisitor final : public AstNVisitor { bool standalonePkg = !m_modSymp && (m_statep->forPrearray() && VN_IS(nodep, Package)); bool doit = (m_modSymp || standalonePkg); VL_RESTORER(m_scope); - VL_RESTORER(m_packagep); + VL_RESTORER(m_classOrPackagep); VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); VL_RESTORER(m_paramNum); @@ -794,7 +794,7 @@ class LinkDotFindVisitor final : public AstNVisitor { UASSERT_OBJ(!nodep->dead(), nodep, "Module in cell tree mislabeled as dead?"); VSymEnt* upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp(); AstPackage* pkgp = VN_CAST(nodep, Package); - m_packagep = pkgp; + m_classOrPackagep = pkgp; if (standalonePkg) { if (pkgp->isDollarUnit()) { m_curSymp = m_modSymp = m_statep->dunitEntp(); @@ -802,7 +802,7 @@ class LinkDotFindVisitor final : public AstNVisitor { } else { m_scope = nodep->name(); m_curSymp = m_modSymp = m_statep->insertBlock( - upperSymp, nodep->name() + "::", nodep, m_packagep); + upperSymp, nodep->name() + "::", nodep, m_classOrPackagep); UINFO(9, "New module scope " << m_curSymp << endl); } } @@ -826,7 +826,7 @@ class LinkDotFindVisitor final : public AstNVisitor { m_scope = nodep->name(); VSymEnt* upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp(); m_curSymp = m_modSymp - = m_statep->insertBlock(upperSymp, nodep->name() + "::", nodep, m_packagep); + = m_statep->insertBlock(upperSymp, nodep->name() + "::", nodep, m_classOrPackagep); iterateChildren(nodep); nodep->user4(true); } else { // !doit @@ -850,7 +850,7 @@ class LinkDotFindVisitor final : public AstNVisitor { VSymEnt* upperSymp = m_curSymp; m_scope = m_scope + "." + nodep->name(); m_curSymp = m_modSymp - = m_statep->insertBlock(upperSymp, nodep->name(), nodep, m_packagep); + = m_statep->insertBlock(upperSymp, nodep->name(), nodep, m_classOrPackagep); m_statep->insertMap(m_curSymp, m_scope); UINFO(9, "New module scope " << m_curSymp << endl); // @@ -965,7 +965,8 @@ class LinkDotFindVisitor final : public AstNVisitor { { m_blockNum = 0; m_blockp = nodep; - m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_packagep); + m_curSymp + = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_classOrPackagep); m_curSymp->fallbackp(oldCurSymp); // Iterate iterateChildren(nodep); @@ -982,8 +983,9 @@ class LinkDotFindVisitor final : public AstNVisitor { VSymEnt* const oldCurSymp = m_curSymp; { // Change to appropriate package if extern declaration (vs definition) - if (nodep->packagep()) { - AstClassOrPackageRef* cpackagerefp = VN_CAST(nodep->packagep(), ClassOrPackageRef); + if (nodep->classOrPackagep()) { + AstClassOrPackageRef* cpackagerefp + = VN_CAST(nodep->classOrPackagep(), ClassOrPackageRef); if (!cpackagerefp) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: extern function definition with class-in-class"); @@ -998,14 +1000,14 @@ class LinkDotFindVisitor final : public AstNVisitor { nodep->unlinkFrBack(); classp->addStmtp(nodep); nodep->isExternDef(true); // So we check there's a matching extern - nodep->packagep()->unlinkFrBack()->deleteTree(); + nodep->classOrPackagep()->unlinkFrBack()->deleteTree(); } } } } // Create symbol table for the task's vars string name = string{nodep->isExternProto() ? "extern " : ""} + nodep->name(); - auto pkgp = m_packagep; + auto pkgp = m_classOrPackagep; // Set the class as package for static class methods if (nodep->lifetime().isStatic() && VN_IS(m_curSymp->nodep(), Class)) { pkgp = VN_CAST(m_curSymp->nodep(), Class); @@ -1033,7 +1035,8 @@ class LinkDotFindVisitor final : public AstNVisitor { newvarp->attrIsolateAssign(nodep->attrIsolateAssign()); nodep->addFvarp(newvarp); // Explicit insert required, as the var name shadows the upper level's task name - m_statep->insertSym(m_curSymp, newvarp->name(), newvarp, nullptr /*packagep*/); + m_statep->insertSym(m_curSymp, newvarp->name(), newvarp, + nullptr /*classOrPackagep*/); } m_ftaskp = nodep; iterateChildren(nodep); @@ -1150,11 +1153,13 @@ class LinkDotFindVisitor final : public AstNVisitor { } } } - VSymEnt* insp = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); + VSymEnt* insp + = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); if (m_statep->forPrimary() && nodep->isGParam()) { m_paramNum++; - VSymEnt* symp = m_statep->insertSym( - m_curSymp, "__paramNumber" + cvtToStr(m_paramNum), nodep, m_packagep); + VSymEnt* symp + = m_statep->insertSym(m_curSymp, "__paramNumber" + cvtToStr(m_paramNum), + nodep, m_classOrPackagep); symp->exported(false); } AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(nodep->subDTypep()); @@ -1169,7 +1174,7 @@ class LinkDotFindVisitor final : public AstNVisitor { virtual void visit(AstTypedef* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); iterateChildren(nodep); - m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); + m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); } virtual void visit(AstTypedefFwd* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); @@ -1180,7 +1185,7 @@ class LinkDotFindVisitor final : public AstNVisitor { virtual void visit(AstParamTypeDType* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit"); iterateChildren(nodep); - m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); + m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); } virtual void visit(AstCFunc* nodep) override { // For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist @@ -1223,7 +1228,7 @@ class LinkDotFindVisitor final : public AstNVisitor { ins = true; } } - if (ins) m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); + if (ins) m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); } virtual void visit(AstPackageImport* nodep) override { UINFO(4, " Link: " << nodep << endl); @@ -1296,7 +1301,7 @@ class LinkDotFindVisitor final : public AstNVisitor { { ++m_modWithNum; m_curSymp = m_statep->insertBlock(m_curSymp, "__Vwith" + cvtToStr(m_modWithNum), nodep, - m_packagep); + m_classOrPackagep); m_curSymp->fallbackp(oldCurSymp); UASSERT_OBJ(nodep->indexArgRefp(), nodep, "Missing lambda argref"); UASSERT_OBJ(nodep->valueArgRefp(), nodep, "Missing lambda argref"); @@ -1427,7 +1432,7 @@ private: refp->user4(true); VSymEnt* symp = m_statep->insertSym(m_statep->getNodeSym(m_modp), "__pinNumber" + cvtToStr(nodep->pinNum()), refp, - nullptr /*packagep*/); + nullptr /*classOrPackagep*/); symp->exported(false); } // Ports not needed any more @@ -1835,7 +1840,7 @@ private: modp->addStmtp(newp); // Link it to signal list, must add the variable under the module; // current scope might be lower now - m_statep->insertSym(moduleSymp, newp->name(), newp, nullptr /*packagep*/); + m_statep->insertSym(moduleSymp, newp->name(), newp, nullptr /*classOrPackagep*/); } } AstVar* foundToVarp(const VSymEnt* symp, AstNode* nodep, VAccess access) { @@ -2119,7 +2124,7 @@ private: bool allowVar = false; if (m_ds.m_dotPos == DP_PACKAGE) { // {package}::{a} - AstNodeModule* packagep = nullptr; + AstNodeModule* classOrPackagep = nullptr; expectWhat = "scope/variable"; allowScope = true; allowVar = true; @@ -2127,9 +2132,9 @@ private: "Bad package link"); AstClassOrPackageRef* cpackagerefp = VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef); - packagep = cpackagerefp->classOrPackagep(); - UASSERT_OBJ(packagep, m_ds.m_dotp->lhsp(), "Bad package link"); - m_ds.m_dotSymp = m_statep->getNodeSym(packagep); + classOrPackagep = cpackagerefp->classOrPackagep(); + UASSERT_OBJ(classOrPackagep, m_ds.m_dotp->lhsp(), "Bad package link"); + m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep); m_ds.m_dotPos = DP_SCOPE; } else if (m_ds.m_dotPos == DP_SCOPE) { // {a}.{b}, where {a} maybe a module name @@ -2246,7 +2251,7 @@ private: AstVarRef* refp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); // lvalue'ness computed later - refp->packagep(foundp->packagep()); + refp->classOrPackagep(foundp->classOrPackagep()); newp = refp; } UINFO(9, " new " << newp << endl); @@ -2305,7 +2310,7 @@ private: } else if (AstEnumItem* valuep = VN_CAST(foundp->nodep(), EnumItem)) { if (allowVar) { AstNode* newp - = new AstEnumItemRef(nodep->fileline(), valuep, foundp->packagep()); + = new AstEnumItemRef(nodep->fileline(), valuep, foundp->classOrPackagep()); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); ok = true; @@ -2379,7 +2384,7 @@ private: if (AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->access()) : nullptr) { nodep->varp(varp); // Generally set by parse, but might be an import - nodep->packagep(foundp->packagep()); + nodep->classOrPackagep(foundp->classOrPackagep()); } if (!nodep->varp()) { nodep->v3error("Can't find definition of signal, again: " << nodep->prettyNameQ()); @@ -2506,7 +2511,7 @@ private: nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages"); } UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link"); - nodep->packagep(cpackagerefp->classOrPackagep()); + nodep->classOrPackagep(cpackagerefp->classOrPackagep()); m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotp = nullptr; } else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) { @@ -2536,7 +2541,7 @@ private: } else { checkNoDot(nodep); } - if (nodep->packagep() && nodep->taskp()) { + if (nodep->classOrPackagep() && nodep->taskp()) { // References into packages don't care about cell hierarchy. } else if (!m_modSymp) { // Module that is not in hierarchy. We'll be dead code eliminating it later. @@ -2552,8 +2557,8 @@ private: // of same name under a subtask isn't a relevant hit however a // function under a begin/end is. So we want begins, but not // the function - if (nodep->packagep()) { // Look only in specified package - dotSymp = m_statep->getNodeSym(nodep->packagep()); + if (nodep->classOrPackagep()) { // Look only in specified package + dotSymp = m_statep->getNodeSym(nodep->classOrPackagep()); } else { if (nodep->inlinedDots() != "") { // Correct for current scope // Dotted lookup is always relative to module, as maybe @@ -2579,7 +2584,7 @@ private: = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : nullptr; // Maybe nullptr if (taskp) { nodep->taskp(taskp); - nodep->packagep(foundp->packagep()); + nodep->classOrPackagep(foundp->classOrPackagep()); UINFO(7, " Resolved " << nodep << endl); // Also prints taskp } else { // Note ParseRef has similar error handling/message output @@ -2812,7 +2817,7 @@ private: if (!nodep->findMember(it->first)) { if (AstEnumItem* aitemp = VN_CAST(itemp, EnumItem)) { AstEnumItemRef* newp = new AstEnumItemRef(aitemp->fileline(), aitemp, - it->second->packagep()); + it->second->classOrPackagep()); UINFO(8, "Class import noderef '" << it->first << "' " << newp << endl); nodep->addMembersp(newp); } @@ -2825,16 +2830,13 @@ private: if (nodep->user3SetOnce()) return; if (AstNode* cpackagep = nodep->classOrPackageOpp()) { if (AstClassOrPackageRef* cpackagerefp = VN_CAST(cpackagep, ClassOrPackageRef)) { - if (cpackagerefp->packagep()) { - nodep->packagep(cpackagerefp->packagep()); - } else { - nodep->packagep(cpackagerefp->classOrPackagep()); - if (!VN_IS(nodep->packagep(), Class) && !VN_IS(nodep->packagep(), Package)) { - cpackagerefp->v3error( - "'::' expected to reference a class/package but referenced " - << nodep->packagep()->prettyTypeName() << '\n' - << cpackagerefp->warnMore() + "... Suggest '.' instead of '::'"); - } + nodep->classOrPackagep(cpackagerefp->classOrPackagep()); + if (!VN_IS(nodep->classOrPackagep(), Class) + && !VN_IS(nodep->classOrPackagep(), Package)) { + cpackagerefp->v3error( + "'::' expected to reference a class/package but referenced " + << nodep->classOrPackagep()->prettyTypeName() << '\n' + << cpackagerefp->warnMore() + "... Suggest '.' instead of '::'"); } } else { cpackagep->v3warn(E_UNSUPPORTED, @@ -2847,9 +2849,10 @@ private: if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(), "Bad package link"); - UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep(), + UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link"); - nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep()); + nodep->classOrPackagep( + VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->classOrPackagep()); m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotp = nullptr; } else { @@ -2858,21 +2861,21 @@ private: if (nodep->typeofp()) { // Really is a typeof not a reference } else if (!nodep->typedefp() && !nodep->subDTypep()) { VSymEnt* foundp; - if (nodep->packagep()) { - foundp = m_statep->getNodeSym(nodep->packagep())->findIdFlat(nodep->name()); + if (nodep->classOrPackagep()) { + foundp = m_statep->getNodeSym(nodep->classOrPackagep())->findIdFlat(nodep->name()); } else { foundp = m_curSymp->findIdFallback(nodep->name()); } if (AstTypedef* defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : nullptr) { nodep->typedefp(defp); - nodep->packagep(foundp->packagep()); + nodep->classOrPackagep(foundp->classOrPackagep()); } else if (AstParamTypeDType* defp = foundp ? VN_CAST(foundp->nodep(), ParamTypeDType) : nullptr) { nodep->refDTypep(defp); - nodep->packagep(foundp->packagep()); + nodep->classOrPackagep(foundp->classOrPackagep()); } else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : nullptr) { AstClassRefDType* newp = new AstClassRefDType(nodep->fileline(), defp); - newp->packagep(foundp->packagep()); + newp->classOrPackagep(foundp->classOrPackagep()); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); return; diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index a1374541e..6e050be7b 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -68,8 +68,8 @@ private: for (const auto& itr : m_varRefScopes) { AstVarRef* nodep = itr.first; AstScope* scopep = itr.second; - if (nodep->packagep() && !nodep->varp()->isClassMember()) { - const auto it2 = m_packageScopes.find(nodep->packagep()); + if (nodep->classOrPackagep() && !nodep->varp()->isClassMember()) { + const auto it2 = m_packageScopes.find(nodep->classOrPackagep()); UASSERT_OBJ(it2 != m_packageScopes.end(), nodep, "Can't locate package scope"); scopep = it2->second; } @@ -365,7 +365,7 @@ private: virtual void visit(AstNodeFTaskRef* nodep) override { // The crossrefs are dealt with in V3LinkDot UINFO(9, " Old pkg-taskref " << nodep << endl); - if (nodep->packagep()) { + if (nodep->classOrPackagep()) { // Point to the clone UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked"); AstNodeFTask* newp = VN_CAST(nodep->taskp()->user2p(), NodeFTask); diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index e3663a476..c949e3478 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -982,7 +982,7 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { const auto refit = m_refs.find(varp); if (refit == m_refs.end()) return; // variable without split_var metacomment UASSERT_OBJ(varp->attrSplitVar(), varp, "split_var attribute must be attached"); - UASSERT_OBJ(!nodep->packagep(), nodep, + UASSERT_OBJ(!nodep->classOrPackagep(), nodep, "variable in package must have been dropped beforehand."); const AstBasicDType* basicp = refit->second.basicp(); refit->second.append(PackedVarRefEntry(nodep, basicp->lsb(), varp->width()), diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 68a2296f0..512bdedf1 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -46,7 +46,7 @@ class VSymEnt final { AstNode* m_nodep; // Node that entry belongs to VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it - AstNodeModule* m_packagep; // Package node is in (for V3LinkDot, unused here) + AstNodeModule* m_classOrPackagep; // Package node is in (for V3LinkDot, unused here) string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here) bool m_exported; // Allow importing bool m_imported; // Was imported @@ -100,7 +100,7 @@ public: m_nodep = reinterpret_cast(1); m_fallbackp = reinterpret_cast(1); m_parentp = reinterpret_cast(1); - m_packagep = reinterpret_cast(1); + m_classOrPackagep = reinterpret_cast(1); #endif } #if defined(VL_DEBUG) && !defined(VL_LEAK_CHECKS) @@ -111,8 +111,8 @@ public: 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; } - AstNodeModule* packagep() const { return m_packagep; } + void classOrPackagep(AstNodeModule* entp) { m_classOrPackagep = entp; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } AstNode* nodep() const { return m_nodep; } string symPrefix() const { return m_symPrefix; } void symPrefix(const string& name) { m_symPrefix = name; } @@ -337,7 +337,7 @@ inline VSymEnt::VSymEnt(VSymGraph* graphp, AstNode* nodep) // by an earlier search insertion. m_fallbackp = nullptr; m_parentp = nullptr; - m_packagep = nullptr; + m_classOrPackagep = nullptr; m_exported = true; m_imported = false; graphp->pushNewEnt(this); @@ -347,7 +347,7 @@ inline VSymEnt::VSymEnt(VSymGraph* graphp, const VSymEnt* symp) : m_nodep(symp->m_nodep) { m_fallbackp = symp->m_fallbackp; m_parentp = symp->m_parentp; - m_packagep = symp->m_packagep; + m_classOrPackagep = symp->m_classOrPackagep; m_exported = symp->m_exported; m_imported = symp->m_imported; graphp->pushNewEnt(this); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index ae0c2731f..08ea024a3 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1415,7 +1415,7 @@ private: = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), msbdim); AstNode* dimp = nodep->dimp()->unlinkFrBack(); AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); - varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp()); + varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -2516,7 +2516,7 @@ private: int selwidth = V3Number::log2b(msbdim) + 1; // Width to address a bit AstVar* varp = enumVarp(adtypep, attrType, (1ULL << selwidth) - 1); AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); - varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp()); + varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); AstNode* newp = new AstArraySel( nodep->fileline(), varrefp, // Select in case widths are @@ -2886,7 +2886,7 @@ private: newp = new AstFuncRef(nodep->fileline(), ftaskp->name(), argsp); } newp->taskp(ftaskp); - newp->packagep(classp); + newp->classOrPackagep(classp); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } else { @@ -3101,7 +3101,7 @@ private: UASSERT_OBJ(classp, nodep, "Unlinked"); if (AstNodeFTask* ftaskp = VN_CAST(classp->findMember("new"), Func)) { nodep->taskp(ftaskp); - nodep->packagep(classp); + nodep->classOrPackagep(classp); } else { // Either made explicitly or V3LinkDot made implicitly classp->v3fatalSrc("Can't find class's new"); diff --git a/src/verilog.y b/src/verilog.y index 8ca424f3c..515bda060 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3873,7 +3873,7 @@ taskId: // | packageClassScope id { $$ = new AstTask($$, *$2, nullptr); - $$->packagep($1); + $$->classOrPackagep($1); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; @@ -3912,7 +3912,7 @@ funcIdNew: // IEEE: from class_constructor_declaration SYMP->pushNewUnder($$, nullptr); } | packageClassScopeNoId yNEW__PAREN { $$ = new AstFunc($2, "new", nullptr, nullptr); - $$->packagep($1); + $$->classOrPackagep($1); $$->isConstructor(true); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; @@ -3934,7 +3934,7 @@ fIdScoped: // IEEE: part of function_body_declaration/task_body_declarat { $$ = $1; $$ = $1; $$ = new AstFunc($$, *$2, nullptr, nullptr); - $$->packagep($1); } + $$->classOrPackagep($1); } ; tfGuts: From bf24fa9478e2c201ba081e2039b731c047167e02 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 22:46:02 -0500 Subject: [PATCH 39/91] Fix access to non-overridden base class variable (#2654). --- Changes | 2 + src/V3Ast.h | 21 +++++++---- src/V3AstNodes.cpp | 4 +- src/V3AstNodes.h | 15 +++++--- src/V3Dead.cpp | 1 + src/V3Descope.cpp | 20 ++++++++-- src/V3EmitV.cpp | 3 +- src/V3LinkDot.cpp | 2 + src/V3Localize.cpp | 3 +- src/V3Scope.cpp | 13 ++++--- test_regress/t/t_class_extends_this3.pl | 21 +++++++++++ test_regress/t/t_class_extends_this3.v | 31 ++++++++++++++++ test_regress/t/t_class_local.v | 49 ++++++++++++++++++++++++- 13 files changed, 157 insertions(+), 28 deletions(-) create mode 100755 test_regress/t/t_class_extends_this3.pl create mode 100644 test_regress/t/t_class_extends_this3.v diff --git a/Changes b/Changes index 68b2adad0..155200731 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] +**** Fix access to non-overridden base class variable (#2654). [Tobias Rosenkranz] + * Verilator 4.104 2020-11-14 diff --git a/src/V3Ast.h b/src/V3Ast.h index 405d3ad73..9910125d1 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2300,7 +2300,8 @@ private: AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy string m_name; // Name of variable - string m_hiername; // Scope converted into name-> for emitting + string m_hiernameToProt; // Scope converted into name-> for emitting + string m_hiernameToUnprot; // Scope converted into name-> for emitting bool m_hierThis = false; // Hiername points to "this" function public: @@ -2331,9 +2332,11 @@ public: void varp(AstVar* varp); AstVarScope* varScopep() const { return m_varScopep; } void varScopep(AstVarScope* varscp) { m_varScopep = varscp; } - string hiername() const { return m_hiername; } + string hiernameToProt() const { return m_hiernameToProt; } + void hiernameToProt(const string& hn) { m_hiernameToProt = hn; } + string hiernameToUnprot() const { return m_hiernameToUnprot; } + void hiernameToUnprot(const string& hn) { m_hiernameToUnprot = hn; } string hiernameProtect() const; - void hiername(const string& hn) { m_hiername = hn; } bool hierThis() const { return m_hierThis; } void hierThis(bool flag) { m_hierThis = flag; } AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } @@ -2620,7 +2623,8 @@ class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt { // A call of a C++ function, perhaps a AstCFunc or perhaps globally named // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. AstCFunc* m_funcp; - string m_hiername; + string m_hiernameToProt; + string m_hiernameToUnprot; string m_argTypes; public: @@ -2634,7 +2638,8 @@ public: AstNodeCCall(AstType t, AstNodeCCall* oldp, AstCFunc* funcp) : AstNodeStmt{t, oldp->fileline(), true} , m_funcp{funcp} { - m_hiername = oldp->hiername(); + m_hiernameToProt = oldp->hiernameToProt(); + m_hiernameToUnprot = oldp->hiernameToUnprot(); m_argTypes = oldp->argTypes(); if (oldp->argsp()) addNOp2p(oldp->argsp()->unlinkFrBackWithNext()); } @@ -2654,8 +2659,10 @@ public: virtual bool isPure() const override; virtual bool isOutputter() const override { return !isPure(); } AstCFunc* funcp() const { return m_funcp; } - string hiername() const { return m_hiername; } - void hiername(const string& hn) { m_hiername = hn; } + string hiernameToProt() const { return m_hiernameToProt; } + void hiernameToProt(const string& hn) { m_hiernameToProt = hn; } + string hiernameToUnprot() const { return m_hiernameToUnprot; } + void hiernameToUnprot(const string& hn) { m_hiernameToUnprot = hn; } string hiernameProtect() const; void argTypes(const string& str) { m_argTypes = str; } string argTypes() const { return m_argTypes; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 87f66d414..dac9ca69e 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -54,7 +54,7 @@ void AstNodeVarRef::cloneRelink() { } string AstNodeVarRef::hiernameProtect() const { - return VIdProtect::protectWordsIf(hiername(), protect()); + return hiernameToUnprot() + VIdProtect::protectWordsIf(hiernameToProt(), protect()); } int AstNodeSel::bitConst() const { @@ -107,7 +107,7 @@ const char* AstNodeCCall::broken() const { } bool AstNodeCCall::isPure() const { return funcp()->pure(); } string AstNodeCCall::hiernameProtect() const { - return VIdProtect::protectWordsIf(hiername(), protect()); + return hiernameToUnprot() + VIdProtect::protectWordsIf(hiernameToProt(), protect()); } void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 7396120c8..8ac7382f9 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2347,7 +2347,7 @@ public: ASTNODE_NODE_FUNCS(VarRef) virtual void dump(std::ostream& str) const override; virtual V3Hash sameHash() const override { - return V3Hash(V3Hash(varp()->name()), V3Hash(hiername())); + return V3Hash(V3Hash(varp()->name()), V3Hash(hiernameToProt())); } virtual bool same(const AstNode* samep) const override { return same(static_cast(samep)); @@ -2356,16 +2356,18 @@ public: if (varScopep()) { return (varScopep() == samep->varScopep() && access() == samep->access()); } else { - return (hiername() == samep->hiername() && varp()->name() == samep->varp()->name() - && access() == samep->access()); + return (hiernameToProt() == samep->hiernameToProt() + && hiernameToUnprot() == samep->hiernameToUnprot() + && varp()->name() == samep->varp()->name() && access() == samep->access()); } } inline bool sameNoLvalue(AstVarRef* samep) const { if (varScopep()) { return (varScopep() == samep->varScopep()); } else { - return (hiername() == samep->hiername() - && (hiername() != "" || samep->hiername() != "") + return (hiernameToProt() == samep->hiernameToProt() + && hiernameToUnprot() == samep->hiernameToUnprot() + && (!hiernameToProt().empty() || !samep->hiernameToProt().empty()) && varp()->name() == samep->varp()->name()); } } @@ -2406,7 +2408,8 @@ public: virtual V3Hash sameHash() const override { return V3Hash(V3Hash(varp()), V3Hash(dotted())); } virtual bool same(const AstNode* samep) const override { const AstVarXRef* asamep = static_cast(samep); - return (hiername() == asamep->hiername() && varp() == asamep->varp() + return (hiernameToProt() == asamep->hiernameToProt() + && hiernameToUnprot() == asamep->hiernameToUnprot() && varp() == asamep->varp() && name() == asamep->name() && dotted() == asamep->dotted()); } }; diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index db12822c4..d9602c913 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -122,6 +122,7 @@ private: // VISITORS virtual void visit(AstNodeModule* nodep) override { + if (m_modp) m_modp->user1Inc(); // e.g. Class under Package VL_RESTORER(m_modp); { m_modp = nodep; diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index b59e900ca..a23413e8c 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -76,7 +76,8 @@ private: // Sets 'hierThisr' true if the object is local to this scope // (and could be made into a function-local later in V3Localize), // false if the object is in another scope. - string descopedName(const AstScope* scopep, bool& hierThisr, const AstVar* varp = nullptr) { + string descopedName(bool& hierThisr, string& hierUnprot, const AstScope* scopep, + const AstVar* varp) { UASSERT(scopep, "Var/Func not scoped"); hierThisr = (scopep == m_scopep); @@ -118,6 +119,9 @@ private: } else if (relativeRefOk && scopep == m_scopep) { m_needThis = true; return "this->"; + } else if (VN_IS(scopep->modp(), Class)) { + hierUnprot = v3Global.opt.modPrefix() + "_"; // Prefix before protected part + return scopep->modp()->name() + "::"; } else if (relativeRefOk && scopep->aboveScopep() && scopep->aboveScopep() == m_scopep) { // Reference to scope of cell directly under this module, can just "cell->" string name = scopep->name(); @@ -249,12 +253,17 @@ private: virtual void visit(AstNodeVarRef* nodep) override { iterateChildren(nodep); // Convert the hierch name + UINFO(9, " ref-in " << nodep << endl); UASSERT_OBJ(m_scopep, nodep, "Node not under scope"); bool hierThis; - nodep->hiername(descopedName(nodep->varScopep()->scopep(), hierThis /*ref*/, - nodep->varScopep()->varp())); + string hierUnprot; + nodep->hiernameToProt(descopedName(hierThis /*ref*/, hierUnprot /*ref*/, + nodep->varScopep()->scopep(), + nodep->varScopep()->varp())); + nodep->hiernameToUnprot(hierUnprot); nodep->hierThis(hierThis); nodep->varScopep(nullptr); + UINFO(9, " refout " << nodep << endl); } virtual void visit(AstNodeCCall* nodep) override { // UINFO(9, " " << nodep << endl); @@ -263,7 +272,10 @@ private: UASSERT_OBJ(m_scopep, nodep, "Node not under scope"); UASSERT_OBJ(nodep->funcp()->scopep(), nodep, "CFunc not under scope"); bool hierThis; - nodep->hiername(descopedName(nodep->funcp()->scopep(), hierThis /*ref*/)); + string hierUnprot; + nodep->hiernameToProt( + descopedName(hierThis /*ref*/, hierUnprot /*ref*/, nodep->funcp()->scopep(), nullptr)); + nodep->hiernameToUnprot(hierUnprot); // Can't do this, as we may have more calls later // nodep->funcp()->scopep(nullptr); } diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 53565a87e..664f6ddbd 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -613,7 +613,8 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { if (nodep->varScopep()) { putfs(nodep, nodep->varScopep()->prettyName()); } else { - putfs(nodep, nodep->hiername()); + putfs(nodep, nodep->hiernameToUnprot()); + puts(nodep->hiernameToProt()); puts(nodep->varp()->prettyName()); } } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index b54e741aa..ab3ead042 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -839,6 +839,7 @@ class LinkDotFindVisitor final : public AstNVisitor { UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit"); UINFO(8, " " << nodep << endl); VL_RESTORER(m_scope); + VL_RESTORER(m_classOrPackagep); VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); VL_RESTORER(m_paramNum); @@ -849,6 +850,7 @@ class LinkDotFindVisitor final : public AstNVisitor { UINFO(4, " Link Class: " << nodep << endl); VSymEnt* upperSymp = m_curSymp; m_scope = m_scope + "." + nodep->name(); + m_classOrPackagep = nodep; m_curSymp = m_modSymp = m_statep->insertBlock(upperSymp, nodep->name(), nodep, m_classOrPackagep); m_statep->insertMap(m_curSymp, m_scope); diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 565bddae5..372f4d188 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -76,7 +76,8 @@ private: // cppcheck-suppress unreadVariable // cppcheck 1.90 bug VarFlags flags(nodep->varp()); if (flags.m_done) { - nodep->hiername(""); // Remove this-> + nodep->hiernameToProt(""); // Remove this-> + nodep->hiernameToUnprot(""); // Remove this-> nodep->hierThis(true); } } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 6e050be7b..cc11bdb40 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -68,7 +68,7 @@ private: for (const auto& itr : m_varRefScopes) { AstVarRef* nodep = itr.first; AstScope* scopep = itr.second; - if (nodep->classOrPackagep() && !nodep->varp()->isClassMember()) { + if (nodep->classOrPackagep()) { const auto it2 = m_packageScopes.find(nodep->classOrPackagep()); UASSERT_OBJ(it2 != m_packageScopes.end(), nodep, "Can't locate package scope"); scopep = it2->second; @@ -109,9 +109,7 @@ private: (m_aboveCellp ? static_cast(m_aboveCellp) : static_cast(nodep)) ->fileline(), nodep, scopename, m_aboveScopep, m_aboveCellp); - if (VN_IS(nodep, Package)) { - m_packageScopes.insert(make_pair(VN_CAST(nodep, Package), m_scopep)); - } + if (VN_IS(nodep, Package)) m_packageScopes.insert(make_pair(nodep, m_scopep)); // Now for each child cell, iterate the module this cell points to for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp = cellnextp->nextp()) { @@ -152,8 +150,10 @@ private: VL_RESTORER(m_scopep); VL_RESTORER(m_aboveCellp); VL_RESTORER(m_aboveScopep); + VL_RESTORER(m_modp); { m_aboveScopep = m_scopep; + m_modp = nodep; string scopename; if (!m_aboveScopep) { @@ -169,6 +169,8 @@ private: : static_cast(nodep)); m_scopep = new AstScope(abovep->fileline(), m_modp, scopename, m_aboveScopep, m_aboveCellp); + m_packageScopes.insert(make_pair(nodep, m_scopep)); + // Create scope for the current usage of this cell AstNode::user1ClearTree(); nodep->addMembersp(m_scopep); @@ -283,7 +285,8 @@ private: } else { // We may have not made the variable yet, and we can't make it now as // the var's referenced package etc might not be created yet. - // So push to a list and post-correct + // So push to a list and post-correct. + // No check here for nodep->classOrPackagep(), will check when walk list. m_varRefScopes.insert(make_pair(nodep, m_scopep)); } } diff --git a/test_regress/t/t_class_extends_this3.pl b/test_regress/t/t_class_extends_this3.pl new file mode 100755 index 000000000..aabcde63e --- /dev/null +++ b/test_regress/t/t_class_extends_this3.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_extends_this3.v b/test_regress/t/t_class_extends_this3.v new file mode 100644 index 000000000..20a66e469 --- /dev/null +++ b/test_regress/t/t_class_extends_this3.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +typedef class Cls; + +class Base; + int value = 1; + function void testBase; + if (value != 1) $stop; + endfunction +endclass + +class Cls extends Base; + function void testDerived; + if (value != 1) $stop; + endfunction +endclass + +module t (/*AUTOARG*/); + initial begin + Cls c; + c = new; + c.testBase(); + c.testDerived(); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_class_local.v b/test_regress/t/t_class_local.v index fb7ff5ae9..cd20f4eb0 100644 --- a/test_regress/t/t_class_local.v +++ b/test_regress/t/t_class_local.v @@ -4,27 +4,72 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -module t (/*AUTOARG*/); - class Cls; typedef enum {A = 10, B = 20, C = 30} en_t; + int m_pub = 1; local int m_loc = 2; protected int m_prot = B; + task f_pub; endtask + local task f_loc; endtask + protected task f_prot; endtask + static task s_pub; endtask + static local task s_loc; endtask + static protected task s_prot; endtask + task check; + Cls o; + if (m_pub != 1) $stop; + if (m_loc != 10) $stop; + if (m_prot != 20) $stop; + f_pub(); // Ok + f_loc(); // Ok + f_prot(); // Ok + s_pub(); // Ok + s_loc(); // Ok + s_prot(); // Ok + Cls::s_pub(); // Ok + Cls::s_loc(); // Ok + Cls::s_prot(); // Ok + endtask endclass +class Ext extends Cls; + task check; + if (m_pub != 1) $stop; + if (m_prot != 20) $stop; + f_pub(); // Ok + f_prot(); // Ok + s_pub(); // Ok + s_prot(); // Ok + Cls::s_pub(); // Ok + Cls::s_prot(); // Ok + endtask +endclass + +module t (/*AUTOARG*/); const Cls mod_c = new; initial begin Cls c; + Ext e; if (c.A != 10) $stop; c = new; + e = new; + if (c.m_pub != 1) $stop; if (c.m_loc != 2) $stop; c.m_loc = 10; if (c.m_loc != 10) $stop; if (c.m_prot != 20) $stop; // if (mod_c.A != 10) $stop; + // + c.check(); + e.check(); + // + Cls::s_pub(); // Ok + c.s_pub(); // Ok + e.s_pub(); // Ok + // $write("*-* All Finished *-*\n"); $finish; end From 8622c754b7981c7dea3a8f6560486c4fa36c9554 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 23:35:44 -0500 Subject: [PATCH 40/91] Fix unstable statistic --- src/V3SplitVar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index c949e3478..3d36af63d 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -960,7 +960,7 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { typedef std::map PackedVarRefMap; AstNetlist* m_netp; AstNodeModule* m_modp = nullptr; // Current module (just for log) - int m_numSplit; // Total number of split variables + int m_numSplit = 0; // Total number of split variables // key:variable to be split. value:location where the variable is referenced. PackedVarRefMap m_refs; virtual void visit(AstNodeFTask* nodep) override { From 114ab1378f1367bab02a8c738b3f7050072d07d8 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Nov 2020 23:36:09 -0500 Subject: [PATCH 41/91] Internals: Track class package on membersels --- src/V3Width.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 08ea024a3..4bb7da94d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2892,6 +2892,7 @@ private: } else { nodep->taskp(ftaskp); nodep->dtypeFrom(ftaskp); + nodep->classOrPackagep(classp); if (VN_IS(ftaskp, Task)) nodep->makeStatement(); } return; From 6095efd84eb430129f61b7a33a4ef97c3fc4ca93 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Nov 2020 07:03:01 -0500 Subject: [PATCH 42/91] Check for proper 'local' and 'protected' (#2228). --- Changes | 2 + src/V3Ast.h | 8 ++ src/V3AstNodes.h | 8 ++ src/V3Error.h | 3 +- src/V3ParseImp.h | 8 +- src/V3WidthCommit.h | 69 +++++++++++++++++ test_regress/t/t_class_local.v | 6 +- test_regress/t/t_class_local_bad.out | 106 +++++++++++++++++++++++++++ test_regress/t/t_class_local_bad.pl | 19 +++++ test_regress/t/t_class_local_bad.v | 89 ++++++++++++++++++++++ 10 files changed, 308 insertions(+), 10 deletions(-) create mode 100644 test_regress/t/t_class_local_bad.out create mode 100755 test_regress/t/t_class_local_bad.pl create mode 100644 test_regress/t/t_class_local_bad.v diff --git a/Changes b/Changes index 155200731..b0f62fc5a 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support 'with item.index'. +*** Check for proper 'local' and 'protected' (#2228). + **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] **** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] diff --git a/src/V3Ast.h b/src/V3Ast.h index 9910125d1..e8436767c 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2688,6 +2688,8 @@ private: bool m_dpiOpenChild : 1; // DPI import open array child wrapper bool m_dpiTask : 1; // DPI import task (vs. void function) bool m_isConstructor : 1; // Class constructor + bool m_isHideLocal : 1; // Verilog local + bool m_isHideProtected : 1; // Verilog protected bool m_pure : 1; // DPI import pure (vs. virtual pure) bool m_pureVirtual : 1; // Pure virtual bool m_virtual : 1; // Virtual method in class @@ -2708,6 +2710,8 @@ public: , m_dpiOpenChild{false} , m_dpiTask{false} , m_isConstructor{false} + , m_isHideLocal{false} + , m_isHideProtected{false} , m_pure{false} , m_pureVirtual{false} , m_virtual{false} { @@ -2766,6 +2770,10 @@ public: bool dpiTask() const { return m_dpiTask; } void isConstructor(bool flag) { m_isConstructor = flag; } bool isConstructor() const { return m_isConstructor; } + bool isHideLocal() const { return m_isHideLocal; } + void isHideLocal(bool flag) { m_isHideLocal = flag; } + bool isHideProtected() const { return m_isHideProtected; } + void isHideProtected(bool flag) { m_isHideProtected = flag; } void pure(bool flag) { m_pure = flag; } bool pure() const { return m_pure; } void pureVirtual(bool flag) { m_pureVirtual = flag; } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 8ac7382f9..3dfca497b 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1897,6 +1897,8 @@ private: bool m_isPullup : 1; // Tri1 bool m_isIfaceParent : 1; // dtype is reference to interface present in this module bool m_isDpiOpenArray : 1; // DPI import open array + bool m_isHideLocal : 1; // Verilog local + bool m_isHideProtected : 1; // Verilog protected bool m_noReset : 1; // Do not do automated reset/randomization bool m_noSubst : 1; // Do not substitute out references bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam @@ -1934,6 +1936,8 @@ private: m_isPullup = false; m_isIfaceParent = false; m_isDpiOpenArray = false; + m_isHideLocal = false; + m_isHideProtected = false; m_noReset = false; m_noSubst = false; m_overridenParam = false; @@ -2083,6 +2087,10 @@ public: void funcReturn(bool flag) { m_funcReturn = flag; } void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; } bool isDpiOpenArray() const { return m_isDpiOpenArray; } + bool isHideLocal() const { return m_isHideLocal; } + void isHideLocal(bool flag) { m_isHideLocal = flag; } + bool isHideProtected() const { return m_isHideProtected; } + void isHideProtected(bool flag) { m_isHideProtected = flag; } void noReset(bool flag) { m_noReset = flag; } bool noReset() const { return m_noReset; } void noSubst(bool flag) { m_noSubst = flag; } diff --git a/src/V3Error.h b/src/V3Error.h index fcf166a75..5e88ba6c2 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -52,6 +52,7 @@ public: I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE) // Error codes: E_DETECTARRAY, // Error: Unsupported: Can't detect changes on arrayed variable + E_ENCAPSULATED, // Error: local/protected violation E_PORTSHORT, // Error: Output port is connected to a constant, electrical short E_UNSUPPORTED, // Error: Unsupported (generally) E_TASKNSVAR, // Error: Task I/O not simple @@ -147,7 +148,7 @@ public: // Boolean " I_CELLDEFINE", " I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE", // Errors - "DETECTARRAY", "PORTSHORT", "UNSUPPORTED", "TASKNSVAR", + "DETECTARRAY", "ENCAPSULATED", "PORTSHORT", "UNSUPPORTED", "TASKNSVAR", // Warnings " EC_FIRST_WARN", "ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN", diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index ee58a7eeb..eb5dc8a6f 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -70,8 +70,8 @@ struct VMemberQualifiers { } void applyToNodes(AstNodeFTask* nodesp) const { for (AstNodeFTask* nodep = nodesp; nodep; nodep = VN_CAST(nodep->nextp(), NodeFTask)) { - // Ignored for now: m_local - // Ignored for now: m_protected + if (m_local) nodep->isHideLocal(true); + if (m_protected) nodep->isHideProtected(true); if (m_virtual) nodep->isVirtual(true); if (m_automatic) nodep->lifetime(VLifetime::AUTOMATIC); if (m_static) nodep->lifetime(VLifetime::STATIC); @@ -83,10 +83,10 @@ struct VMemberQualifiers { } void applyToNodes(AstVar* nodesp) const { for (AstVar* nodep = nodesp; nodep; nodep = VN_CAST(nodep->nextp(), Var)) { - // Ignored for now: m_local - // Ignored for now: m_protected // Ignored for now: m_rand // Ignored for now: m_randc + if (m_local) nodep->isHideLocal(true); + if (m_protected) nodep->isHideProtected(true); if (m_automatic) nodep->lifetime(VLifetime::AUTOMATIC); if (m_static) nodep->lifetime(VLifetime::STATIC); if (m_const) nodep->isConst(true); diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 2176bc8cd..3abe211ba 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -69,6 +69,9 @@ class WidthCommitVisitor final : public AstNVisitor { // AstVar::user1p -> bool, processed AstUser1InUse m_inuser1; + // STATE + AstNodeModule* m_modp = nullptr; + public: // METHODS static AstConst* newIfConstCommitSize(AstConst* nodep) { @@ -112,7 +115,56 @@ private: } return nodep; } + void classEncapCheck(AstNode* nodep, AstNode* defp, AstClass* defClassp) { + // Call on non-local class to check local/protected status and complain + bool local = false; + bool prot = false; + if (const auto varp = VN_CAST(defp, Var)) { + local = varp->isHideLocal(); + prot = varp->isHideProtected(); + } else if (const auto ftaskp = VN_CAST(defp, NodeFTask)) { + local = ftaskp->isHideLocal(); + prot = ftaskp->isHideProtected(); + } else { + nodep->v3fatalSrc("ref to unhandled definition type " << defp->prettyTypeName()); + } + if (local || prot) { + auto refClassp = VN_CAST(m_modp, Class); + const char* how = nullptr; + if (local && defClassp && refClassp != defClassp) { + how = "'local'"; + } else if (prot && defClassp && !classExtendedRecurse(refClassp, defClassp)) { + how = "'protected'"; + } + if (how) { + UINFO(9, "refclass " << refClassp << endl); + UINFO(9, "defclass " << defClassp << endl); + nodep->v3warn(E_ENCAPSULATED, nodep->prettyNameQ() + << " is hidden as " << how + << " within this context (IEEE 1800-2017 8.18)\n" + << nodep->warnContextPrimary() << endl + << nodep->warnOther() + << "... Location of definition" << endl + << defp->warnContextSecondary()); + } + } + } + static bool classExtendedRecurse(const AstClass* refClassp, const AstClass* defClassp) { + // Return true if refClassp is an extends class of defClassp + if (!refClassp || !defClassp) return false; + if (refClassp == defClassp) return true; + return classExtendedRecurse(refClassp->extendsp()->classp(), defClassp); + } + // VISITORS + virtual void visit(AstNodeModule* nodep) override { + VL_RESTORER(m_modp); + { + m_modp = nodep; + iterateChildren(nodep); + editDType(nodep); + } + } virtual void visit(AstConst* nodep) override { UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype"); iterate(nodep->dtypep()); // Do datatype first @@ -153,6 +205,23 @@ private: nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep())); nodep->virtRefDType2p(editOneDType(nodep->virtRefDType2p())); } + virtual void visit(AstNodeVarRef* nodep) override { + iterateChildren(nodep); + editDType(nodep); + classEncapCheck(nodep, nodep->varp(), VN_CAST(nodep->classOrPackagep(), Class)); + } + virtual void visit(AstNodeFTaskRef* nodep) override { + iterateChildren(nodep); + editDType(nodep); + classEncapCheck(nodep, nodep->taskp(), VN_CAST(nodep->classOrPackagep(), Class)); + } + virtual void visit(AstMemberSel* nodep) override { + iterateChildren(nodep); + editDType(nodep); + if (auto* classrefp = VN_CAST(nodep->fromp()->dtypep(), ClassRefDType)) { + classEncapCheck(nodep, nodep->varp(), classrefp->classp()); + } // else might be struct, etc + } virtual void visit(AstNodePreSel* nodep) override { // LCOV_EXCL_LINE // This check could go anywhere after V3Param nodep->v3fatalSrc("Presels should have been removed before this point"); diff --git a/test_regress/t/t_class_local.v b/test_regress/t/t_class_local.v index cd20f4eb0..0a5b6cf78 100644 --- a/test_regress/t/t_class_local.v +++ b/test_regress/t/t_class_local.v @@ -19,7 +19,7 @@ class Cls; task check; Cls o; if (m_pub != 1) $stop; - if (m_loc != 10) $stop; + if (m_loc != 2) $stop; if (m_prot != 20) $stop; f_pub(); // Ok f_loc(); // Ok @@ -56,10 +56,6 @@ module t (/*AUTOARG*/); c = new; e = new; if (c.m_pub != 1) $stop; - if (c.m_loc != 2) $stop; - c.m_loc = 10; - if (c.m_loc != 10) $stop; - if (c.m_prot != 20) $stop; // if (mod_c.A != 10) $stop; // diff --git a/test_regress/t/t_class_local_bad.out b/test_regress/t/t_class_local_bad.out new file mode 100644 index 000000000..102a251d1 --- /dev/null +++ b/test_regress/t/t_class_local_bad.out @@ -0,0 +1,106 @@ +%Error-ENCAPSULATED: t/t_class_local_bad.v:71:20: 'm_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 71 | bad(); if (c.m_loc != 2) $stop; + | ^~~~~ + t/t_class_local_bad.v:71:20: ... Location of definition + 15 | local int m_loc = 2; + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:72:20: 'm_prot' is hidden as 'protected' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 72 | bad(); if (c.m_prot != 20) $stop; + | ^~~~~~ + t/t_class_local_bad.v:72:20: ... Location of definition + 16 | protected int m_prot = 3; + | ^~~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:74:20: 'm_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 74 | bad(); if (e.m_loc != 2) $stop; + | ^~~~~ + t/t_class_local_bad.v:74:20: ... Location of definition + 15 | local int m_loc = 2; + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:75:20: 'm_prot' is hidden as 'protected' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 75 | bad(); if (e.m_prot != 20) $stop; + | ^~~~~~ + t/t_class_local_bad.v:75:20: ... Location of definition + 16 | protected int m_prot = 3; + | ^~~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:77:16: 'f_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 77 | bad(); c.f_loc(); + | ^~~~~ + t/t_class_local_bad.v:77:16: ... Location of definition + 18 | local task f_loc; endtask + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:78:16: 'f_prot' is hidden as 'protected' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 78 | bad(); c.f_prot(); + | ^~~~~~ + t/t_class_local_bad.v:78:16: ... Location of definition + 19 | protected task f_prot; endtask + | ^~~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:80:16: 's_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 80 | bad(); c.s_loc(); + | ^~~~~ + t/t_class_local_bad.v:80:16: ... Location of definition + 21 | static local task s_loc; endtask + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:81:16: 's_prot' is hidden as 'protected' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 81 | bad(); c.s_prot(); + | ^~~~~~ + t/t_class_local_bad.v:81:16: ... Location of definition + 22 | static protected task s_prot; endtask + | ^~~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:83:19: 's_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 83 | bad(); Cls::s_loc(); + | ^~~~~ + t/t_class_local_bad.v:83:19: ... Location of definition + 21 | static local task s_loc; endtask + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:84:19: 's_prot' is hidden as 'protected' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 84 | bad(); Cls::s_prot(); + | ^~~~~~ + t/t_class_local_bad.v:84:19: ... Location of definition + 22 | static protected task s_prot; endtask + | ^~~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:47:18: 'm_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 47 | bad(); if (m_loc != 10) $stop; + | ^~~~~ + t/t_class_local_bad.v:47:18: ... Location of definition + 15 | local int m_loc = 2; + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:50:14: 'f_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 50 | bad(); f_loc(); + | ^~~~~ + t/t_class_local_bad.v:50:14: ... Location of definition + 18 | local task f_loc; endtask + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:53:16: 'f_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 53 | bad(); o.f_loc(); + | ^~~~~ + t/t_class_local_bad.v:53:16: ... Location of definition + 18 | local task f_loc; endtask + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:56:14: 's_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 56 | bad(); s_loc(); + | ^~~~~ + t/t_class_local_bad.v:56:14: ... Location of definition + 21 | static local task s_loc; endtask + | ^~~~~ +%Error-ENCAPSULATED: t/t_class_local_bad.v:59:19: 's_loc' is hidden as 'local' within this context (IEEE 1800-2017 8.18) + : ... In instance t + 59 | bad(); Cls::s_loc(); + | ^~~~~ + t/t_class_local_bad.v:59:19: ... Location of definition + 21 | static local task s_loc; endtask + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_local_bad.pl b/test_regress/t/t_class_local_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_class_local_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_local_bad.v b/test_regress/t/t_class_local_bad.v new file mode 100644 index 000000000..636b89f43 --- /dev/null +++ b/test_regress/t/t_class_local_bad.v @@ -0,0 +1,89 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// Let context messages easily know if given line is expected ok or bad +task ok; +endtask +task bad; +endtask + +class Cls; + int m_pub = 1; + local int m_loc = 2; + protected int m_prot = 3; + task f_pub; endtask + local task f_loc; endtask + protected task f_prot; endtask + static task s_pub; endtask + static local task s_loc; endtask + static protected task s_prot; endtask + task check; + Cls o; + ok(); if (m_pub != 1) $stop; + ok(); if (m_loc != 10) $stop; + ok(); if (m_prot != 20) $stop; + ok(); f_pub(); + ok(); f_loc(); + ok(); f_prot(); + ok(); o.f_pub(); + ok(); o.f_loc(); + ok(); o.f_prot(); + ok(); s_pub(); + ok(); s_loc(); + ok(); s_prot(); + ok(); Cls::s_pub(); + ok(); Cls::s_loc(); + ok(); Cls::s_prot(); + endtask +endclass + +class Ext extends Cls; + task check; + Ext o; + ok(); if (m_pub != 1) $stop; + bad(); if (m_loc != 10) $stop; + ok(); if (m_prot != 20) $stop; + ok(); f_pub(); + bad(); f_loc(); + ok(); f_prot(); + ok(); o.f_pub(); + bad(); o.f_loc(); + ok(); o.f_prot(); + ok(); s_pub(); + bad(); s_loc(); + ok(); s_prot(); + ok(); Cls::s_pub(); + bad(); Cls::s_loc(); + ok(); Cls::s_prot(); + endtask +endclass + +module t (/*AUTOARG*/); + initial begin + Cls c; + Ext e; + c = new; + e = new; + ok(); if (c.m_pub != 1) $stop; + bad(); if (c.m_loc != 2) $stop; + bad(); if (c.m_prot != 20) $stop; + ok(); if (e.m_pub != 1) $stop; + bad(); if (e.m_loc != 2) $stop; + bad(); if (e.m_prot != 20) $stop; + ok(); c.f_pub(); + bad(); c.f_loc(); + bad(); c.f_prot(); + ok(); c.s_pub(); + bad(); c.s_loc(); + bad(); c.s_prot(); + ok(); Cls::s_pub(); + bad(); Cls::s_loc(); + bad(); Cls::s_prot(); + // + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule From 085ef5fc054c2ffde25661f6c74a460ec4c8f619 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Nov 2020 20:05:44 -0500 Subject: [PATCH 43/91] Fix extern function var refs getting errors. --- src/V3LinkDot.cpp | 18 ++++++++++-------- test_regress/t/t_class_extern.v | 33 +++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index ab3ead042..798dd23c8 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -363,7 +363,8 @@ public: UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9, " INSERTblk se" << cvtToHex(symp) << " above=se" << cvtToHex(abovep) - << " node=" << nodep << endl); + << " pkg=" << cvtToHex(classOrPackagep) << " node=" << nodep + << endl); symp->parentp(abovep); symp->classOrPackagep(classOrPackagep); symp->fallbackp(abovep); @@ -378,7 +379,8 @@ public: UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9, " INSERTsym se" << cvtToHex(symp) << " name='" << name << "' above=se" - << cvtToHex(abovep) << " node=" << nodep << endl); + << cvtToHex(abovep) << " pkg=" << cvtToHex(classOrPackagep) + << " node=" << nodep << endl); // We don't remember the ent associated with each node, because we // need a unique scope entry for each instantiation symp->classOrPackagep(classOrPackagep); @@ -981,6 +983,7 @@ class LinkDotFindVisitor final : public AstNVisitor { UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Function/Task not under module?"); if (nodep->name() == "new") m_explicitNew = true; // Remember the existing symbol table scope + VL_RESTORER(m_classOrPackagep); VL_RESTORER(m_curSymp); VSymEnt* const oldCurSymp = m_curSymp; { @@ -1007,14 +1010,13 @@ class LinkDotFindVisitor final : public AstNVisitor { } } } + // Set the class as package for iteration + if (VN_IS(m_curSymp->nodep(), Class)) { + m_classOrPackagep = VN_CAST(m_curSymp->nodep(), Class); + } // Create symbol table for the task's vars string name = string{nodep->isExternProto() ? "extern " : ""} + nodep->name(); - auto pkgp = m_classOrPackagep; - // Set the class as package for static class methods - if (nodep->lifetime().isStatic() && VN_IS(m_curSymp->nodep(), Class)) { - pkgp = VN_CAST(m_curSymp->nodep(), Class); - } - m_curSymp = m_statep->insertBlock(m_curSymp, name, nodep, pkgp); + m_curSymp = m_statep->insertBlock(m_curSymp, name, nodep, m_classOrPackagep); m_curSymp->fallbackp(oldCurSymp); // Convert the func's range to the output variable // This should probably be done in the Parser instead, as then we could diff --git a/test_regress/t/t_class_extern.v b/test_regress/t/t_class_extern.v index eb15c625b..ba96dc70e 100644 --- a/test_regress/t/t_class_extern.v +++ b/test_regress/t/t_class_extern.v @@ -5,23 +5,44 @@ // SPDX-License-Identifier: CC0-1.0 class Cls; - extern task extcls(); - extern function int extone(); + extern function int ext_f_np; + extern function int ext_f_p(); + extern function int ext_f_i(int in); + extern task ext_t_np; + extern task ext_t_p(); + extern task ext_t_i(int in); endclass -function int Cls::extone(); +function int Cls::ext_f_np; return 1; endfunction -task Cls::extcls(); +function int Cls::ext_f_p(); + return 2; +endfunction + +function int Cls::ext_f_i(int in); + return in+1; +endfunction + +task Cls::ext_t_np(); $write("*-* All Finished *-*\n"); +endtask +task Cls::ext_t_p(); $finish; endtask +task Cls::ext_t_i(int in); + if (in != 2) $stop; +endtask module t (/*AUTOARG*/); initial begin Cls c = new; - if (c.extone() != 1) $stop; - c.extcls(); + if (c.ext_f_np() != 1) $stop; + if (c.ext_f_p() != 2) $stop; + if (c.ext_f_i(10) != 11) $stop; + c.ext_t_i(2); + c.ext_t_np(); + c.ext_t_p(); end endmodule From f2d8e45d721289558fddc0539b8beb0b62543d5b Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Nov 2020 20:57:30 -0500 Subject: [PATCH 44/91] For performance, use unordered_set/map where possible. No functional change intended. --- include/verilated_heavy.h | 5 +++-- include/verilated_syms.h | 4 +++- include/verilated_vpi.cpp | 2 +- src/V3Delayed.cpp | 2 +- src/V3EmitCSyms.cpp | 2 +- src/V3Gate.cpp | 2 +- src/V3Graph.cpp | 2 +- src/V3GraphDfa.cpp | 2 +- src/V3GraphStream.h | 2 +- src/V3Hashed.cpp | 2 +- src/V3HierBlock.cpp | 5 +++-- src/V3HierBlock.h | 7 ++++--- src/V3Inline.cpp | 4 ++-- src/V3Life.cpp | 4 ++-- src/V3LinkDot.cpp | 2 +- src/V3LinkParse.cpp | 2 +- src/V3Param.cpp | 2 +- src/V3Simulate.h | 2 +- src/V3String.h | 3 ++- src/V3SymTable.h | 2 +- src/V3Task.cpp | 2 +- src/V3Tristate.cpp | 2 +- 22 files changed, 34 insertions(+), 28 deletions(-) diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index c5409364a..f6cb8dd71 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -32,6 +32,7 @@ #include #include #include +#include //=================================================================== // String formatters (required by below containers) @@ -267,7 +268,7 @@ public: void shuffle() { std::shuffle(m_deque.begin(), m_deque.end(), VlURNG()); } VlQueue unique() const { VlQueue out; - std::set saw; + std::unordered_set saw; for (const auto& i : m_deque) { auto it = saw.find(i); if (it == saw.end()) { @@ -280,7 +281,7 @@ public: VlQueue unique_index() const { VlQueue out; IData index = 0; - std::set saw; + std::unordered_set saw; for (const auto& i : m_deque) { auto it = saw.find(i); if (it == saw.end()) { diff --git a/include/verilated_syms.h b/include/verilated_syms.h index c8f8514fc..29fdfcb90 100644 --- a/include/verilated_syms.h +++ b/include/verilated_syms.h @@ -31,6 +31,7 @@ #include "verilated_sym_props.h" #include +#include #include //====================================================================== @@ -58,7 +59,8 @@ public: typedef std::vector VerilatedScopeVector; -class VerilatedHierarchyMap final : public std::map { +class VerilatedHierarchyMap final + : public std::unordered_map { public: VerilatedHierarchyMap() = default; ~VerilatedHierarchyMap() = default; diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 3f0b34218..104383c2a 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -497,7 +497,7 @@ public: assertOneCheck(); VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange]; bool called = false; - typedef std::set VpioVarSet; + typedef std::unordered_set VpioVarSet; VpioVarSet update; // set of objects to update after callbacks if (cbObjList.empty()) return called; const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index c03478ad1..096dbe912 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -98,7 +98,7 @@ private: typedef std::map, AstVar*> VarMap; VarMap m_modVarMap; // Table of new var names created under module VDouble0 m_statSharedSet; // Statistic tracking - typedef std::map ScopeVecMap; + typedef std::unordered_map ScopeVecMap; ScopeVecMap m_scopeVecMap; // Next var number for each scope // METHODS diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index fe2ef52f8..3c8fb2e6e 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -109,7 +109,7 @@ class EmitCSyms final : EmitCBaseVisitor { int m_numStmts = 0; // Number of statements output int m_funcNum = 0; // CFunc split function number V3OutCFile* m_ofpBase = nullptr; // Base (not split) C file - std::map m_usesVfinal; // Split method uses __Vfinal + std::unordered_map m_usesVfinal; // Split method uses __Vfinal // METHODS void emitSymHdr(); diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 72aca1174..7049a14a4 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -906,7 +906,7 @@ void GateVisitor::optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode* class GateDedupeHash final : public V3HashedUserSame { public: // TYPES - typedef std::set NodeSet; + typedef std::unordered_set NodeSet; private: // NODE STATE diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index 1e7216bfd..518c1ce70 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -335,7 +335,7 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) const { // We use a map here, as we don't want to corrupt anything (userp) in the graph, // and we don't care if this is slow. - std::map numMap; + std::unordered_map numMap; // Print vertices int n = 0; diff --git a/src/V3GraphDfa.cpp b/src/V3GraphDfa.cpp index 7669fa619..3d193aca3 100644 --- a/src/V3GraphDfa.cpp +++ b/src/V3GraphDfa.cpp @@ -294,7 +294,7 @@ private: UINFO(9, " On dfaState " << dfaStatep << endl); // From this dfaState, what corresponding nfaStates have what inputs? - std::set inputs; + std::unordered_set inputs; // Foreach NFA state (this DFA state was formed from) for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep; dfaEdgep = dfaEdgep->outNextp()) { diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index cc53b9e9d..f7bd78cb5 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -81,7 +81,7 @@ private: }; typedef std::set ReadyVertices; - typedef std::unordered_map WaitingVertices; + typedef std::map WaitingVertices; // MEMBERS VxHolderCmp m_vxHolderCmp; // Vertext comparison functor diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index 459bed724..a72e45106 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -153,7 +153,7 @@ void V3Hashed::dumpFile(const string& filename, bool tree) { const std::unique_ptr logp(V3File::new_ofstream(filename)); if (logp->fail()) v3fatal("Can't write " << filename); - std::map dist; + std::unordered_map dist; V3Hash lasthash; int num_in_bucket = 0; diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index be21161e2..41f647826 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -240,7 +240,7 @@ class HierBlockUsageCollectVisitor final : public AstNVisitor { AstUser1InUse m_inuser1; // STATE - typedef std::set ModuleSet; + typedef std::unordered_set ModuleSet; V3HierBlockPlan* const m_planp; AstModule* m_modp = nullptr; // The current module AstModule* m_hierBlockp = nullptr; // The nearest parent module that is a hierarchical block @@ -355,7 +355,8 @@ void V3HierBlockPlan::createPlan(AstNetlist* nodep) { } V3HierBlockPlan::HierVector V3HierBlockPlan::hierBlocksSorted() const { - typedef std::map> ChildrenMap; + typedef std::unordered_map> + ChildrenMap; ChildrenMap childrenOfHierBlock; HierVector sorted; diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h index e5409d1fd..7ce652a74 100644 --- a/src/V3HierBlock.h +++ b/src/V3HierBlock.h @@ -29,6 +29,7 @@ #include #include #include +#include #include class AstNodeModule; @@ -40,8 +41,8 @@ class AstVar; class V3HierBlock final { public: typedef std::vector GParams; - typedef std::set HierBlockSet; - typedef std::set NodeModuleSet; + typedef std::unordered_set HierBlockSet; + typedef std::unordered_set NodeModuleSet; private: // TYPES @@ -96,7 +97,7 @@ public: // Holds relashonship between AstNodeModule and V3HierBlock class V3HierBlockPlan final { - typedef std::map HierMap; + typedef std::unordered_map HierMap; HierMap m_blocks; V3HierBlockPlan() = default; diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 829cf1e6c..c72990a3a 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -74,10 +74,10 @@ private: // Within the context of a given module, LocalInstanceMap maps // from child modules to the count of each child's local instantiations. - typedef std::map LocalInstanceMap; + typedef std::unordered_map LocalInstanceMap; // We keep a LocalInstanceMap for each module in the design - std::map m_instances; + std::unordered_map m_instances; // METHODS VL_DEBUG_FUNC; // Declare debug() diff --git a/src/V3Life.cpp b/src/V3Life.cpp index fc4708235..daa9028f5 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -123,7 +123,7 @@ class LifeBlock final { // LIFE MAP // For each basic block, we'll make a new map of what variables that if/else is changing - typedef std::map LifeMap; + typedef std::unordered_map LifeMap; LifeMap m_map; // Current active lifetime map for current scope LifeBlock* m_aboveLifep; // Upper life, or nullptr LifeState* m_statep; // Current global state @@ -278,7 +278,7 @@ private: // LIFE MAP // For each basic block, we'll make a new map of what variables that if/else is changing - typedef std::map LifeMap; + typedef std::unordered_map LifeMap; // cppcheck-suppress memleak // cppcheck bug - it is deleted LifeBlock* m_lifep; // Current active lifetime map for current scope diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 798dd23c8..5ddf96eb6 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -141,7 +141,7 @@ public: private: // TYPES typedef std::multimap NameScopeSymMap; - typedef std::map ScopeAliasMap; + typedef std::unordered_map ScopeAliasMap; typedef std::set> ImplicitNameSet; typedef std::vector IfaceVarSyms; typedef std::vector> IfaceModSyms; diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 2dce23b64..a3883b91c 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -45,7 +45,7 @@ private: // TYPES typedef std::map, AstTypedef*> ImplTypedefMap; - typedef std::set FileLineSet; + typedef std::unordered_set FileLineSet; // STATE AstVar* m_varp = nullptr; // Variable we're under diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 6c491ae5e..91def7f9f 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -216,7 +216,7 @@ private: typedef std::deque> IfaceRefRefs; // STATE - typedef std::map CloneMap; + typedef std::unordered_map CloneMap; struct ModInfo { AstNodeModule* m_modp; // Module with specified name CloneMap m_cloneMap; // Map of old-varp -> new cloned varp diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 6a251e905..edec6cffe 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -61,7 +61,7 @@ public: }; typedef std::deque ConstDeque; -typedef std::map ConstPile; +typedef std::unordered_map ConstPile; class SimulateVisitor VL_NOT_FINAL : public AstNVisitor { // Simulate a node tree, returning value of variables diff --git a/src/V3String.h b/src/V3String.h index af5437092..6bc0bd61f 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -23,8 +23,9 @@ // No V3 headers here - this is a base class for Vlc etc #include -#include #include +#include +#include #include //###################################################################### diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 512bdedf1..0b0cd7242 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -36,7 +36,7 @@ class VSymEnt; //###################################################################### // Symbol table -typedef std::set VSymConstMap; +typedef std::unordered_set VSymConstMap; class VSymEnt final { // Symbol table that can have a "superior" table for resolving upper references diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 11829195d..38afb4c39 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -104,7 +104,7 @@ private: // TYPES typedef std::map, AstVarScope*> VarToScopeMap; - typedef std::map FuncToClassMap; + typedef std::unordered_map FuncToClassMap; typedef std::vector Initials; // MEMBERS VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 8988b6258..237636f14 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -329,7 +329,7 @@ class TristateVisitor final : public TristateBaseVisitor { // TYPES typedef std::vector RefVec; - typedef std::map VarMap; + typedef std::unordered_map VarMap; enum : uint8_t { U2_GRAPHING = 1, // bit[0] if did m_graphing visit U2_NONGRAPH = 2, // bit[1] if did !m_graphing visit From de931d6a97930a0ece0294b2b671979e393e489c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Nov 2020 21:09:25 -0500 Subject: [PATCH 45/91] Fix LHS is not a lvalue when using tristate with -Oi. --- src/V3Tristate.cpp | 1 + test_regress/t/t_altera_lpm_mult_noinl.pl | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 test_regress/t/t_altera_lpm_mult_noinl.pl diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 237636f14..ca5119846 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -1107,6 +1107,7 @@ class TristateVisitor final : public TristateBaseVisitor { AstVar* enVarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, nodep->name() + "__en" + cvtToStr(m_unique++), VFlagBitPacked(), enModVarp->width()); + enModVarp->direction(VDirection::INPUT); UINFO(9, " newenv " << enVarp << endl); AstPin* enpinp = new AstPin(nodep->fileline(), nodep->pinNum(), diff --git a/test_regress/t/t_altera_lpm_mult_noinl.pl b/test_regress/t/t_altera_lpm_mult_noinl.pl new file mode 100755 index 000000000..2eac39a3a --- /dev/null +++ b/test_regress/t/t_altera_lpm_mult_noinl.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(vlt_all => 1); + +top_filename("t/t_altera_lpm.v"); +(my $module = $Self->{name}) =~ s/.*t_altera_//; +$module =~ s/_noinl//; + +compile( + verilator_flags2 => ["--top-module ${module}", "-Oi"] + ); + +ok(1); +1; From ac2058c7ece9b01e7c3161a62fd0e1ef6121ce17 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Nov 2020 21:18:13 -0500 Subject: [PATCH 46/91] Tests: Fix t_unopt_combo_waive with -Oi --- test_regress/t/t_unopt_combo.vlt | 2 +- test_regress/t/t_unopt_combo_waive.out | 0 test_regress/t/t_unopt_combo_waive.pl | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 test_regress/t/t_unopt_combo_waive.out diff --git a/test_regress/t/t_unopt_combo.vlt b/test_regress/t/t_unopt_combo.vlt index f07f4d9f5..ffec0fb7a 100644 --- a/test_regress/t/t_unopt_combo.vlt +++ b/test_regress/t/t_unopt_combo.vlt @@ -1,3 +1,3 @@ `verilator_config -lint_off -rule UNOPTFLAT -file "*t_unopt_combo.v" -match "Signal unoptimizable: Feedback to clock or circular logic: 't.c'" +lint_off -rule UNOPTFLAT -file "*t_unopt_combo.v" -match "Signal unoptimizable: Feedback to clock or circular logic: *" diff --git a/test_regress/t/t_unopt_combo_waive.out b/test_regress/t/t_unopt_combo_waive.out deleted file mode 100644 index e69de29bb..000000000 diff --git a/test_regress/t/t_unopt_combo_waive.pl b/test_regress/t/t_unopt_combo_waive.pl index e9505bfa5..99f3041e4 100755 --- a/test_regress/t/t_unopt_combo_waive.pl +++ b/test_regress/t/t_unopt_combo_waive.pl @@ -14,7 +14,7 @@ top_filename("t/t_unopt_combo.v"); compile( v_flags2 => ['+define+ATTRIBUTES', "t/t_unopt_combo.vlt"], - expect_filename => $Self->{golden_filename}, # Expect no output, as we waived + # Passes, as we waived ); ok(1); From 380137a402a1b6d5d9759cda92e4996ec152976b Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Nov 2020 21:34:56 -0500 Subject: [PATCH 47/91] Fix internal pointer shown on CLKDATA warnings --- src/V3Order.cpp | 4 ++-- test_regress/t/t_clocker.pl | 2 +- test_regress/t/t_clocker.v | 15 ++++++--------- test_regress/t/t_clocker_bad.out | 11 +++++++++++ test_regress/t/t_clocker_bad.pl | 21 +++++++++++++++++++++ 5 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 test_regress/t/t_clocker_bad.out create mode 100755 test_regress/t/t_clocker_bad.pl diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 6d734e123..cca5359fe 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -290,8 +290,8 @@ private: // do the marking if (m_hasClk) { if (nodep->lhsp()->width() > m_rightClkWidth) { - nodep->v3warn(CLKDATA, - "Clock is assigned to part of data signal " << nodep->lhsp()); + nodep->v3warn(CLKDATA, "Clock is assigned to part of data signal " + << nodep->lhsp()->prettyNameQ()); UINFO(4, "CLKDATA: lhs with width " << nodep->lhsp()->width() << endl); UINFO(4, " but rhs clock with width " << m_rightClkWidth << endl); return; // skip the marking diff --git a/test_regress/t/t_clocker.pl b/test_regress/t/t_clocker.pl index 1af79252d..46b824b58 100755 --- a/test_regress/t/t_clocker.pl +++ b/test_regress/t/t_clocker.pl @@ -11,7 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( - verilator_flags2 => ["--trace"] + verilator_flags2 => ["--trace", "-Wno-CLKDATA"] ); execute( diff --git a/test_regress/t/t_clocker.v b/test_regress/t/t_clocker.v index 7a4bdca32..1694ae894 100644 --- a/test_regress/t/t_clocker.v +++ b/test_regress/t/t_clocker.v @@ -18,6 +18,7 @@ module t (/*AUTOARG*/ ); input clk; output reg res; + // When not inlining the below may trigger CLKDATA output reg [7:0] res8; output reg [15:0] res16; @@ -41,23 +42,19 @@ module t (/*AUTOARG*/ // the following two assignment triggers the CLKDATA warning // because on LHS there are a mix of signals both CLOCK and // DATA - /* verilator lint_off CLKDATA */ assign res8 = {clk_3, 1'b0, clk_4}; assign res16 = {count, clk_3, clk_1, clk_4}; - /* verilator lint_on CLKDATA */ initial - count = 0; + count = 0; always @(posedge clk_final or negedge clk_final) begin - count = count + 1; - // the following assignment should trigger the CLKDATA warning - // because CLOCK signal is used as DATA in sequential block - /* verilator lint_off CLKDATA */ - res <= clk_final; - /* verilator lint_on CLKDATA */ + count = count + 1; + // the following assignment should trigger the CLKDATA warning + // because CLOCK signal is used as DATA in sequential block + res <= clk_final; if ( count == 8'hf) begin $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_clocker_bad.out b/test_regress/t/t_clocker_bad.out new file mode 100644 index 000000000..eb3477c3c --- /dev/null +++ b/test_regress/t/t_clocker_bad.out @@ -0,0 +1,11 @@ +%Warning-CLKDATA: t/t_clocker.v:45:17: Clock is assigned to part of data signal 'res8' + 45 | assign res8 = {clk_3, 1'b0, clk_4}; + | ^ + ... Use "/* verilator lint_off CLKDATA */" and lint_on around source to disable this message. +%Warning-CLKDATA: t/t_clocker.v:46:17: Clock is assigned to part of data signal 'res16' + 46 | assign res16 = {count, clk_3, clk_1, clk_4}; + | ^ +%Warning-CLKDATA: t/t_clocker.v:57:14: Clock used as data (on rhs of assignment) in sequential block 'clk' + 57 | res <= clk_final; + | ^~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_clocker_bad.pl b/test_regress/t/t_clocker_bad.pl new file mode 100755 index 000000000..0628b9d18 --- /dev/null +++ b/test_regress/t/t_clocker_bad.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 2004 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(vlt => 1); + +top_filename("t/t_clocker.v"); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; From ffbae97a3d2bf553f673645a82b34284e559abc9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Nov 2020 21:42:47 -0500 Subject: [PATCH 48/91] Tests: Make t_lint_syncasyncnet_bad etc tolerate -Oi. --- test_regress/t/t_lint_syncasyncnet_bad.out | 10 ++-- test_regress/t/t_lint_syncasyncnet_bad.v | 58 ++++------------------ test_regress/t/t_mem_twoedge.v | 2 +- 3 files changed, 16 insertions(+), 54 deletions(-) diff --git a/test_regress/t/t_lint_syncasyncnet_bad.out b/test_regress/t/t_lint_syncasyncnet_bad.out index fd13ef2e0..dd4ca5627 100644 --- a/test_regress/t/t_lint_syncasyncnet_bad.out +++ b/test_regress/t/t_lint_syncasyncnet_bad.out @@ -1,9 +1,9 @@ -%Warning-SYNCASYNCNET: t/t_lint_syncasyncnet_bad.v:16:25: Signal flopped as both synchronous and async: 'rst_both_l' - t/t_lint_syncasyncnet_bad.v:91:15: ... Location of async usage - 91 | q2 <= (~rst_both_l) ? 1'b0 : d; +%Warning-SYNCASYNCNET: t/t_lint_syncasyncnet_bad.v:14:10: Signal flopped as both synchronous and async: 'rst_both_l' + t/t_lint_syncasyncnet_bad.v:52:15: ... Location of async usage + 52 | q4 <= (~rst_both_l) ? 1'b0 : d; | ^~~~~~~~~~ - t/t_lint_syncasyncnet_bad.v:59:14: ... Location of sync usage - 59 | q2 <= (rst_both_l) ? d : 1'b0; + t/t_lint_syncasyncnet_bad.v:34:14: ... Location of sync usage + 34 | q2 <= (rst_both_l) ? d : 1'b0; | ^~~~~~~~~~ ... Use "/* verilator lint_off SYNCASYNCNET */" and lint_on around source to disable this message. %Error: Exiting due to diff --git a/test_regress/t/t_lint_syncasyncnet_bad.v b/test_regress/t/t_lint_syncasyncnet_bad.v index f941d0514..9db96f3fe 100644 --- a/test_regress/t/t_lint_syncasyncnet_bad.v +++ b/test_regress/t/t_lint_syncasyncnet_bad.v @@ -6,40 +6,15 @@ module t (/*AUTOARG*/ // Inputs - rst_sync_l, rst_both_l, rst_async_l, d, clk + clk, rst_both_l, rst_sync_l, rst_async_l, d ); /*AUTOINPUT*/ - // Beginning of automatic inputs (from unused autoinst inputs) - input clk; // To sub1 of sub1.v, ... - input d; // To sub1 of sub1.v, ... - input rst_async_l; // To sub2 of sub2.v - input rst_both_l; // To sub1 of sub1.v, ... - input rst_sync_l; // To sub1 of sub1.v - // End of automatics - - sub1 sub1 (/*AUTOINST*/ - // Inputs - .clk (clk), - .rst_both_l (rst_both_l), - .rst_sync_l (rst_sync_l), - .d (d)); - sub2 sub2 (/*AUTOINST*/ - // Inputs - .clk (clk), - .rst_both_l (rst_both_l), - .rst_async_l (rst_async_l), - .d (d)); -endmodule - -module sub1 (/*AUTOARG*/ - // Inputs - clk, rst_both_l, rst_sync_l, d - ); input clk; input rst_both_l; input rst_sync_l; - //input rst_async_l; + input rst_async_l; + input d; reg q1; reg q2; @@ -60,40 +35,27 @@ module sub1 (/*AUTOARG*/ if (0 && q1 && q2) ; end -endmodule - -module sub2 (/*AUTOARG*/ - // Inputs - clk, rst_both_l, rst_async_l, d - ); - - input clk; - input rst_both_l; - //input rst_sync_l; - input rst_async_l; - input d; - reg q1; - reg q2; reg q3; - always @(posedge clk or negedge rst_async_l) begin if (~rst_async_l) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops - q1 <= 1'h0; + q3 <= 1'h0; // End of automatics end else begin - q1 <= d; + q3 <= d; end end + reg q4; always @(posedge clk or negedge rst_both_l) begin - q2 <= (~rst_both_l) ? 1'b0 : d; + q4 <= (~rst_both_l) ? 1'b0 : d; end // Make there be more async uses than sync uses + reg q5; always @(posedge clk or negedge rst_both_l) begin - q3 <= (~rst_both_l) ? 1'b0 : d; - if (0 && q1 && q2 && q3) ; + q5 <= (~rst_both_l) ? 1'b0 : d; + if (0 && q3 && q4 && q5) ; end endmodule diff --git a/test_regress/t/t_mem_twoedge.v b/test_regress/t/t_mem_twoedge.v index 2a2af9faf..9c241853c 100644 --- a/test_regress/t/t_mem_twoedge.v +++ b/test_regress/t/t_mem_twoedge.v @@ -90,9 +90,9 @@ module Test (/*AUTOARG*/ input [7:0] d0; input [7:0] d1; output reg [31:0] out; + // verilator lint_off MULTIDRIVEN output reg [15:0] out2; - // verilator lint_off MULTIDRIVEN reg [7:0] mem [4]; // verilator lint_on MULTIDRIVEN From ad21f2e850e84209f99d5aa6de5ce2c54167cce3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 26 Nov 2020 08:28:53 -0500 Subject: [PATCH 49/91] Fix 'this' in extern functions. --- src/V3LinkDot.cpp | 2 +- test_regress/t/t_class_uses_this.v | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 5ddf96eb6..a0cb84763 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2024,7 +2024,7 @@ private: if (VN_IS(nodep->lhsp(), ParseRef) && nodep->lhsp()->name() == "this") { VSymEnt* classSymp = m_ds.m_dotSymp; do { - classSymp = classSymp->fallbackp(); + classSymp = classSymp->parentp(); } while (classSymp && !VN_IS(classSymp->nodep(), Class)); m_ds.m_dotSymp = classSymp; if (!classSymp) { diff --git a/test_regress/t/t_class_uses_this.v b/test_regress/t/t_class_uses_this.v index d1a30b01a..531c6e1cb 100644 --- a/test_regress/t/t_class_uses_this.v +++ b/test_regress/t/t_class_uses_this.v @@ -4,31 +4,39 @@ // any use, without warranty, 2020 Rafal Kapuscik // SPDX-License-Identifier: CC0-1.0 // -class foo; +class Cls; bit [3:0] addr; - function void set (bit [3:0] addr); + function void set(bit [3:0] addr); begin : body this.addr = addr; end : body endfunction + extern function void setext(bit [3:0] addr); endclass +function void Cls::setext(bit [3:0] addr); + this.addr = addr; +endfunction + module t(/*AUTOARG*/ // Inputs clk ); input clk; - foo bar; - foo baz; + Cls bar; + Cls baz; initial begin - bar = new(); - baz = new(); - bar.set(4); + bar = new(); + baz = new(); + bar.set(4); `ifdef TEST_VERBOSE - $display(bar.addr); - $display(baz.addr); + $display(bar.addr); + $display(baz.addr); `endif - $write("*-* All Finished *-*\n"); - $finish; + if (bar.addr != 4) $stop; + bar.setext(2); + if (bar.addr != 2) $stop; + $write("*-* All Finished *-*\n"); + $finish; end endmodule From 60a1d25a96dfa5990c04e7728ee0578bbc60ba16 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 26 Nov 2020 08:55:32 -0500 Subject: [PATCH 50/91] Fix extern function member references. --- src/V3LinkDot.cpp | 5 +++-- test_regress/t/t_class_extern.v | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index a0cb84763..45c949149 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -985,7 +985,7 @@ class LinkDotFindVisitor final : public AstNVisitor { // Remember the existing symbol table scope VL_RESTORER(m_classOrPackagep); VL_RESTORER(m_curSymp); - VSymEnt* const oldCurSymp = m_curSymp; + VSymEnt* upSymp = m_curSymp; { // Change to appropriate package if extern declaration (vs definition) if (nodep->classOrPackagep()) { @@ -1000,6 +1000,7 @@ class LinkDotFindVisitor final : public AstNVisitor { nodep->v3error("Extern declaration's scope is not a defined class"); } else { m_curSymp = m_statep->getNodeSym(classp); + upSymp = m_curSymp; if (!nodep->isExternDef()) { // Move it to proper spot under the target class nodep->unlinkFrBack(); @@ -1017,7 +1018,7 @@ class LinkDotFindVisitor final : public AstNVisitor { // Create symbol table for the task's vars string name = string{nodep->isExternProto() ? "extern " : ""} + nodep->name(); m_curSymp = m_statep->insertBlock(m_curSymp, name, nodep, m_classOrPackagep); - m_curSymp->fallbackp(oldCurSymp); + m_curSymp->fallbackp(upSymp); // Convert the func's range to the output variable // This should probably be done in the Parser instead, as then we could // just attach normal signal attributes to it. diff --git a/test_regress/t/t_class_extern.v b/test_regress/t/t_class_extern.v index ba96dc70e..94a71825f 100644 --- a/test_regress/t/t_class_extern.v +++ b/test_regress/t/t_class_extern.v @@ -5,6 +5,7 @@ // SPDX-License-Identifier: CC0-1.0 class Cls; + int value; extern function int ext_f_np; extern function int ext_f_p(); extern function int ext_f_i(int in); @@ -18,7 +19,7 @@ function int Cls::ext_f_np; endfunction function int Cls::ext_f_p(); - return 2; + return value; endfunction function int Cls::ext_f_i(int in); @@ -33,16 +34,17 @@ task Cls::ext_t_p(); endtask task Cls::ext_t_i(int in); if (in != 2) $stop; + value = in; endtask module t (/*AUTOARG*/); initial begin Cls c = new; - if (c.ext_f_np() != 1) $stop; - if (c.ext_f_p() != 2) $stop; - if (c.ext_f_i(10) != 11) $stop; c.ext_t_i(2); c.ext_t_np(); c.ext_t_p(); + if (c.ext_f_np() != 1) $stop; + if (c.ext_f_p() != 2) $stop; + if (c.ext_f_i(10) != 11) $stop; end endmodule From 1a92a44c7d407187b107b5cf3691b334127efcf8 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 26 Nov 2020 09:38:47 -0500 Subject: [PATCH 51/91] Internals: Assert on misexpected 'new'. --- src/V3Width.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 4bb7da94d..6291db047 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -3091,7 +3091,8 @@ private: virtual void visit(AstNew* nodep) override { if (nodep->didWidthAndSet()) return; - AstClassRefDType* refp = VN_CAST(m_vup->dtypeNullSkipRefp(), ClassRefDType); + AstClassRefDType* refp + = m_vup ? VN_CAST(m_vup->dtypeNullSkipRefp(), ClassRefDType) : nullptr; if (!refp) { // e.g. int a = new; nodep->v3error("new() not expected in this context"); return; From a37866ee92f2aa8aeeae8d6e317406b8e9bdb16a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 26 Nov 2020 11:06:59 -0500 Subject: [PATCH 52/91] Support 'super'. --- Changes | 2 ++ src/V3AstNodes.cpp | 3 +++ src/V3LinkDot.cpp | 34 +++++++++++++++++++++--- test_regress/t/t_class_extends_this.out | 25 ----------------- test_regress/t/t_class_extends_this.pl | 4 +-- test_regress/t/t_class_extends_this.v | 21 ++++++++++----- test_regress/t/t_class_super_bad.out | 4 +++ test_regress/t/t_class_super_bad.pl | 19 +++++++++++++ test_regress/t/t_class_super_bad.v | 19 +++++++++++++ test_regress/t/t_class_super_bad2.out | 4 +++ test_regress/t/t_class_super_bad2.pl | 19 +++++++++++++ test_regress/t/t_class_super_bad2.v | 12 +++++++++ test_regress/t/t_class_uses_this_bad.out | 2 +- test_regress/t/t_interface2.v | 4 +++ 14 files changed, 133 insertions(+), 39 deletions(-) delete mode 100644 test_regress/t/t_class_extends_this.out create mode 100644 test_regress/t/t_class_super_bad.out create mode 100755 test_regress/t/t_class_super_bad.pl create mode 100644 test_regress/t/t_class_super_bad.v create mode 100644 test_regress/t/t_class_super_bad2.out create mode 100755 test_regress/t/t_class_super_bad2.pl create mode 100644 test_regress/t/t_class_super_bad2.v diff --git a/Changes b/Changes index b0f62fc5a..023477ec9 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support $random and $urandom seeds. +*** Support 'super'. + *** Support 'with item.index'. *** Check for proper 'local' and 'protected' (#2228). diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index dac9ca69e..9978297e5 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1180,6 +1180,9 @@ void AstClass::dump(std::ostream& str) const { } AstClass* AstClassExtends::classp() const { AstClassRefDType* refp = VN_CAST(dtypep(), ClassRefDType); + if (VL_UNLIKELY(!refp)) { // LinkDot uses this for 'super.' + refp = VN_CAST(childDTypep(), ClassRefDType); + } UASSERT_OBJ(refp, this, "class extends non-ref"); return refp->classp(); } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 45c949149..1c05ae13c 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2027,10 +2027,34 @@ private: do { classSymp = classSymp->parentp(); } while (classSymp && !VN_IS(classSymp->nodep(), Class)); - m_ds.m_dotSymp = classSymp; if (!classSymp) { - nodep->v3error("'this' used outside class"); + nodep->v3error("'this' used outside class (IEEE 1800-2017 8.11)"); m_ds.m_dotErr = true; + } else { + m_ds.m_dotSymp = classSymp; + UINFO(8, " this. " << m_ds.ascii() << endl); + } + } else if (VN_IS(nodep->lhsp(), ParseRef) && nodep->lhsp()->name() == "super") { + VSymEnt* classSymp = m_ds.m_dotSymp; + do { + classSymp = classSymp->parentp(); + } while (classSymp && !VN_IS(classSymp->nodep(), Class)); + if (!classSymp) { + nodep->v3error("'super' used outside class (IEEE 1800-2017 8.15)"); + m_ds.m_dotErr = true; + } else { + auto classp = VN_CAST(classSymp->nodep(), Class); + if (!classp->extendsp()) { + nodep->v3error("'super' used on non-extended class (IEEE 1800-2017 8.15)"); + m_ds.m_dotErr = true; + } else { + auto cextp = VN_CAST(classp->extendsp(), ClassExtends); + UASSERT_OBJ(cextp, nodep, "Bad super extends link"); + auto classp = cextp->classp(); + UASSERT_OBJ(classp, nodep, "Bad superclass"); + m_ds.m_dotSymp = m_statep->getNodeSym(classp); + UINFO(8, " super. " << m_ds.ascii() << endl); + } } } else if (VN_IS(nodep->lhsp(), ClassOrPackageRef)) { // m_ds.m_dotText communicates the cell prefix between stages @@ -2504,6 +2528,7 @@ private: virtual void visit(AstNodeFTaskRef* nodep) override { if (nodep->user3SetOnce()) return; UINFO(8, " " << nodep << endl); + UINFO(8, " " << m_ds.ascii() << endl); if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(), "Bad package link"); @@ -2558,12 +2583,15 @@ private: } else { string baddot; VSymEnt* okSymp = nullptr; - VSymEnt* dotSymp = m_curSymp; // Start search at module, as a variable + VSymEnt* dotSymp = nodep->dotted().empty() + ? m_ds.m_dotSymp // Non-'super.' dotted reference + : m_curSymp; // Start search at dotted point // of same name under a subtask isn't a relevant hit however a // function under a begin/end is. So we want begins, but not // the function if (nodep->classOrPackagep()) { // Look only in specified package dotSymp = m_statep->getNodeSym(nodep->classOrPackagep()); + UINFO(8, " Override classOrPackage " << dotSymp << endl); } else { if (nodep->inlinedDots() != "") { // Correct for current scope // Dotted lookup is always relative to module, as maybe diff --git a/test_regress/t/t_class_extends_this.out b/test_regress/t/t_class_extends_this.out deleted file mode 100644 index 87bd383a9..000000000 --- a/test_regress/t/t_class_extends_this.out +++ /dev/null @@ -1,25 +0,0 @@ -%Error-UNSUPPORTED: t/t_class_extends_this.v:22:11: Unsupported: super - 22 | if (super.value != 1) $stop; - | ^~~~~ -%Error: t/t_class_extends_this.v:22:11: Can't find definition of scope/variable: 'super' - 22 | if (super.value != 1) $stop; - | ^~~~~ -%Error-UNSUPPORTED: t/t_class_extends_this.v:23:7: Unsupported: super - 23 | super.test(); - | ^~~~~ -%Error: t/t_class_extends_this.v:23:7: Can't find definition of scope/variable: 'super' - 23 | super.test(); - | ^~~~~ -%Error-UNSUPPORTED: t/t_class_extends_this.v:24:7: Unsupported: super - 24 | super.value = 10; - | ^~~~~ -%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:26:11: Unsupported: super - 26 | if (super.value != 10) $stop; - | ^~~~~ -%Error: t/t_class_extends_this.v:26:11: Can't find definition of scope/variable: 'super' - 26 | if (super.value != 10) $stop; - | ^~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_class_extends_this.pl b/test_regress/t/t_class_extends_this.pl index 2ad4a887d..aabcde63e 100755 --- a/test_regress/t/t_class_extends_this.pl +++ b/test_regress/t/t_class_extends_this.pl @@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( - fails => $Self->{vlt_all}, - expect_filename => $Self->{golden_filename}, ); execute( check_finished => 1, - ) if !$Self->{vlt_all}; + ); ok(1); 1; diff --git a/test_regress/t/t_class_extends_this.v b/test_regress/t/t_class_extends_this.v index 4f72270e9..fb185267d 100644 --- a/test_regress/t/t_class_extends_this.v +++ b/test_regress/t/t_class_extends_this.v @@ -11,20 +11,27 @@ class Base; function void test; if (value != 1) $stop; if (this.value != 1) $stop; + value = 2; + if (value != 2) $stop; + this.value = 3; + if (value != 3) $stop; endfunction endclass class Cls extends Base; - int value = 2; + int value = 20; function void test; - if (value != 2) $stop; - if (this.value != 2) $stop; + if (value != 20) $stop; + if (this.value != 20) $stop; if (super.value != 1) $stop; + super.test(); - super.value = 10; - this.value = 20; - if (super.value != 10) $stop; - if (value != 20) $stop;; + if (this.value != 20) $stop; + + super.value = 9; + this.value = 29; + if (super.value != 9) $stop; + if (value != 29) $stop;; endfunction endclass diff --git a/test_regress/t/t_class_super_bad.out b/test_regress/t/t_class_super_bad.out new file mode 100644 index 000000000..9927708ff --- /dev/null +++ b/test_regress/t/t_class_super_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_class_super_bad.v:15:12: 'super' used outside class (IEEE 1800-2017 8.15) + 15 | super.addr = 2; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_class_super_bad.pl b/test_regress/t/t_class_super_bad.pl new file mode 100755 index 000000000..45af9e7a6 --- /dev/null +++ b/test_regress/t/t_class_super_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +compile( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_super_bad.v b/test_regress/t/t_class_super_bad.v new file mode 100644 index 000000000..20a229969 --- /dev/null +++ b/test_regress/t/t_class_super_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 + super.addr = 2; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_class_super_bad2.out b/test_regress/t/t_class_super_bad2.out new file mode 100644 index 000000000..b3b195c17 --- /dev/null +++ b/test_regress/t/t_class_super_bad2.out @@ -0,0 +1,4 @@ +%Error: t/t_class_super_bad2.v:10:12: 'super' used on non-extended class (IEEE 1800-2017 8.15) + 10 | super.i = 1; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_class_super_bad2.pl b/test_regress/t/t_class_super_bad2.pl new file mode 100755 index 000000000..45af9e7a6 --- /dev/null +++ b/test_regress/t/t_class_super_bad2.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +compile( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_super_bad2.v b/test_regress/t/t_class_super_bad2.v new file mode 100644 index 000000000..ba31d657b --- /dev/null +++ b/test_regress/t/t_class_super_bad2.v @@ -0,0 +1,12 @@ +// 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 Cls; + task t; + super.i = 1; // Bad - no extends + endtask +endclass diff --git a/test_regress/t/t_class_uses_this_bad.out b/test_regress/t/t_class_uses_this_bad.out index 05075f46a..0b2fd0a3c 100644 --- a/test_regress/t/t_class_uses_this_bad.out +++ b/test_regress/t/t_class_uses_this_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_class_uses_this_bad.v:15:12: 'this' used outside class +%Error: t/t_class_uses_this_bad.v:15:12: 'this' used outside class (IEEE 1800-2017 8.11) 15 | this.addr = 2; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_interface2.v b/test_regress/t/t_interface2.v index caa6c1591..799e7ec13 100644 --- a/test_regress/t/t_interface2.v +++ b/test_regress/t/t_interface2.v @@ -104,6 +104,10 @@ module counter_nansi(clkm, c_data, i_value); endmodule : counter_nansi `endif +// Test uses Verilator --top-module, which means this isn't in the hierarchy +// Other simulators will see it, and is illegal to have unconnected interface +`ifdef VERILATOR module modunused (ifunused ifinunused); ifunused ifunused(); endmodule +`endif From d56b923eaabc2397731041fcd9998f30ef3552d9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 26 Nov 2020 11:50:50 -0500 Subject: [PATCH 53/91] Fix 'randomize() with {}' crash --- src/V3LinkDot.cpp | 12 +++++++----- test_regress/t/t_with.v | 6 ++++++ test_regress/t/t_with_bbox.pl | 21 --------------------- 3 files changed, 13 insertions(+), 26 deletions(-) delete mode 100755 test_regress/t/t_with_bbox.pl diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 1c05ae13c..c2058735f 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1290,11 +1290,13 @@ class LinkDotFindVisitor final : public AstNVisitor { VL_DO_DANGLING(argp->unlinkFrBackWithNext()->deleteTree(), argp); } // Type depends on the method used, let V3Width figure it out later - auto* indexArgRefp = new AstLambdaArgRef(argFl, name + "__DOT__index", true); - auto* valueArgRefp = new AstLambdaArgRef(argFl, name, false); - auto* newp = new AstWith(nodep->fileline(), indexArgRefp, valueArgRefp, - nodep->exprp()->unlinkFrBackWithNext()); - funcrefp->addPinsp(newp); + const auto indexArgRefp = new AstLambdaArgRef(argFl, name + "__DOT__index", true); + const auto valueArgRefp = new AstLambdaArgRef(argFl, name, false); + if (nodep->exprp()) { // Else empty expression and pretend no "with" + const auto newp = new AstWith(nodep->fileline(), indexArgRefp, valueArgRefp, + nodep->exprp()->unlinkFrBackWithNext()); + funcrefp->addPinsp(newp); + } nodep->replaceWith(funcrefp->unlinkFrBack()); VL_DO_DANGLING(nodep->deleteTree(), nodep); } diff --git a/test_regress/t/t_with.v b/test_regress/t/t_with.v index 015cdc295..3a3da8ff2 100644 --- a/test_regress/t/t_with.v +++ b/test_regress/t/t_with.v @@ -26,6 +26,12 @@ module t (/*AUTOARG*/); found = aliases.find with (item == i); aliases.find with (item == i); +`ifdef VERILATOR + // No expression (e.g. x.randomize() with {}) + // Hack until randomize() supported + found = aliases.sort() with {}; +`endif + // Unique (array method) id = 4; found = aliases.find with (id); diff --git a/test_regress/t/t_with_bbox.pl b/test_regress/t/t_with_bbox.pl deleted file mode 100755 index cc3646920..000000000 --- a/test_regress/t/t_with_bbox.pl +++ /dev/null @@ -1,21 +0,0 @@ -#!/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(vlt => 1); - -top_filename("t/t_with_unsup.v"); - -lint( - verilator_flags => ["--bbox-unsup"], - fails => 1, - ); - -ok(1); -1; From 04febb194437e8b982e3c14c25d9d4298f11ec1d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 26 Nov 2020 15:03:55 -0500 Subject: [PATCH 54/91] Internals: Move V3Param code. No functional change. --- src/V3Param.cpp | 409 ++++++++++++++++++++++++------------------------ 1 file changed, 205 insertions(+), 204 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 91def7f9f..fbdf6bc67 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -65,6 +65,7 @@ //###################################################################### // Hierarchical block and parameter db (modules without parameter is also handled) + class ParameterizedHierBlocks final { typedef std::multimap HierBlockOptsByOrigName; typedef HierBlockOptsByOrigName::const_iterator HierMapIt; @@ -195,10 +196,9 @@ public: }; //###################################################################### -// Param state, as a visitor of each AstNode +// Process parameter visitor class ParamVisitor final : public AstNVisitor { -private: // NODE STATE // AstNodeModule::user5() // bool True if processed // AstGenFor::user5() // bool True if processed @@ -531,7 +531,209 @@ private: } return newmodp; } - void visitCellDeparam(AstCell* nodep, const string& hierName); + void visitCellDeparam(AstCell* nodep, const string& hierName) { + // Cell: Check for parameters in the instantiation. + iterateChildren(nodep); + UASSERT_OBJ(nodep->modp(), nodep, "Not linked?"); + // We always run this, even if no parameters, as need to look for interfaces, + // and remove any recursive references + { + UINFO(4, "De-parameterize: " << nodep << endl); + // Create new module name with _'s between the constants + if (debug() >= 10) nodep->dumpTree(cout, "-cell: "); + // Evaluate all module constants + V3Const::constifyParamsEdit(nodep); + AstNodeModule* srcModp = nodep->modp(); + srcModp->hierName(hierName + "." + nodep->name()); + + // Make sure constification worked + // Must be a separate loop, as constant conversion may have changed some pointers. + // if (debug()) nodep->dumpTree(cout, "-cel2: "); + string longname = srcModp->name(); + bool any_overrides = false; + // Must always clone __Vrcm (recursive modules) + if (nodep->recursive()) any_overrides = true; + longname += "_"; + if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (!pinp->exprp()) continue; // No-connect + if (AstVar* modvarp = pinp->modVarp()) { + if (!modvarp->isGParam()) { + pinp->v3error("Attempted parameter setting of non-parameter: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } else if (VN_IS(pinp->exprp(), InitArray) + && arraySubDTypep(modvarp->subDTypep())) { + // Array assigned to array + AstNode* exprp = pinp->exprp(); + longname + += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + any_overrides = true; + } else { + AstConst* exprp = VN_CAST(pinp->exprp(), Const); + AstConst* origp = VN_CAST(modvarp->valuep(), Const); + if (!exprp) { + // if (debug()) pinp->dumpTree(cout, "error:"); + pinp->v3error("Can't convert defparam value to constant: Param " + << pinp->prettyNameQ() << " of " + << nodep->prettyNameQ()); + pinp->exprp()->replaceWith(new AstConst( + pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0)); + } else if (origp && exprp->sameTree(origp)) { + // Setting parameter to its default value. Just ignore it. + // This prevents making additional modules, and makes coverage more + // obvious as it won't show up under a unique module page name. + } else if (exprp->num().isDouble() || exprp->num().isString() + || exprp->num().isFourState() || exprp->num().width() != 32) { + longname += ("_" + paramSmallName(srcModp, modvarp) + + paramValueNumber(exprp)); + any_overrides = true; + } else { + longname += ("_" + paramSmallName(srcModp, modvarp) + + exprp->num().ascii(false)); + any_overrides = true; + } + } + } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { + AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType); + AstNodeDType* origp = modvarp->subDTypep(); + if (!exprp) { + pinp->v3error("Parameter type pin value isn't a type: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } else if (!origp) { + pinp->v3error("Parameter type variable isn't a type: Param " + << modvarp->prettyNameQ()); + } else { + UINFO(9, "Parameter type assignment expr=" << exprp << " to " << origp + << endl); + if (exprp->sameTree(origp)) { + // Setting parameter to its default value. Just ignore it. + // This prevents making additional modules, and makes coverage more + // obvious as it won't show up under a unique module page name. + } else { + V3Const::constifyParamsEdit(exprp); + longname += "_" + paramSmallName(srcModp, modvarp) + + paramValueNumber(exprp); + any_overrides = true; + } + } + } else { + pinp->v3error("Parameter not found in sub-module: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } + } + IfaceRefRefs ifaceRefRefs; + for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + AstVar* modvarp = pinp->modVarp(); + if (modvarp->isIfaceRef()) { + AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType); + if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) { + portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType); + } + AstIfaceRefDType* pinIrefp = nullptr; + AstNode* exprp = pinp->exprp(); + AstVar* varp = (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp() + : nullptr; + if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) { + pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType); + } else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep()) + && VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType)) { + pinIrefp = VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType); + } else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef) + && VN_CAST(exprp->op1p(), VarRef)->varp() + && VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep() + && arraySubDTypep( + VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()) + && VN_CAST(arraySubDTypep( + VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), + IfaceRefDType)) { + pinIrefp = VN_CAST( + arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), + IfaceRefDType); + } + + UINFO(9, " portIfaceRef " << portIrefp << endl); + + if (!portIrefp) { + pinp->v3error("Interface port " << modvarp->prettyNameQ() + << " is not an interface " << modvarp); + } else if (!pinIrefp) { + pinp->v3error("Interface port " + << modvarp->prettyNameQ() + << " is not connected to interface/modport pin expression"); + } else { + UINFO(9, " pinIfaceRef " << pinIrefp << endl); + if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) { + UINFO(9, " IfaceRefDType needs reconnect " << pinIrefp << endl); + longname += ("_" + paramSmallName(srcModp, pinp->modVarp()) + + paramValueNumber(pinIrefp)); + any_overrides = true; + ifaceRefRefs.push_back(make_pair(portIrefp, pinIrefp)); + if (portIrefp->ifacep() != pinIrefp->ifacep() + // Might be different only due to param cloning, so check names too + && portIrefp->ifaceName() != pinIrefp->ifaceName()) { + pinp->v3error("Port " + << pinp->prettyNameQ() << " expects " + << AstNode::prettyNameQ(portIrefp->ifaceName()) + << " interface but pin connects " + << AstNode::prettyNameQ(pinIrefp->ifaceName()) + << " interface"); + } + } + } + } + } + + if (!any_overrides) { + UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); + } else if (AstNodeModule* modp + = m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) { + nodep->modp(modp); + nodep->modName(modp->name()); + modp->dead(false); + // We need to relink the pins to the new module + relinkPinsByName(nodep->pinsp(), modp); + } else { + // If the name is very long, we don't want to overwhelm the filename limit + // We don't do this always, as it aids debugability to have intuitive naming. + // TODO can use new V3Name hash replacement instead of this + // Shorter name is convenient for hierarchical block + string newname = moduleCalcName(srcModp, nodep, longname); + UINFO(4, + "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); + // + // Already made this flavor? + AstNodeModule* cellmodp = nullptr; + auto iter = m_modNameMap.find(newname); + if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp; + if (!cellmodp) { + cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs); + iter = m_modNameMap.find(newname); + UASSERT(iter != m_modNameMap.end(), "should find just-made module"); + } else { + UINFO(4, " De-parameterize to old: " << cellmodp << endl); + } + // Have child use this module instead. + nodep->modp(cellmodp); + nodep->modName(newname); + // We need to relink the pins to the new module + CloneMap* clonemapp = &(iter->second.m_cloneMap); + relinkPins(clonemapp, nodep->pinsp()); + UINFO(8, " Done with " << cellmodp << endl); + } // if any_overrides + + nodep->recursive(false); + + // Delete the parameters from the cell; they're not relevant any longer. + if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree(); + UINFO(8, " Done with " << nodep << endl); + // if (debug() >= 10) + // v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree")); + } + + // Now remember to process the child module at the end of the module + m_todoModps.insert(make_pair(nodep->modp()->level(), nodep->modp())); + } + void visitModules() { // Loop on all modules left to process // Hitting a cell adds to the appropriate level of this level-sorted list, @@ -877,207 +1079,6 @@ public: virtual ~ParamVisitor() override = default; }; -//---------------------------------------------------------------------- -// VISITs - -void ParamVisitor::visitCellDeparam(AstCell* nodep, const string& hierName) { - // Cell: Check for parameters in the instantiation. - iterateChildren(nodep); - UASSERT_OBJ(nodep->modp(), nodep, "Not linked?"); - // We always run this, even if no parameters, as need to look for interfaces, - // and remove any recursive references - { - UINFO(4, "De-parameterize: " << nodep << endl); - // Create new module name with _'s between the constants - if (debug() >= 10) nodep->dumpTree(cout, "-cell: "); - // Evaluate all module constants - V3Const::constifyParamsEdit(nodep); - AstNodeModule* srcModp = nodep->modp(); - srcModp->hierName(hierName + "." + nodep->name()); - - // Make sure constification worked - // Must be a separate loop, as constant conversion may have changed some pointers. - // if (debug()) nodep->dumpTree(cout, "-cel2: "); - string longname = srcModp->name(); - bool any_overrides = false; - // Must always clone __Vrcm (recursive modules) - if (nodep->recursive()) any_overrides = true; - longname += "_"; - if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); - for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - if (!pinp->exprp()) continue; // No-connect - if (AstVar* modvarp = pinp->modVarp()) { - if (!modvarp->isGParam()) { - pinp->v3error("Attempted parameter setting of non-parameter: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } else if (VN_IS(pinp->exprp(), InitArray) - && arraySubDTypep(modvarp->subDTypep())) { - // Array assigned to array - AstNode* exprp = pinp->exprp(); - longname += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); - any_overrides = true; - } else { - AstConst* exprp = VN_CAST(pinp->exprp(), Const); - AstConst* origp = VN_CAST(modvarp->valuep(), Const); - if (!exprp) { - // if (debug()) pinp->dumpTree(cout, "error:"); - pinp->v3error("Can't convert defparam value to constant: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - pinp->exprp()->replaceWith(new AstConst( - pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0)); - } else if (origp && exprp->sameTree(origp)) { - // Setting parameter to its default value. Just ignore it. - // This prevents making additional modules, and makes coverage more - // obvious as it won't show up under a unique module page name. - } else if (exprp->num().isDouble() || exprp->num().isString() - || exprp->num().isFourState() || exprp->num().width() != 32) { - longname - += ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp)); - any_overrides = true; - } else { - longname += ("_" + paramSmallName(srcModp, modvarp) - + exprp->num().ascii(false)); - any_overrides = true; - } - } - } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { - AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType); - AstNodeDType* origp = modvarp->subDTypep(); - if (!exprp) { - pinp->v3error("Parameter type pin value isn't a type: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } else if (!origp) { - pinp->v3error("Parameter type variable isn't a type: Param " - << modvarp->prettyNameQ()); - } else { - UINFO(9, - "Parameter type assignment expr=" << exprp << " to " << origp << endl); - if (exprp->sameTree(origp)) { - // Setting parameter to its default value. Just ignore it. - // This prevents making additional modules, and makes coverage more - // obvious as it won't show up under a unique module page name. - } else { - V3Const::constifyParamsEdit(exprp); - longname - += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); - any_overrides = true; - } - } - } else { - pinp->v3error("Parameter not found in sub-module: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } - } - IfaceRefRefs ifaceRefRefs; - for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - AstVar* modvarp = pinp->modVarp(); - if (modvarp->isIfaceRef()) { - AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType); - if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) { - portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType); - } - AstIfaceRefDType* pinIrefp = nullptr; - AstNode* exprp = pinp->exprp(); - AstVar* varp - = (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp() : nullptr; - if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) { - pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType); - } else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep()) - && VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType)) { - pinIrefp = VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType); - } else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef) - && VN_CAST(exprp->op1p(), VarRef)->varp() - && VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep() - && arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()) - && VN_CAST( - arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), - IfaceRefDType)) { - pinIrefp = VN_CAST( - arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), - IfaceRefDType); - } - - UINFO(9, " portIfaceRef " << portIrefp << endl); - - if (!portIrefp) { - pinp->v3error("Interface port " << modvarp->prettyNameQ() - << " is not an interface " << modvarp); - } else if (!pinIrefp) { - pinp->v3error("Interface port " - << modvarp->prettyNameQ() - << " is not connected to interface/modport pin expression"); - } else { - UINFO(9, " pinIfaceRef " << pinIrefp << endl); - if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) { - UINFO(9, " IfaceRefDType needs reconnect " << pinIrefp << endl); - longname += ("_" + paramSmallName(srcModp, pinp->modVarp()) - + paramValueNumber(pinIrefp)); - any_overrides = true; - ifaceRefRefs.push_back(make_pair(portIrefp, pinIrefp)); - if (portIrefp->ifacep() != pinIrefp->ifacep() - // Might be different only due to param cloning, so check names too - && portIrefp->ifaceName() != pinIrefp->ifaceName()) { - pinp->v3error("Port " << pinp->prettyNameQ() << " expects " - << AstNode::prettyNameQ(portIrefp->ifaceName()) - << " interface but pin connects " - << AstNode::prettyNameQ(pinIrefp->ifaceName()) - << " interface"); - } - } - } - } - } - - if (!any_overrides) { - UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); - } else if (AstNodeModule* modp - = m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) { - nodep->modp(modp); - nodep->modName(modp->name()); - modp->dead(false); - // We need to relink the pins to the new module - relinkPinsByName(nodep->pinsp(), modp); - } else { - // If the name is very long, we don't want to overwhelm the filename limit - // We don't do this always, as it aids debugability to have intuitive naming. - // TODO can use new V3Name hash replacement instead of this - // Shorter name is convenient for hierarchical block - string newname = moduleCalcName(srcModp, nodep, longname); - UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); - // - // Already made this flavor? - AstNodeModule* cellmodp = nullptr; - auto iter = m_modNameMap.find(newname); - if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp; - if (!cellmodp) { - cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs); - iter = m_modNameMap.find(newname); - UASSERT(iter != m_modNameMap.end(), "should find just-made module"); - } else { - UINFO(4, " De-parameterize to old: " << cellmodp << endl); - } - // Have child use this module instead. - nodep->modp(cellmodp); - nodep->modName(newname); - // We need to relink the pins to the new module - CloneMap* clonemapp = &(iter->second.m_cloneMap); - relinkPins(clonemapp, nodep->pinsp()); - UINFO(8, " Done with " << cellmodp << endl); - } // if any_overrides - - nodep->recursive(false); - - // Delete the parameters from the cell; they're not relevant any longer. - if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree(); - UINFO(8, " Done with " << nodep << endl); - // if (debug() >= 10) - // v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree")); - } - - // Now remember to process the child module at the end of the module - m_todoModps.insert(make_pair(nodep->modp()->level(), nodep->modp())); -} - //###################################################################### // Param class functions From 84d7380588573305e816582c9a99725fc0cf0794 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 08:50:29 -0500 Subject: [PATCH 55/91] Internals: Param immediate delete, in prep for next commit. No functional change intended. --- src/V3Param.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index fbdf6bc67..13cb5caff 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -519,9 +519,7 @@ class ParamVisitor final : public AstNVisitor { } else if (AstParamTypeDType* modptp = pinp->modPTypep()) { AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); UASSERT_OBJ(dtypep, pinp, "unlinked param dtype"); - if (modptp->childDTypep()) { - pushDeletep(modptp->childDTypep()->unlinkFrBack()); - } + if (modptp->childDTypep()) modptp->childDTypep()->unlinkFrBack()->deleteTree(); // Set this parameter to value requested by cell modptp->childDTypep(dtypep->cloneTree(false)); // Later V3LinkDot will convert the ParamDType to a Typedef From d89fc05da1e69e0981b535542b49af1c62cb28f2 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 09:04:56 -0500 Subject: [PATCH 56/91] Internals: Refactor V3Param through code movement only. No functional change intended. --- src/V3Param.cpp | 459 +++++++++++++++++++++++++----------------------- 1 file changed, 237 insertions(+), 222 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 13cb5caff..c3abcb43e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -196,16 +196,17 @@ public: }; //###################################################################### -// Process parameter visitor +// Remove parameters from cells and build new modules -class ParamVisitor final : public AstNVisitor { - // NODE STATE - // AstNodeModule::user5() // bool True if processed - // AstGenFor::user5() // bool True if processed - // AstVar::user5() // bool True if constant propagated +class ParamProcessor final { + // NODE STATE - Local // AstVar::user4() // int Global parameter number (for naming new module) // // (0=not processed, 1=iterated, but no number, // // 65+ parameter numbered) + // NODE STATE - Shared with ParamVisitor + // AstNodeModule::user5() // bool True if processed + // AstGenFor::user5() // bool True if processed + // AstVar::user5() // bool True if constant propagated // AstCell::user5p() // string* Generate portion of hierarchical name AstUser4InUse m_inuser4; AstUser5InUse m_inuser5; @@ -239,16 +240,7 @@ class ParamVisitor final : public AstNVisitor { ValueMap m_valueMap; // Hash of node hash to (param value, name) int m_nextValue = 1; // Next value to use in m_valueMap - typedef std::multimap LevelModMap; - LevelModMap m_todoModps; // Modules left to process - - typedef std::deque CellList; - CellList m_cellps; // Cells left to process (in this module) - AstNodeModule* m_modp = nullptr; // Current module being processed - string m_unlinkedTxt; // Text for AstUnlinkedRef - UnrollStateful m_unroller; // Loop unroller - string m_generateHierName; // Generate portion of hierarchy name // Database to get protect-lib wrapper that matches parameters in hierarchical Verilation ParameterizedHierBlocks m_hierBlocks; @@ -529,209 +521,239 @@ class ParamVisitor final : public AstNVisitor { } return newmodp; } + +public: + void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& hierName) { + m_modp = modp; + // Cell: Check for parameters in the instantiation. + // We always run this, even if no parameters, as need to look for interfaces, + // and remove any recursive references + UINFO(4, "De-parameterize: " << nodep << endl); + // Create new module name with _'s between the constants + if (debug() >= 10) nodep->dumpTree(cout, "-cell: "); + // Evaluate all module constants + V3Const::constifyParamsEdit(nodep); + AstNodeModule* srcModp = nodep->modp(); + srcModp->hierName(hierName + "." + nodep->name()); + + // Make sure constification worked + // Must be a separate loop, as constant conversion may have changed some pointers. + // if (debug()) nodep->dumpTree(cout, "-cel2: "); + string longname = srcModp->name(); + bool any_overrides = false; + // Must always clone __Vrcm (recursive modules) + if (nodep->recursive()) any_overrides = true; + longname += "_"; + if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (!pinp->exprp()) continue; // No-connect + if (AstVar* modvarp = pinp->modVarp()) { + if (!modvarp->isGParam()) { + pinp->v3error("Attempted parameter setting of non-parameter: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } else if (VN_IS(pinp->exprp(), InitArray) + && arraySubDTypep(modvarp->subDTypep())) { + // Array assigned to array + AstNode* exprp = pinp->exprp(); + longname += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + any_overrides = true; + } else { + AstConst* exprp = VN_CAST(pinp->exprp(), Const); + AstConst* origp = VN_CAST(modvarp->valuep(), Const); + if (!exprp) { + // if (debug()) pinp->dumpTree(cout, "error:"); + pinp->v3error("Can't convert defparam value to constant: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + pinp->exprp()->replaceWith(new AstConst( + pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0)); + } else if (origp && exprp->sameTree(origp)) { + // Setting parameter to its default value. Just ignore it. + // This prevents making additional modules, and makes coverage more + // obvious as it won't show up under a unique module page name. + } else if (exprp->num().isDouble() || exprp->num().isString() + || exprp->num().isFourState() || exprp->num().width() != 32) { + longname + += ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp)); + any_overrides = true; + } else { + longname += ("_" + paramSmallName(srcModp, modvarp) + + exprp->num().ascii(false)); + any_overrides = true; + } + } + } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { + AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType); + AstNodeDType* origp = modvarp->subDTypep(); + if (!exprp) { + pinp->v3error("Parameter type pin value isn't a type: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } else if (!origp) { + pinp->v3error("Parameter type variable isn't a type: Param " + << modvarp->prettyNameQ()); + } else { + UINFO(9, + "Parameter type assignment expr=" << exprp << " to " << origp << endl); + if (exprp->sameTree(origp)) { + // Setting parameter to its default value. Just ignore it. + // This prevents making additional modules, and makes coverage more + // obvious as it won't show up under a unique module page name. + } else { + V3Const::constifyParamsEdit(exprp); + longname + += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + any_overrides = true; + } + } + } else { + pinp->v3error("Parameter not found in sub-module: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } + } + IfaceRefRefs ifaceRefRefs; + for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + AstVar* modvarp = pinp->modVarp(); + if (modvarp->isIfaceRef()) { + AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType); + if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) { + portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType); + } + AstIfaceRefDType* pinIrefp = nullptr; + AstNode* exprp = pinp->exprp(); + AstVar* varp + = (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp() : nullptr; + if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) { + pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType); + } else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep()) + && VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType)) { + pinIrefp = VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType); + } else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef) + && VN_CAST(exprp->op1p(), VarRef)->varp() + && VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep() + && arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()) + && VN_CAST( + arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), + IfaceRefDType)) { + pinIrefp = VN_CAST( + arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), + IfaceRefDType); + } + + UINFO(9, " portIfaceRef " << portIrefp << endl); + + if (!portIrefp) { + pinp->v3error("Interface port " << modvarp->prettyNameQ() + << " is not an interface " << modvarp); + } else if (!pinIrefp) { + pinp->v3error("Interface port " + << modvarp->prettyNameQ() + << " is not connected to interface/modport pin expression"); + } else { + UINFO(9, " pinIfaceRef " << pinIrefp << endl); + if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) { + UINFO(9, " IfaceRefDType needs reconnect " << pinIrefp << endl); + longname += ("_" + paramSmallName(srcModp, pinp->modVarp()) + + paramValueNumber(pinIrefp)); + any_overrides = true; + ifaceRefRefs.push_back(make_pair(portIrefp, pinIrefp)); + if (portIrefp->ifacep() != pinIrefp->ifacep() + // Might be different only due to param cloning, so check names too + && portIrefp->ifaceName() != pinIrefp->ifaceName()) { + pinp->v3error("Port " << pinp->prettyNameQ() << " expects " + << AstNode::prettyNameQ(portIrefp->ifaceName()) + << " interface but pin connects " + << AstNode::prettyNameQ(pinIrefp->ifaceName()) + << " interface"); + } + } + } + } + } + + if (!any_overrides) { + UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); + } else if (AstNodeModule* modp + = m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) { + nodep->modp(modp); + nodep->modName(modp->name()); + modp->dead(false); + // We need to relink the pins to the new module + relinkPinsByName(nodep->pinsp(), modp); + } else { + // If the name is very long, we don't want to overwhelm the filename limit + // We don't do this always, as it aids debugability to have intuitive naming. + // TODO can use new V3Name hash replacement instead of this + // Shorter name is convenient for hierarchical block + string newname = moduleCalcName(srcModp, nodep, longname); + UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); + // + // Already made this flavor? + AstNodeModule* cellmodp = nullptr; + auto iter = m_modNameMap.find(newname); + if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp; + if (!cellmodp) { + cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs); + iter = m_modNameMap.find(newname); + UASSERT(iter != m_modNameMap.end(), "should find just-made module"); + } else { + UINFO(4, " De-parameterize to old: " << cellmodp << endl); + } + // Have child use this module instead. + nodep->modp(cellmodp); + nodep->modName(newname); + // We need to relink the pins to the new module + CloneMap* clonemapp = &(iter->second.m_cloneMap); + relinkPins(clonemapp, nodep->pinsp()); + UINFO(8, " Done with " << cellmodp << endl); + } // if any_overrides + + nodep->recursive(false); + + // Delete the parameters from the cell; they're not relevant any longer. + if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree(); + UINFO(8, " Done with " << nodep << endl); + // if (debug() >= 10) + // v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree")); + } + + // CONSTRUCTORS + ParamProcessor(AstNetlist* nodep) + : m_hierBlocks{v3Global.opt.hierBlocks(), nodep} { + for (AstNodeModule* modp = nodep->modulesp(); modp; + modp = VN_CAST(modp->nextp(), NodeModule)) { + m_allModuleNames.insert(modp->name()); + } + } + ~ParamProcessor() = default; + VL_UNCOPYABLE(ParamProcessor); +}; + +//###################################################################### +// Process parameter visitor + +class ParamVisitor final : public AstNVisitor { + // STATE + ParamProcessor m_processor; // De-parameterize a cell, build modules + UnrollStateful m_unroller; // Loop unroller + + AstNodeModule* m_modp = nullptr; // Current module being processed + string m_generateHierName; // Generate portion of hierarchy name + string m_unlinkedTxt; // Text for AstUnlinkedRef + std::deque m_cellps; // Cells left to process (in this module) + + typedef std::multimap LevelModMap; + LevelModMap m_todoModps; // Modules left to process + + // METHODS + VL_DEBUG_FUNC; // Declare debug() + void visitCellDeparam(AstCell* nodep, const string& hierName) { // Cell: Check for parameters in the instantiation. iterateChildren(nodep); UASSERT_OBJ(nodep->modp(), nodep, "Not linked?"); - // We always run this, even if no parameters, as need to look for interfaces, - // and remove any recursive references - { - UINFO(4, "De-parameterize: " << nodep << endl); - // Create new module name with _'s between the constants - if (debug() >= 10) nodep->dumpTree(cout, "-cell: "); - // Evaluate all module constants - V3Const::constifyParamsEdit(nodep); - AstNodeModule* srcModp = nodep->modp(); - srcModp->hierName(hierName + "." + nodep->name()); - - // Make sure constification worked - // Must be a separate loop, as constant conversion may have changed some pointers. - // if (debug()) nodep->dumpTree(cout, "-cel2: "); - string longname = srcModp->name(); - bool any_overrides = false; - // Must always clone __Vrcm (recursive modules) - if (nodep->recursive()) any_overrides = true; - longname += "_"; - if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); - for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - if (!pinp->exprp()) continue; // No-connect - if (AstVar* modvarp = pinp->modVarp()) { - if (!modvarp->isGParam()) { - pinp->v3error("Attempted parameter setting of non-parameter: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } else if (VN_IS(pinp->exprp(), InitArray) - && arraySubDTypep(modvarp->subDTypep())) { - // Array assigned to array - AstNode* exprp = pinp->exprp(); - longname - += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); - any_overrides = true; - } else { - AstConst* exprp = VN_CAST(pinp->exprp(), Const); - AstConst* origp = VN_CAST(modvarp->valuep(), Const); - if (!exprp) { - // if (debug()) pinp->dumpTree(cout, "error:"); - pinp->v3error("Can't convert defparam value to constant: Param " - << pinp->prettyNameQ() << " of " - << nodep->prettyNameQ()); - pinp->exprp()->replaceWith(new AstConst( - pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0)); - } else if (origp && exprp->sameTree(origp)) { - // Setting parameter to its default value. Just ignore it. - // This prevents making additional modules, and makes coverage more - // obvious as it won't show up under a unique module page name. - } else if (exprp->num().isDouble() || exprp->num().isString() - || exprp->num().isFourState() || exprp->num().width() != 32) { - longname += ("_" + paramSmallName(srcModp, modvarp) - + paramValueNumber(exprp)); - any_overrides = true; - } else { - longname += ("_" + paramSmallName(srcModp, modvarp) - + exprp->num().ascii(false)); - any_overrides = true; - } - } - } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { - AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType); - AstNodeDType* origp = modvarp->subDTypep(); - if (!exprp) { - pinp->v3error("Parameter type pin value isn't a type: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } else if (!origp) { - pinp->v3error("Parameter type variable isn't a type: Param " - << modvarp->prettyNameQ()); - } else { - UINFO(9, "Parameter type assignment expr=" << exprp << " to " << origp - << endl); - if (exprp->sameTree(origp)) { - // Setting parameter to its default value. Just ignore it. - // This prevents making additional modules, and makes coverage more - // obvious as it won't show up under a unique module page name. - } else { - V3Const::constifyParamsEdit(exprp); - longname += "_" + paramSmallName(srcModp, modvarp) - + paramValueNumber(exprp); - any_overrides = true; - } - } - } else { - pinp->v3error("Parameter not found in sub-module: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } - } - IfaceRefRefs ifaceRefRefs; - for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - AstVar* modvarp = pinp->modVarp(); - if (modvarp->isIfaceRef()) { - AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType); - if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) { - portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType); - } - AstIfaceRefDType* pinIrefp = nullptr; - AstNode* exprp = pinp->exprp(); - AstVar* varp = (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp() - : nullptr; - if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) { - pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType); - } else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep()) - && VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType)) { - pinIrefp = VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType); - } else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef) - && VN_CAST(exprp->op1p(), VarRef)->varp() - && VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep() - && arraySubDTypep( - VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()) - && VN_CAST(arraySubDTypep( - VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), - IfaceRefDType)) { - pinIrefp = VN_CAST( - arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()), - IfaceRefDType); - } - - UINFO(9, " portIfaceRef " << portIrefp << endl); - - if (!portIrefp) { - pinp->v3error("Interface port " << modvarp->prettyNameQ() - << " is not an interface " << modvarp); - } else if (!pinIrefp) { - pinp->v3error("Interface port " - << modvarp->prettyNameQ() - << " is not connected to interface/modport pin expression"); - } else { - UINFO(9, " pinIfaceRef " << pinIrefp << endl); - if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) { - UINFO(9, " IfaceRefDType needs reconnect " << pinIrefp << endl); - longname += ("_" + paramSmallName(srcModp, pinp->modVarp()) - + paramValueNumber(pinIrefp)); - any_overrides = true; - ifaceRefRefs.push_back(make_pair(portIrefp, pinIrefp)); - if (portIrefp->ifacep() != pinIrefp->ifacep() - // Might be different only due to param cloning, so check names too - && portIrefp->ifaceName() != pinIrefp->ifaceName()) { - pinp->v3error("Port " - << pinp->prettyNameQ() << " expects " - << AstNode::prettyNameQ(portIrefp->ifaceName()) - << " interface but pin connects " - << AstNode::prettyNameQ(pinIrefp->ifaceName()) - << " interface"); - } - } - } - } - } - - if (!any_overrides) { - UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); - } else if (AstNodeModule* modp - = m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) { - nodep->modp(modp); - nodep->modName(modp->name()); - modp->dead(false); - // We need to relink the pins to the new module - relinkPinsByName(nodep->pinsp(), modp); - } else { - // If the name is very long, we don't want to overwhelm the filename limit - // We don't do this always, as it aids debugability to have intuitive naming. - // TODO can use new V3Name hash replacement instead of this - // Shorter name is convenient for hierarchical block - string newname = moduleCalcName(srcModp, nodep, longname); - UINFO(4, - "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); - // - // Already made this flavor? - AstNodeModule* cellmodp = nullptr; - auto iter = m_modNameMap.find(newname); - if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp; - if (!cellmodp) { - cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs); - iter = m_modNameMap.find(newname); - UASSERT(iter != m_modNameMap.end(), "should find just-made module"); - } else { - UINFO(4, " De-parameterize to old: " << cellmodp << endl); - } - // Have child use this module instead. - nodep->modp(cellmodp); - nodep->modName(newname); - // We need to relink the pins to the new module - CloneMap* clonemapp = &(iter->second.m_cloneMap); - relinkPins(clonemapp, nodep->pinsp()); - UINFO(8, " Done with " << cellmodp << endl); - } // if any_overrides - - nodep->recursive(false); - - // Delete the parameters from the cell; they're not relevant any longer. - if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree(); - UINFO(8, " Done with " << nodep << endl); - // if (debug() >= 10) - // v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree")); - } - - // Now remember to process the child module at the end of the module + m_processor.cellDeparam(nodep, m_modp, hierName); + // Remember to process the child module at the end of the module m_todoModps.insert(make_pair(nodep->modp()->level(), nodep->modp())); } - void visitModules() { // Loop on all modules left to process // Hitting a cell adds to the appropriate level of this level-sorted list, @@ -774,10 +796,6 @@ class ParamVisitor final : public AstNVisitor { } // VISITORS - virtual void visit(AstNetlist* nodep) override { - // Modules must be done in top-down-order - iterateChildren(nodep); - } virtual void visit(AstNodeModule* nodep) override { if (nodep->dead()) { UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot @@ -1066,15 +1084,12 @@ class ParamVisitor final : public AstNVisitor { public: // CONSTRUCTORS explicit ParamVisitor(AstNetlist* nodep) - : m_hierBlocks{v3Global.opt.hierBlocks(), nodep} { - for (AstNodeModule* modp = nodep->modulesp(); modp; - modp = VN_CAST(modp->nextp(), NodeModule)) { - m_allModuleNames.insert(modp->name()); - } - // + : m_processor{nodep} { + // Relies on modules already being in top-down-order iterate(nodep); } virtual ~ParamVisitor() override = default; + VL_UNCOPYABLE(ParamVisitor); }; //###################################################################### From 4643d6e883f0b744eac7796d2e4362c087644d4d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 09:17:44 -0500 Subject: [PATCH 57/91] Internals: Refactor V3Param through code movement only. No functional change intended. --- src/V3Param.cpp | 82 ++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index c3abcb43e..36f091e8e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -522,29 +522,8 @@ class ParamProcessor final { return newmodp; } -public: - void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& hierName) { - m_modp = modp; - // Cell: Check for parameters in the instantiation. - // We always run this, even if no parameters, as need to look for interfaces, - // and remove any recursive references - UINFO(4, "De-parameterize: " << nodep << endl); - // Create new module name with _'s between the constants - if (debug() >= 10) nodep->dumpTree(cout, "-cell: "); - // Evaluate all module constants - V3Const::constifyParamsEdit(nodep); + void cellPinCleanup(AstCell* nodep, string& longnamer, bool& any_overridesr) { AstNodeModule* srcModp = nodep->modp(); - srcModp->hierName(hierName + "." + nodep->name()); - - // Make sure constification worked - // Must be a separate loop, as constant conversion may have changed some pointers. - // if (debug()) nodep->dumpTree(cout, "-cel2: "); - string longname = srcModp->name(); - bool any_overrides = false; - // Must always clone __Vrcm (recursive modules) - if (nodep->recursive()) any_overrides = true; - longname += "_"; - if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (!pinp->exprp()) continue; // No-connect if (AstVar* modvarp = pinp->modVarp()) { @@ -555,8 +534,8 @@ public: && arraySubDTypep(modvarp->subDTypep())) { // Array assigned to array AstNode* exprp = pinp->exprp(); - longname += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); - any_overrides = true; + longnamer += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + any_overridesr = true; } else { AstConst* exprp = VN_CAST(pinp->exprp(), Const); AstConst* origp = VN_CAST(modvarp->valuep(), Const); @@ -572,13 +551,13 @@ public: // obvious as it won't show up under a unique module page name. } else if (exprp->num().isDouble() || exprp->num().isString() || exprp->num().isFourState() || exprp->num().width() != 32) { - longname + longnamer += ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp)); - any_overrides = true; + any_overridesr = true; } else { - longname += ("_" + paramSmallName(srcModp, modvarp) - + exprp->num().ascii(false)); - any_overrides = true; + longnamer += ("_" + paramSmallName(srcModp, modvarp) + + exprp->num().ascii(false)); + any_overridesr = true; } } } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { @@ -599,9 +578,9 @@ public: // obvious as it won't show up under a unique module page name. } else { V3Const::constifyParamsEdit(exprp); - longname + longnamer += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); - any_overrides = true; + any_overridesr = true; } } } else { @@ -609,7 +588,11 @@ public: << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); } } - IfaceRefRefs ifaceRefRefs; + } + + void cellInterfaceCleanup(AstCell* nodep, string& longnamer, bool& any_overridesr, + IfaceRefRefs& ifaceRefRefs) { + AstNodeModule* srcModp = nodep->modp(); for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { AstVar* modvarp = pinp->modVarp(); if (modvarp->isIfaceRef()) { @@ -651,9 +634,9 @@ public: UINFO(9, " pinIfaceRef " << pinIrefp << endl); if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) { UINFO(9, " IfaceRefDType needs reconnect " << pinIrefp << endl); - longname += ("_" + paramSmallName(srcModp, pinp->modVarp()) - + paramValueNumber(pinIrefp)); - any_overrides = true; + longnamer += ("_" + paramSmallName(srcModp, pinp->modVarp()) + + paramValueNumber(pinIrefp)); + any_overridesr = true; ifaceRefRefs.push_back(make_pair(portIrefp, pinIrefp)); if (portIrefp->ifacep() != pinIrefp->ifacep() // Might be different only due to param cloning, so check names too @@ -668,6 +651,35 @@ public: } } } + } + +public: + void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& hierName) { + m_modp = modp; + // Cell: Check for parameters in the instantiation. + // We always run this, even if no parameters, as need to look for interfaces, + // and remove any recursive references + UINFO(4, "De-parameterize: " << nodep << endl); + // Create new module name with _'s between the constants + if (debug() >= 10) nodep->dumpTree(cout, "-cell: "); + // Evaluate all module constants + V3Const::constifyParamsEdit(nodep); + AstNodeModule* srcModp = nodep->modp(); + srcModp->hierName(hierName + "." + nodep->name()); + + // Make sure constification worked + // Must be a separate loop, as constant conversion may have changed some pointers. + // if (debug()) nodep->dumpTree(cout, "-cel2: "); + string longname = srcModp->name(); + bool any_overrides = false; + // Must always clone __Vrcm (recursive modules) + if (nodep->recursive()) any_overrides = true; + longname += "_"; + if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); + + cellPinCleanup(nodep, longname /*ref*/, any_overrides /*ref*/); + IfaceRefRefs ifaceRefRefs; + cellInterfaceCleanup(nodep, longname /*ref*/, any_overrides /*ref*/, ifaceRefRefs /*ref*/); if (!any_overrides) { UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); From 963fd0664d48b26f20a7478f90fa9591565999c6 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 09:42:51 -0500 Subject: [PATCH 58/91] Fix class-in-module issues --- src/V3Class.cpp | 3 ++- src/V3Param.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/V3Class.cpp b/src/V3Class.cpp index bd4e7a612..529a7e15b 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -87,7 +87,8 @@ private: iterateChildren(nodep); } } - virtual void visit(AstPackage* nodep) override { + virtual void visit(AstNodeModule* nodep) override { + // Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule) VL_RESTORER(m_prefix); { m_prefix = nodep->name() + "__03a__03a"; // :: diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 36f091e8e..3bd40c096 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -803,6 +803,7 @@ class ParamVisitor final : public AstNVisitor { } m_cellps.clear(); m_modp = nullptr; + UINFO(4, " MOD-done\n"); } } } @@ -815,6 +816,8 @@ class ParamVisitor final : public AstNVisitor { // Fake, made for recursive elimination UINFO(4, " MOD-recursive-dead. " << nodep << endl); nodep->dead(true); // So Dead checks won't count references to it + } else if (m_modp) { + UINFO(4, " MOD-under-MOD. " << nodep << endl); } else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top || VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet // Add request to END of modules left to process From cc307626c0e8ad57db9e995324c76dab2dd1b25c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 10:34:31 -0500 Subject: [PATCH 59/91] Tests: Add class name test. --- test_regress/t/t_class_name.v | 166 ++++++++++++++++++++++++++++++---- 1 file changed, 147 insertions(+), 19 deletions(-) diff --git a/test_regress/t/t_class_name.v b/test_regress/t/t_class_name.v index 8aa884a73..0be89d598 100644 --- a/test_regress/t/t_class_name.v +++ b/test_regress/t/t_class_name.v @@ -4,30 +4,158 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -task unit_name; - $write("unit_name = '%m'\n"); -endtask +`ifdef verilator + `define stop $stop +`else + `define stop +`endif +`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); + +function string unit_name; + return $sformatf("u %m"); +endfunction class Cls; - static task static_name; - $write("static_name = '%m'\n"); - endtask - task nonstatic_name; - $write("nonstatic_name = '%m'\n"); - endtask -endclass : Cls + // We use the same name for all static_name's to check we resolve right + static function string static_name; + return $sformatf("c %m"); + endfunction + // Different for non_statis to make sure likewise + function string c_auto_name; + return $sformatf("c %m"); + endfunction +endclass -module t (/*AUTOARG*/); - initial begin +package P; +class Cls; + static function string static_name; + return $sformatf("p %m"); + endfunction + function string p_auto_name; + return $sformatf("p %m"); + endfunction +endclass +endpackage + +module M; +class Cls; + static function string static_name; + return $sformatf("m %m"); + endfunction + function string m_auto_name; + return $sformatf("m %m"); + endfunction +endclass + S sub(); + function string cls_static_name; + return Cls::static_name(); + endfunction + function string cls_auto_name; Cls c; c = new; - $write("t = '%m'\n"); - unit_name(); - $write("Below results vary with simulator.\n"); - // E.g. '$unit.\Cls::static_name ' - // E.g. '$unit_x.Cls.static_name' - c.static_name(); - c.nonstatic_name(); + return c.m_auto_name(); + endfunction +endmodule + +module S; +class Cls; + static function string static_name; + return $sformatf("ms %m"); + endfunction + function string ms_auto_name; + return $sformatf("ms %m"); + endfunction +endclass + function string cls_static_name; + return Cls::static_name(); + endfunction + function string cls_auto_name; + Cls c; + c = new; + return c.ms_auto_name(); + endfunction +endmodule + +module t (/*AUTOARG*/); + string s; + + M m(); + + function string mod_func_name; + return $sformatf("tmf %m"); + endfunction + + initial begin + Cls c; + P::Cls p; + p = new; + c = new; + + s = mod_func_name(); + `checks(s, "tmf top.t"); + // UNSUP `checks(s, "tmf top.t.mod_func_name"); + + s = unit_name(); + `checks(s, "u top.$unit"); + // UNSUP `checks(s, "u top.$unit.unit_name"); + // Others: "u $unit_????::unit_name + // Others: "u $unit::unit_name + // Others: "u \\package UnitScopePackage_1\ .UnitScopePackage_1.unit_name + + // *** Below results vary with simulator. + + s = Cls::static_name(); + `checks(s, "c top.$unit.Cls"); + // UNSUP `checks(s, "c top.$unit.Cls.static_name"); + // Others: "c $unit_????.Cls.static_name + // Others: "c $unit::\Cls::static_name + // Others: "c Cls.static_name + s = c.c_auto_name(); + `checks(s, "c top.$unit.Cls"); + // UNSUP `checks(s, "c top.$unit.Cls.c_auto_name"); + // Others: "c $unit_????.Cls.c_auto_name + // Others: "c $unit::\Cls::c_auto_name + // Others: "c Cls.c_auto_name + + //UNSUP s = P::Cls::static_name(); + //UNSUP `checks(s, "p top.P.Cls"); + // UNSUP `checks(s, "p top.P.Cls.static_name"); + // Others: "p P.Cls.static_name + // Others: "p P::Cls.static_name + // Others: "p P::\Cls::static_name + // Others: "p \\package P\ .Cls.static_name + + s = p.p_auto_name(); + `checks(s, "p top.P.Cls"); + // UNSUP `checks(s, "p top.P.Cls.p_auto_name"); + // Others: "p P.Cls.p_auto_name + // Others: "p P::Cls.p_auto_name + // Others: "p P::\Cls::p_auto_name + // Others: "p \\package P\ .Cls.p_auto_name + + s = m.cls_static_name(); + `checks(s, "m top.t.m.Cls"); + // UNSUP `checks(s, "m top.t.m.Cls.static_name"); + // Others: "m top.t.m.Cls.static_name + // Others: "m top.t.m.\Cls::static_name + + s = m.cls_auto_name(); + `checks(s, "m top.t.m.Cls"); + // UNSUP `checks(s, "m top.t.m.Cls.m_auto_name"); + // Others: "m top.t.m.Cls.m_auto_name + // Others: "m top.t.m.\Cls::m_auto_name + + s = m.sub.cls_static_name(); + `checks(s, "ms top.t.m.sub.Cls"); + // UNSUP `checks(s, "ms top.t.m.sub.Cls.static_name"); + // Others: "ms top.t.m.sub.Cls.static_name + // Others: "ms top.t.m.sub.\Cls::static_name + s = m.sub.cls_auto_name(); + `checks(s, "ms top.t.m.sub.Cls"); + // UNSUP `checks(s, "ms top.t.m.sub.Cls.ms_auto_name"); + // Others: "ms top.t.m.sub.Cls.ms_auto_name + // Others: "ms top.t.m.sub.\Cls::ms_auto_name + $write("*-* All Finished *-*\n"); $finish; end From 123d1af29de0e4b6c97ff670e16538908086f619 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 14:58:50 -0500 Subject: [PATCH 60/91] Fix crash on non-class static function --- src/V3Class.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/V3Class.cpp b/src/V3Class.cpp index 529a7e15b..83f99724a 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -100,7 +100,7 @@ private: iterateChildren(nodep); // Don't move now, or wouldn't keep interating the class // TODO move class statics too - if (m_ftaskp && m_ftaskp->lifetime().isStatic()) { + if (m_packageScopep && m_ftaskp && m_ftaskp->lifetime().isStatic()) { m_moves.push_back(make_pair(nodep, m_packageScopep)); } } @@ -115,7 +115,7 @@ private: { m_ftaskp = nodep; iterateChildren(nodep); - if (nodep->lifetime().isStatic()) { + if (m_packageScopep && nodep->lifetime().isStatic()) { m_moves.push_back(make_pair(nodep, m_packageScopep)); } } From ed268805ceaa4bf6cc6c64c5f5bb9d467d3bf317 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 19:53:04 -0500 Subject: [PATCH 61/91] Lint check for pure virtual in non-virtual class. --- src/V3WidthCommit.h | 9 +++++++++ test_regress/t/t_class_virtual_pure.out | 7 ------- test_regress/t/t_class_virtual_pure_bad.out | 4 ++++ test_regress/t/t_class_virtual_pure_bad.pl | 19 +++++++++++++++++++ test_regress/t/t_class_virtual_pure_bad.v | 9 +++++++++ 5 files changed, 41 insertions(+), 7 deletions(-) delete mode 100644 test_regress/t/t_class_virtual_pure.out create mode 100644 test_regress/t/t_class_virtual_pure_bad.out create mode 100755 test_regress/t/t_class_virtual_pure_bad.pl create mode 100644 test_regress/t/t_class_virtual_pure_bad.v diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 3abe211ba..52344c197 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -205,6 +205,15 @@ private: nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep())); nodep->virtRefDType2p(editOneDType(nodep->virtRefDType2p())); } + virtual void visit(AstNodeFTask* nodep) override { + iterateChildren(nodep); + editDType(nodep); + if (nodep->classMethod() && nodep->pureVirtual() && VN_IS(m_modp, Class) + && !VN_CAST(m_modp, Class)->isVirtual()) { + nodep->v3error( + "Illegal to have 'pure virtual' in non-virtual class (IEEE 1800-2017 8.21)"); + } + } virtual void visit(AstNodeVarRef* nodep) override { iterateChildren(nodep); editDType(nodep); diff --git a/test_regress/t/t_class_virtual_pure.out b/test_regress/t/t_class_virtual_pure.out deleted file mode 100644 index ec7ef63ac..000000000 --- a/test_regress/t/t_class_virtual_pure.out +++ /dev/null @@ -1,7 +0,0 @@ -%Error-UNSUPPORTED: t/t_class_virtual_pure.v:8:22: Unsupported: 'virtual' class method - 8 | pure virtual task hello(); - | ^~~~~ -%Error-UNSUPPORTED: t/t_class_virtual_pure.v:7:9: Unsupported: virtual class - 7 | virtual class VC; - | ^~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_class_virtual_pure_bad.out b/test_regress/t/t_class_virtual_pure_bad.out new file mode 100644 index 000000000..067482f2b --- /dev/null +++ b/test_regress/t/t_class_virtual_pure_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_class_virtual_pure_bad.v:8:22: Illegal to have 'pure virtual' in non-virtual class (IEEE 1800-2017 8.21) + 8 | pure virtual task pure_task; + | ^~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_virtual_pure_bad.pl b/test_regress/t/t_class_virtual_pure_bad.pl new file mode 100755 index 000000000..009248fc5 --- /dev/null +++ b/test_regress/t/t_class_virtual_pure_bad.pl @@ -0,0 +1,19 @@ +#!/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(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_virtual_pure_bad.v b/test_regress/t/t_class_virtual_pure_bad.v new file mode 100644 index 000000000..7b3754db3 --- /dev/null +++ b/test_regress/t/t_class_virtual_pure_bad.v @@ -0,0 +1,9 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2019 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class VBase; + pure virtual task pure_task; +endclass From cef7610b14a3c5997018843e08f4bc15ecbdb784 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 20:02:17 -0500 Subject: [PATCH 62/91] Fix crash on virtual interfaces. --- src/verilog.y | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/verilog.y b/src/verilog.y index 515bda060..e77ea9086 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -1837,8 +1837,10 @@ data_typeNoRef: // ==IEEE: data_type, excluding class_type etc referenc // // IEEE has ['.' modport] but that will conflict with port // // declarations which decode '.' modport themselves, so // // instead see data_typeVar - | yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: virtual interface"); } - | yVIRTUAL__anyID id/*interface*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: virtual data type"); } + | yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ + { $$ = new AstBasicDType($1, AstBasicDTypeKwd::CHANDLE); BBUNSUP($1, "Unsupported: virtual interface"); } + | yVIRTUAL__anyID id/*interface*/ + { $$ = new AstBasicDType($1, AstBasicDTypeKwd::CHANDLE); BBUNSUP($1, "Unsupported: virtual data type"); } | type_reference { $$ = $1; } // // IEEE: class_scope: see data_type above // // IEEE: class_type: see data_type above From 5091298fae876602d68263a9d57912abdbae31e3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 20:25:02 -0500 Subject: [PATCH 63/91] Internals: Cleanup V3Unknown. No functional change intended. --- src/V3Unknown.cpp | 36 ++++++++++++++++++++----------- test_regress/t/t_math_countbits.v | 16 +++++++++++++- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 8c952c9a0..1a3dae823 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -137,6 +137,7 @@ private: virtual void visit(AstNodeModule* nodep) override { UINFO(4, " MOD " << nodep << endl); VL_RESTORER(m_modp); + VL_RESTORER(m_constXCvt); { m_modp = nodep; m_constXCvt = true; @@ -144,25 +145,34 @@ private: } } virtual void visit(AstAssignDly* nodep) override { - m_assigndlyp = nodep; - VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. - m_assigndlyp = nullptr; + VL_RESTORER(m_assigndlyp); + { + m_assigndlyp = nodep; + VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. + } } virtual void visit(AstAssignW* nodep) override { - m_assignwp = nodep; - VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. - m_assignwp = nullptr; + VL_RESTORER(m_assignwp); + { + m_assignwp = nodep; + VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. + } } virtual void visit(AstCaseItem* nodep) override { - m_constXCvt = false; // Avoid losing the X's in casex - iterateAndNextNull(nodep->condsp()); - m_constXCvt = true; - iterateAndNextNull(nodep->bodysp()); + VL_RESTORER(m_constXCvt); + { + m_constXCvt = false; // Avoid losing the X's in casex + iterateAndNextNull(nodep->condsp()); + m_constXCvt = true; + iterateAndNextNull(nodep->bodysp()); + } } virtual void visit(AstNodeDType* nodep) override { - m_constXCvt = false; // Avoid losing the X's in casex - iterateChildren(nodep); - m_constXCvt = true; + VL_RESTORER(m_constXCvt); + { + m_constXCvt = false; // Avoid losing the X's in casex + iterateChildren(nodep); + } } void visitEqNeqCase(AstNodeBiop* nodep) { UINFO(4, " N/EQCASE->EQ " << nodep << endl); diff --git a/test_regress/t/t_math_countbits.v b/test_regress/t/t_math_countbits.v index 8a1d9d4c5..e82c9ee93 100644 --- a/test_regress/t/t_math_countbits.v +++ b/test_regress/t/t_math_countbits.v @@ -37,6 +37,18 @@ module t(/*AUTOARG*/ reg [5:0] result_59_3; reg [6:0] result_70_3; + initial begin + if ($countbits(32'b111100000000, '1) != 4) $stop; + if ($countbits(32'b111100000000, '0) != 28) $stop; + if ($countbits(32'b111100000000, '0, '1) != 32) $stop; + if ($countbits(4'bxxx0, 'x) != 3) $stop; + if ($countbits(4'bzzz0, 'z) != 3) $stop; + if ($countbits(4'b1zz0, 'z, '0) != 3) $stop; + if ($countbits(4'b1xx0, 'x, '0) != 3) $stop; + if ($countbits(4'b1xx0, 'x, '0, '1) != 4) $stop; + if ($countbits(4'bzzx0, 'x, 'z) != 3) $stop; + end + always @* begin result_16_1 = $countbits(in16, ctrl0); result_16_2 = $countbits(in16, ctrl0, ctrl1); @@ -73,11 +85,13 @@ module t(/*AUTOARG*/ if ($countbits(32'b1100x01z101, 'x, 'z) != 2) $stop; if ($countbits(32'b1100x01z101, 'x, 'z, '1) != 7) $stop; -`ifndef VERILATOR // Unsup if ($countbits(val, '1) != 7) $stop; if ($countones(val) != 7) $stop; if ($countbits(val, '0) != 25) $stop; if ($countbits(val, '0, '1) != 32) $stop; +`ifndef VERILATOR // Unsup + if ($countbits(val, 'x) != 0) $stop; + if ($countbits(val, 'z) != 0) $stop; if ($countbits(val, 'x, 'z) != 0) $stop; `endif end From 0c6bd42da3220634af3ce4e24bf911f943c066ec Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 20:51:32 -0500 Subject: [PATCH 64/91] Fix $countbits(..., 'x) --- src/V3Unknown.cpp | 36 +++++++++++++++++++++++++++++++ test_regress/t/t_math_countbits.v | 15 ++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 1a3dae823..6c760998e 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -258,6 +258,42 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } + virtual void visit(AstCountBits* nodep) override { + // Ahh, we're two state, so this is easy + std::array dropop; + dropop[0] = VN_IS(nodep->rhsp(), Const) && VN_CAST(nodep->rhsp(), Const)->num().isAnyX(); + dropop[1] = VN_IS(nodep->thsp(), Const) && VN_CAST(nodep->thsp(), Const)->num().isAnyX(); + dropop[2] = VN_IS(nodep->fhsp(), Const) && VN_CAST(nodep->fhsp(), Const)->num().isAnyX(); + UINFO(4, " COUNTBITS(" << dropop[0] << dropop[1] << dropop[2] << " " << nodep << endl); + + AstNode* nonXp = nullptr; + if (!dropop[0]) + nonXp = nodep->rhsp(); + else if (!dropop[1]) + nonXp = nodep->thsp(); + else if (!dropop[2]) + nonXp = nodep->fhsp(); + else { // Was all X-s + UINFO(4, " COUNTBITS('x)->0 " << nodep << endl); + AstConst* newp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + return; + } + if (dropop[0]) { + nodep->rhsp()->unlinkFrBack()->deleteTree(); + nodep->rhsp(nonXp->cloneTree(true)); + } + if (dropop[1]) { + nodep->thsp()->unlinkFrBack()->deleteTree(); + nodep->thsp(nonXp->cloneTree(true)); + } + if (dropop[2]) { + nodep->fhsp()->unlinkFrBack()->deleteTree(); + nodep->fhsp(nonXp->cloneTree(true)); + } + iterateChildren(nodep); + } virtual void visit(AstConst* nodep) override { if (m_constXCvt && nodep->num().isFourState()) { UINFO(4, " CONST4 " << nodep << endl); diff --git a/test_regress/t/t_math_countbits.v b/test_regress/t/t_math_countbits.v index e82c9ee93..de02ccb5c 100644 --- a/test_regress/t/t_math_countbits.v +++ b/test_regress/t/t_math_countbits.v @@ -89,9 +89,22 @@ module t(/*AUTOARG*/ if ($countones(val) != 7) $stop; if ($countbits(val, '0) != 25) $stop; if ($countbits(val, '0, '1) != 32) $stop; -`ifndef VERILATOR // Unsup + // Optimization may depend on position of X, so need to walk it if ($countbits(val, 'x) != 0) $stop; + if ($countbits(val, 'x, '1) != 7) $stop; + if ($countbits(val, '1, 'x) != 7) $stop; + if ($countbits(val, '1, '1, 'x) != 7) $stop; + if ($countbits(val, 'x, '0) != 25) $stop; + if ($countbits(val, 'x, '0, '1) != 32) $stop; +`ifndef VERILATOR + // Optimization may depend on position of Z, so need to walk it if ($countbits(val, 'z) != 0) $stop; + if ($countbits(val, 'z, '1) != 7) $stop; + if ($countbits(val, '1, 'z) != 7) $stop; + if ($countbits(val, '1, '1, 'z) != 7) $stop; + if ($countbits(val, 'z, '0) != 25) $stop; + if ($countbits(val, 'z, '0, '1) != 32) $stop; + // if ($countbits(val, 'x, 'z) != 0) $stop; `endif end From d77beecc6e957d2b82189a4ed3d103cb724d1855 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 21:34:40 -0500 Subject: [PATCH 65/91] Fix $countbits(..., 'z) --- src/V3Number.cpp | 5 +-- src/V3Number.h | 1 + src/V3Tristate.cpp | 59 +++++++++++++++++++++++++++++++ test_regress/t/t_math_countbits.v | 2 -- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 8d4e57307..a2073dff7 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -937,10 +937,11 @@ bool V3Number::isAnyX() const { } return false; } -bool V3Number::isAnyXZ() const { +bool V3Number::isAnyXZ() const { return isAnyX() || isAnyZ(); } +bool V3Number::isAnyZ() const { if (isDouble() || isString()) return false; for (int bit = 0; bit < width(); bit++) { - if (bitIsX(bit) || bitIsZ(bit)) return true; + if (bitIsZ(bit)) return true; } return false; } diff --git a/src/V3Number.h b/src/V3Number.h index 7a01876fb..240858ea9 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -273,6 +273,7 @@ public: void isSigned(bool ssigned) { m_signed = ssigned; } bool isAnyX() const; bool isAnyXZ() const; + bool isAnyZ() const; bool isMsbXZ() const { return bitIsXZ(m_width); } uint32_t toUInt() const; vlsint32_t toSInt() const; diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index ca5119846..cc192edd4 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -981,6 +981,65 @@ class TristateVisitor final : public TristateBaseVisitor { virtual void visit(AstEqWild* nodep) override { visitEqNeqWild(nodep); } virtual void visit(AstNeqWild* nodep) override { visitEqNeqWild(nodep); } + virtual void visit(AstCountBits* nodep) override { + std::array dropop; + dropop[0] = VN_IS(nodep->rhsp(), Const) && VN_CAST(nodep->rhsp(), Const)->num().isAnyZ(); + dropop[1] = VN_IS(nodep->thsp(), Const) && VN_CAST(nodep->thsp(), Const)->num().isAnyZ(); + dropop[2] = VN_IS(nodep->fhsp(), Const) && VN_CAST(nodep->fhsp(), Const)->num().isAnyZ(); + UINFO(4, " COUNTBITS(" << dropop[0] << dropop[1] << dropop[2] << " " << nodep << endl); + AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); // Input variable + if (m_graphing) { + iterateAndNextNull(nodep->lhsp()); + if (!dropop[0]) iterateAndNextNull(nodep->rhsp()); + if (!dropop[1]) iterateAndNextNull(nodep->thsp()); + if (!dropop[2]) iterateAndNextNull(nodep->fhsp()); + } else { + AstNode* nonXp = nullptr; + if (!dropop[0]) + nonXp = nodep->rhsp(); + else if (!dropop[1]) + nonXp = nodep->thsp(); + else if (!dropop[2]) + nonXp = nodep->fhsp(); + // Replace 'z with non-Z + if (dropop[0] || dropop[1] || dropop[2]) { + // Unsupported: A $countones('0) should compare with the enables, but we don't + // do so at present, we only compare if there is a z in the equation. Otherwise + // we'd need to attach an enable to every signal, then optimize them away later + // when we determine the signal has no tristate + if (!VN_IS(nodep->lhsp(), VarRef)) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported LHS tristate construct: " + << nodep->prettyTypeName()); + return; + } + AstVar* envarp = getCreateEnVarp(varrefp->varp()); + // If any drops, we need to add in the count of Zs (from __en) + UINFO(4, " COUNTBITS('z)-> " << nodep << endl); + AstNRelinker relinkHandle; + nodep->unlinkFrBack(&relinkHandle); + AstNode* newp = new AstCountOnes( + nodep->fileline(), new AstVarRef(nodep->fileline(), envarp, VAccess::READ)); + if (nonXp) { // Need to still count '0 or '1 or 'x's + if (dropop[0]) { + nodep->rhsp()->unlinkFrBack()->deleteTree(); + nodep->rhsp(nonXp->cloneTree(true)); + } + if (dropop[1]) { + nodep->thsp()->unlinkFrBack()->deleteTree(); + nodep->thsp(nonXp->cloneTree(true)); + } + if (dropop[2]) { + nodep->fhsp()->unlinkFrBack()->deleteTree(); + nodep->fhsp(nonXp->cloneTree(true)); + } + newp = new AstAdd(nodep->fileline(), nodep, newp); + } + if (debug() >= 9) newp->dumpTree(cout, "-countout: "); + relinkHandle.relink(newp); + } + iterateChildren(nodep); + } + } virtual void visit(AstPull* nodep) override { UINFO(9, dbgState() << nodep << endl); AstVarRef* varrefp = nullptr; diff --git a/test_regress/t/t_math_countbits.v b/test_regress/t/t_math_countbits.v index de02ccb5c..547263faa 100644 --- a/test_regress/t/t_math_countbits.v +++ b/test_regress/t/t_math_countbits.v @@ -96,7 +96,6 @@ module t(/*AUTOARG*/ if ($countbits(val, '1, '1, 'x) != 7) $stop; if ($countbits(val, 'x, '0) != 25) $stop; if ($countbits(val, 'x, '0, '1) != 32) $stop; -`ifndef VERILATOR // Optimization may depend on position of Z, so need to walk it if ($countbits(val, 'z) != 0) $stop; if ($countbits(val, 'z, '1) != 7) $stop; @@ -106,7 +105,6 @@ module t(/*AUTOARG*/ if ($countbits(val, 'z, '0, '1) != 32) $stop; // if ($countbits(val, 'x, 'z) != 0) $stop; -`endif end else if (cyc == 1) begin in16 <= 16'h0AF0; From cf2810db8bb0aaf1bab81b0b633d1a91b0a39c33 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 21:49:47 -0500 Subject: [PATCH 66/91] Change -sv option to select 1800-2017 instead of 1800-2005. --- Changes | 2 ++ bin/verilator | 2 +- src/V3Options.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 023477ec9..e740aff86 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.105 devel +*** Change -sv option to select 1800-2017 instead of 1800-2005. + *** Support $random and $urandom seeds. *** Support 'super'. diff --git a/bin/verilator b/bin/verilator index b059d87e7..ac88b8e2a 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1461,7 +1461,7 @@ future version of Verilator no longer always packs unpacked structures. =item -sv Specifies SystemVerilog language features should be enabled; equivalent to -"--language 1800-2005". This option is selected by default, it exists for +"--language 1800-2017". This option is selected by default, it exists for compatibility with other simulators. =item +systemverilogext+I diff --git a/src/V3Options.cpp b/src/V3Options.cpp index d0bae2ff4..3b49377ed 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1101,7 +1101,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char } else if (onoff(sw, "-structs-unpacked", flag /*ref*/)) { m_structsPacked = flag; } else if (!strcmp(sw, "-sv")) { - m_defaultLanguage = V3LangCode::L1800_2005; + m_defaultLanguage = V3LangCode::L1800_2017; } else if (onoff(sw, "-threads-coarsen", flag /*ref*/)) { // Undocumented, debug m_threadsCoarsen = flag; } else if (onoff(sw, "-trace", flag /*ref*/)) { From 1299b70945ef04708b5c0a87250eb49914c15143 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 27 Nov 2020 22:48:42 -0500 Subject: [PATCH 67/91] Internals: Pass class parameters through link. --- src/V3AstNodes.h | 5 +++- src/V3LinkCells.cpp | 7 ++++++ src/V3LinkDot.cpp | 36 +++++++++++++++++++++------- test_regress/t/t_class_param_bad.out | 17 +++++++++++++ test_regress/t/t_class_param_bad.pl | 19 +++++++++++++++ test_regress/t/t_class_param_bad.v | 15 ++++++++++++ test_regress/t/t_class_vparam.out | 3 +++ 7 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 test_regress/t/t_class_param_bad.out create mode 100755 test_regress/t/t_class_param_bad.pl create mode 100644 test_regress/t/t_class_param_bad.v diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 3dfca497b..09d1cdc91 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -988,14 +988,16 @@ public: class AstClassRefDType final : public AstNodeDType { // Reference to a class + // Children: PINs (for parameter settings) private: AstClass* m_classp; // data type pointed to, BELOW the AstTypedef AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy public: - AstClassRefDType(FileLine* fl, AstClass* classp) + AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp) : ASTGEN_SUPER(fl) , m_classp{classp} { dtypep(this); + addNOp4p(paramsp); } ASTNODE_NODE_FUNCS(ClassRefDType) // METHODS @@ -1032,6 +1034,7 @@ public: void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } AstClass* classp() const { return m_classp; } void classp(AstClass* nodep) { m_classp = nodep; } + AstPin* paramsp() const { return VN_CAST(op4p(), Pin); } }; class AstIfaceRefDType final : public AstNodeDType { diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index b4dec71fa..df9d24582 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -457,6 +457,13 @@ private: UINFO(4, " Link Cell done: " << nodep << endl); } + virtual void visit(AstRefDType* nodep) override { + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + pinp->param(true); + if (pinp->name() == "") pinp->name("__paramNumber" + cvtToStr(pinp->pinNum())); + } + } + // Accelerate the recursion // Must do statements to support Generates, math though... virtual void visit(AstNodeMath*) override {} diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index c2058735f..23f600284 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1941,11 +1941,13 @@ private: virtual void visit(AstCell* nodep) override { // Cell: Recurse inside or cleanup not founds checkNoDot(nodep); - m_cellp = nodep; AstNode::user5ClearTree(); UASSERT_OBJ(nodep->modp(), nodep, "Cell has unlinked module"); // V3LinkCell should have errored out + VL_RESTORER(m_cellp); + VL_RESTORER(m_pinSymp); { + m_cellp = nodep; if (VN_IS(nodep->modp(), NotFoundModule)) { // Prevent warnings about missing pin connects if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree(); @@ -1960,13 +1962,26 @@ private: // if (debug()) nodep->dumpTree(cout, "linkcell:"); // if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:"); iterateChildren(nodep); - m_pinSymp = nullptr; } } - m_cellp = nullptr; // Parent module inherits child's publicity // This is done bottom up in the LinkBotupVisitor stage } + virtual void visit(AstClassRefDType* nodep) override { + // Cell: Recurse inside or cleanup not founds + checkNoDot(nodep); + AstNode::user5ClearTree(); + UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class"); + VL_RESTORER(m_pinSymp); + { + // ClassRef's have pins, so track + m_pinSymp = m_statep->getNodeSym(nodep->classp()); + UINFO(4, "(Backto) Link ClassRefDType: " << nodep << endl); + // if (debug()) nodep->dumpTree(cout, "linkcell:"); + // if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:"); + iterateChildren(nodep); + } + } virtual void visit(AstPin* nodep) override { // Pin: Link to submodule's port checkNoDot(nodep); @@ -1976,7 +1991,8 @@ private: VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name()); const char* whatp = nodep->param() ? "parameter pin" : "pin"; if (!foundp) { - if (nodep->name() == "__paramNumber1" && VN_IS(m_cellp->modp(), Primitive)) { + if (nodep->name() == "__paramNumber1" && m_cellp + && VN_IS(m_cellp->modp(), Primitive)) { // Primitive parameter is really a delay we can just ignore VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return; @@ -2540,7 +2556,7 @@ private: "Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name())); } if (cpackagerefp->paramsp()) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages"); + nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages for task calls"); } UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link"); nodep->classOrPackagep(cpackagerefp->classOrPackagep()); @@ -2817,8 +2833,10 @@ private: cextp->v3error("Attempting to extend class " << nodep->prettyNameQ() << " from itself"); } else { - AstClassRefDType* newp - = new AstClassRefDType{nodep->fileline(), classp}; + AstNode* paramsp = cpackagerefp->paramsp(); + if (paramsp) paramsp = paramsp->cloneTree(true); + const auto newp + = new AstClassRefDType{nodep->fileline(), classp, paramsp}; cextp->childDTypep(newp); classp->isExtended(true); nodep->isExtended(true); @@ -2909,7 +2927,9 @@ private: nodep->refDTypep(defp); nodep->classOrPackagep(foundp->classOrPackagep()); } else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : nullptr) { - AstClassRefDType* newp = new AstClassRefDType(nodep->fileline(), defp); + AstNode* paramsp = nodep->paramsp(); + if (paramsp) paramsp->unlinkFrBackWithNext(); + AstClassRefDType* newp = new AstClassRefDType{nodep->fileline(), defp, paramsp}; newp->classOrPackagep(foundp->classOrPackagep()); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); diff --git a/test_regress/t/t_class_param_bad.out b/test_regress/t/t_class_param_bad.out new file mode 100644 index 000000000..d7a071bf0 --- /dev/null +++ b/test_regress/t/t_class_param_bad.out @@ -0,0 +1,17 @@ +%Error-UNSUPPORTED: t/t_class_param_bad.v:12:4: Unsupported: parameterized packages + 12 | Cls #(.PARAMBAD(1)) c; + | ^~~ +%Error: t/t_class_param_bad.v:12:11: Parameter pin not found: 'PARAMBAD' + : ... Suggested alternative: 'PARAMB' + 12 | Cls #(.PARAMBAD(1)) c; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_class_param_bad.v:13:4: Unsupported: parameterized packages + 13 | Cls #(13, 1) cd; + | ^~~ +%Error: t/t_class_param_bad.v:13:14: Parameter pin not found: '__paramNumber2' + 13 | Cls #(13, 1) cd; + | ^ +%Error-UNSUPPORTED: t/t_class_param_bad.v:7:23: Unsupported: class parameter + 7 | class Cls #(parameter PARAMB = 12); + | ^~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_param_bad.pl b/test_regress/t/t_class_param_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_class_param_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_param_bad.v b/test_regress/t/t_class_param_bad.v new file mode 100644 index 000000000..ba12815f1 --- /dev/null +++ b/test_regress/t/t_class_param_bad.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls #(parameter PARAMB = 12); +endclass + +module t (/*AUTOARG*/); + + Cls #(.PARAMBAD(1)) c; // Bad param name + Cls #(13, 1) cd; // Bad param number + +endmodule diff --git a/test_regress/t/t_class_vparam.out b/test_regress/t/t_class_vparam.out index c5a35f922..1816089b8 100644 --- a/test_regress/t/t_class_vparam.out +++ b/test_regress/t/t_class_vparam.out @@ -1,4 +1,7 @@ %Error-UNSUPPORTED: t/t_class_vparam.v:13:40: Unsupported: parameterized packages 13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); | ^~~~~~~~~~~~~~~ +%Error: t/t_class_vparam.v:13:58: Parameter pin not found: '__paramNumber1' + 13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); + | ^~~~~~~ %Error: Exiting due to From e14319b4017a2cbc89dc9380442a208b3093a35e Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 12:04:29 -0500 Subject: [PATCH 68/91] Internals: Refactor V3Param through code movement only. No functional change intended. --- src/V3Param.cpp | 204 +++++++++++++++++++++++------------------------- 1 file changed, 98 insertions(+), 106 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 3bd40c096..df9e60c1e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -307,7 +307,7 @@ class ParamProcessor final { } return string("z") + cvtToStr(num); } - string moduleCalcName(AstNodeModule* srcModp, AstCell* cellp, const string& longname) { + string moduleCalcName(AstNodeModule* srcModp, AstPin* paramsp, const string& longname) { string newname = longname; if (longname.length() > 30 || srcModp->hierBlock()) { const auto iter = m_longMap.find(longname); @@ -315,7 +315,7 @@ class ParamProcessor final { newname = iter->second; } else { if (srcModp->hierBlock()) { - newname = parametrizedHierBlockName(srcModp, cellp->paramsp()); + newname = parametrizedHierBlockName(srcModp, paramsp); } else { newname = srcModp->name(); // We use all upper case above, so lower here can't conflict @@ -324,6 +324,7 @@ class ParamProcessor final { m_longMap.insert(make_pair(longname, newname)); } } + UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); return newname; } AstNodeDType* arraySubDTypep(AstNodeDType* nodep) { @@ -358,7 +359,7 @@ class ParamProcessor final { } } } - void relinkPins(CloneMap* clonemapp, AstPin* startpinp) { + void relinkPins(const CloneMap* clonemapp, AstPin* startpinp) { for (AstPin* pinp = startpinp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->modVarp()) { // Find it in the clone structure @@ -419,6 +420,7 @@ class ParamProcessor final { if (m_modNameMap.find(modName) != m_modNameMap.end()) return true; return false; } + string parametrizedHierBlockName(const AstNodeModule* modp, AstPin* paramPinsp) const { VHashSha256 hash; // Calculate hash using module name, parameter name, and parameter value @@ -446,8 +448,8 @@ class ParamProcessor final { hash.insert(V3Os::trueRandom(64)); } } - AstNodeModule* deepCloneModule(AstNodeModule* srcModp, AstCell* cellp, const string& newname, - const IfaceRefRefs& ifaceRefRefs) { + void deepCloneModule(AstNodeModule* srcModp, AstNode* cellp, AstPin* paramsp, + const string& newname, const IfaceRefRefs& ifaceRefRefs) { // Deep clone of new module // Note all module internal variables will be re-linked to the new modules by clone // However links outside the module (like on the upper cells) will not. @@ -458,7 +460,6 @@ class ParamProcessor final { newmodp->recursiveClone(false); // Only the first generation of clone holds this property newmodp->hierBlock(srcModp->hierBlock() && !srcModp->recursiveClone()); - cellp->recursive(false); // Recursion may need level cleanups if (newmodp->level() <= m_modp->level()) newmodp->level(m_modp->level() + 1); if ((newmodp->level() - srcModp->level()) >= (v3Global.opt.moduleRecursionDepth() - 2)) { @@ -483,7 +484,7 @@ class ParamProcessor final { // thus we need to stash this info. collectPins(clonemapp, newmodp); // Relink parameter vars to the new module - relinkPins(clonemapp, cellp->paramsp()); + relinkPins(clonemapp, paramsp); // Fix any interface references for (auto it = ifaceRefRefs.cbegin(); it != ifaceRefRefs.cend(); ++it) { AstIfaceRefDType* portIrefp = it->first; @@ -498,7 +499,7 @@ class ParamProcessor final { } // Assign parameters to the constants specified // DOES clone() so must be finished with module clonep() before here - for (AstPin* pinp = cellp->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + for (AstPin* pinp = paramsp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->exprp()) { if (newmodp->hierBlock()) checkSupportedParam(newmodp, pinp); if (AstVar* modvarp = pinp->modVarp()) { @@ -519,80 +520,87 @@ class ParamProcessor final { } } } - return newmodp; + } + const ModInfo* moduleFindOrClone(AstNodeModule* srcModp, AstNode* cellp, AstPin* paramsp, + const string& newname, const IfaceRefRefs& ifaceRefRefs) { + // Already made this flavor? + auto it = m_modNameMap.find(newname); + if (it != m_modNameMap.end()) { + UINFO(4, " De-parameterize to old: " << it->second.m_modp << endl); + } else { + deepCloneModule(srcModp, cellp, paramsp, newname, ifaceRefRefs); + it = m_modNameMap.find(newname); + UASSERT(it != m_modNameMap.end(), "should find just-made module"); + } + const ModInfo* modInfop = &(it->second); + return modInfop; } - void cellPinCleanup(AstCell* nodep, string& longnamer, bool& any_overridesr) { - AstNodeModule* srcModp = nodep->modp(); - for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { - if (!pinp->exprp()) continue; // No-connect - if (AstVar* modvarp = pinp->modVarp()) { - if (!modvarp->isGParam()) { - pinp->v3error("Attempted parameter setting of non-parameter: Param " + void cellPinCleanup(AstNode* nodep, AstPin* pinp, AstNodeModule* srcModp, string& longnamer, + bool& any_overridesr) { + if (!pinp->exprp()) return; // No-connect + if (AstVar* modvarp = pinp->modVarp()) { + if (!modvarp->isGParam()) { + pinp->v3error("Attempted parameter setting of non-parameter: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } else if (VN_IS(pinp->exprp(), InitArray) && arraySubDTypep(modvarp->subDTypep())) { + // Array assigned to array + AstNode* exprp = pinp->exprp(); + longnamer += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + any_overridesr = true; + } else { + AstConst* exprp = VN_CAST(pinp->exprp(), Const); + AstConst* origp = VN_CAST(modvarp->valuep(), Const); + if (!exprp) { + // if (debug()) pinp->dumpTree(cout, "error:"); + pinp->v3error("Can't convert defparam value to constant: Param " << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } else if (VN_IS(pinp->exprp(), InitArray) - && arraySubDTypep(modvarp->subDTypep())) { - // Array assigned to array - AstNode* exprp = pinp->exprp(); - longnamer += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + pinp->exprp()->replaceWith(new AstConst( + pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0)); + } else if (origp && exprp->sameTree(origp)) { + // Setting parameter to its default value. Just ignore it. + // This prevents making additional modules, and makes coverage more + // obvious as it won't show up under a unique module page name. + } else if (exprp->num().isDouble() || exprp->num().isString() + || exprp->num().isFourState() || exprp->num().width() != 32) { + longnamer + += ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp)); any_overridesr = true; } else { - AstConst* exprp = VN_CAST(pinp->exprp(), Const); - AstConst* origp = VN_CAST(modvarp->valuep(), Const); - if (!exprp) { - // if (debug()) pinp->dumpTree(cout, "error:"); - pinp->v3error("Can't convert defparam value to constant: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - pinp->exprp()->replaceWith(new AstConst( - pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0)); - } else if (origp && exprp->sameTree(origp)) { - // Setting parameter to its default value. Just ignore it. - // This prevents making additional modules, and makes coverage more - // obvious as it won't show up under a unique module page name. - } else if (exprp->num().isDouble() || exprp->num().isString() - || exprp->num().isFourState() || exprp->num().width() != 32) { - longnamer - += ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp)); - any_overridesr = true; - } else { - longnamer += ("_" + paramSmallName(srcModp, modvarp) - + exprp->num().ascii(false)); - any_overridesr = true; - } + longnamer + += ("_" + paramSmallName(srcModp, modvarp) + exprp->num().ascii(false)); + any_overridesr = true; } - } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { - AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType); - AstNodeDType* origp = modvarp->subDTypep(); - if (!exprp) { - pinp->v3error("Parameter type pin value isn't a type: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); - } else if (!origp) { - pinp->v3error("Parameter type variable isn't a type: Param " - << modvarp->prettyNameQ()); - } else { - UINFO(9, - "Parameter type assignment expr=" << exprp << " to " << origp << endl); - if (exprp->sameTree(origp)) { - // Setting parameter to its default value. Just ignore it. - // This prevents making additional modules, and makes coverage more - // obvious as it won't show up under a unique module page name. - } else { - V3Const::constifyParamsEdit(exprp); - longnamer - += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); - any_overridesr = true; - } - } - } else { - pinp->v3error("Parameter not found in sub-module: Param " - << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); } + } else if (AstParamTypeDType* modvarp = pinp->modPTypep()) { + AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType); + AstNodeDType* origp = modvarp->subDTypep(); + if (!exprp) { + pinp->v3error("Parameter type pin value isn't a type: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + } else if (!origp) { + pinp->v3error("Parameter type variable isn't a type: Param " + << modvarp->prettyNameQ()); + } else { + UINFO(9, "Parameter type assignment expr=" << exprp << " to " << origp << endl); + if (exprp->sameTree(origp)) { + // Setting parameter to its default value. Just ignore it. + // This prevents making additional modules, and makes coverage more + // obvious as it won't show up under a unique module page name. + } else { + V3Const::constifyParamsEdit(exprp); + longnamer += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + any_overridesr = true; + } + } + } else { + pinp->v3error("Parameter not found in sub-module: Param " + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); } } - void cellInterfaceCleanup(AstCell* nodep, string& longnamer, bool& any_overridesr, - IfaceRefRefs& ifaceRefRefs) { - AstNodeModule* srcModp = nodep->modp(); + void cellInterfaceCleanup(AstCell* nodep, AstNodeModule* srcModp, string& longnamer, + bool& any_overridesr, IfaceRefRefs& ifaceRefRefs) { for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { AstVar* modvarp = pinp->modVarp(); if (modvarp->isIfaceRef()) { @@ -670,16 +678,18 @@ public: // Make sure constification worked // Must be a separate loop, as constant conversion may have changed some pointers. // if (debug()) nodep->dumpTree(cout, "-cel2: "); - string longname = srcModp->name(); + string longname = srcModp->name() + "_"; bool any_overrides = false; // Must always clone __Vrcm (recursive modules) if (nodep->recursive()) any_overrides = true; - longname += "_"; if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); - cellPinCleanup(nodep, longname /*ref*/, any_overrides /*ref*/); + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + cellPinCleanup(nodep, pinp, srcModp, longname /*ref*/, any_overrides /*ref*/); + } IfaceRefRefs ifaceRefRefs; - cellInterfaceCleanup(nodep, longname /*ref*/, any_overrides /*ref*/, ifaceRefRefs /*ref*/); + cellInterfaceCleanup(nodep, srcModp, longname /*ref*/, any_overrides /*ref*/, + ifaceRefRefs /*ref*/); if (!any_overrides) { UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); @@ -691,32 +701,16 @@ public: // We need to relink the pins to the new module relinkPinsByName(nodep->pinsp(), modp); } else { - // If the name is very long, we don't want to overwhelm the filename limit - // We don't do this always, as it aids debugability to have intuitive naming. - // TODO can use new V3Name hash replacement instead of this - // Shorter name is convenient for hierarchical block - string newname = moduleCalcName(srcModp, nodep, longname); - UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); - // - // Already made this flavor? - AstNodeModule* cellmodp = nullptr; - auto iter = m_modNameMap.find(newname); - if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp; - if (!cellmodp) { - cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs); - iter = m_modNameMap.find(newname); - UASSERT(iter != m_modNameMap.end(), "should find just-made module"); - } else { - UINFO(4, " De-parameterize to old: " << cellmodp << endl); - } + string newname = moduleCalcName(srcModp, nodep->paramsp(), longname); + const ModInfo* modInfop + = moduleFindOrClone(srcModp, nodep, nodep->paramsp(), newname, ifaceRefRefs); // Have child use this module instead. - nodep->modp(cellmodp); + nodep->modp(modInfop->m_modp); nodep->modName(newname); // We need to relink the pins to the new module - CloneMap* clonemapp = &(iter->second.m_cloneMap); - relinkPins(clonemapp, nodep->pinsp()); - UINFO(8, " Done with " << cellmodp << endl); - } // if any_overrides + relinkPins(&(modInfop->m_cloneMap), nodep->pinsp()); + UINFO(8, " Done with " << modInfop->m_modp << endl); + } nodep->recursive(false); @@ -788,19 +782,17 @@ class ParamVisitor final : public AstNVisitor { if ((nonIf == 0 && VN_IS(cellp->modp(), Iface)) || (nonIf == 1 && !VN_IS(cellp->modp(), Iface))) { string fullName(m_modp->hierName()); - if (string* genHierNamep = (string*)cellp->user5p()) { + if (const string* genHierNamep = (string*)cellp->user5p()) { fullName += *genHierNamep; } visitCellDeparam(cellp, fullName); + if (const string* genHierNamep = (string*)cellp->user5p()) { + cellp->user5p(nullptr); + VL_DO_DANGLING(delete genHierNamep, genHierNamep); + } } } } - for (AstCell* cellp : m_cellps) { - if (string* genHierNamep = (string*)cellp->user5p()) { - cellp->user5p(nullptr); - VL_DO_DANGLING(delete genHierNamep, genHierNamep); - } - } m_cellps.clear(); m_modp = nullptr; UINFO(4, " MOD-done\n"); From 05f3fd7c6eec8e90b16ca790122041f174e2cc21 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 12:26:44 -0500 Subject: [PATCH 69/91] Fix class new with math. --- src/V3Width.cpp | 1 - test_regress/t/t_class_new.v | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6291db047..f4a35ce6d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -3113,7 +3113,6 @@ private: "Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)"); } userIterate(nodep->taskp(), nullptr); - userIterateChildren(nodep, nullptr); processFTaskRefArgs(nodep); } virtual void visit(AstNewCopy* nodep) override { diff --git a/test_regress/t/t_class_new.v b/test_regress/t/t_class_new.v index f8642e6cf..ba1506312 100644 --- a/test_regress/t/t_class_new.v +++ b/test_regress/t/t_class_new.v @@ -29,7 +29,7 @@ module t (/*AUTOARG*/); c1 = new; if (c1.imembera != 5) $stop; - c2 = new(2); + c2 = new(3 - 1); if (c2.imembera != 3) $stop; if (c2.geta() != 3) $stop; From 30686d855044dcefab9f3359c091aea634666295 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 12:43:13 -0500 Subject: [PATCH 70/91] Support passing of objects to functions --- src/V3Width.cpp | 1 + test_regress/t/t_class_new.v | 9 +++++++++ test_regress/t/t_class_static_method.v | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index f4a35ce6d..af2a557c5 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1789,6 +1789,7 @@ private: } } else if (nodep->isIO() && !(VN_IS(nodep->dtypeSkipRefp(), BasicDType) + || VN_IS(nodep->dtypeSkipRefp(), ClassRefDType) || VN_IS(nodep->dtypeSkipRefp(), NodeArrayDType) || VN_IS(nodep->dtypeSkipRefp(), NodeUOrStructDType))) { nodep->v3warn(E_UNSUPPORTED, diff --git a/test_regress/t/t_class_new.v b/test_regress/t/t_class_new.v index ba1506312..811693dc5 100644 --- a/test_regress/t/t_class_new.v +++ b/test_regress/t/t_class_new.v @@ -19,6 +19,11 @@ class ClsArg; function int geta; return imembera; endfunction + static function ClsArg create6; + ClsArg obj; + obj = new(6 - 1); + return obj; + endfunction endclass module t (/*AUTOARG*/); @@ -33,6 +38,10 @@ module t (/*AUTOARG*/); if (c2.imembera != 3) $stop; if (c2.geta() != 3) $stop; + c2 = ClsArg::create6(); + if (c2.imembera != 6) $stop; + if (c2.geta() != 6) $stop; + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_class_static_method.v b/test_regress/t/t_class_static_method.v index 1d408aaef..5b518afb3 100644 --- a/test_regress/t/t_class_static_method.v +++ b/test_regress/t/t_class_static_method.v @@ -16,17 +16,34 @@ class Cls; if (x != 23) $stop; return 42; endfunction - endclass : Cls +class OCls; + int i; + static function OCls create(); + OCls o = new; + o.i = 42; + return o; + endfunction + static task test_obj(OCls o); + if (o.i != 42) $stop; + endtask +endclass + module t (/*AUTOARG*/); initial begin int x; + OCls oc; + Cls::static_task(16); x = Cls::static_function(23); $write("Static function result: %d\n", x); if (x != 42) $stop; + + oc = OCls::create(); + OCls::test_obj(oc); + $write("*-* All Finished *-*\n"); $finish; end From 9a9931fb9d8e899c7eb1c8cb4d27c39df60b54c5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 13:46:14 -0500 Subject: [PATCH 71/91] Support complex function arguments. --- Changes | 8 ++-- include/verilated_heavy.h | 2 + src/V3AstNodes.h | 21 +++++----- src/V3Width.cpp | 15 ++----- test_regress/t/t_func_complex.pl | 21 ++++++++++ test_regress/t/t_func_complex.v | 54 ++++++++++++++++++++++++++ test_regress/t/t_func_complex_noinl.pl | 24 ++++++++++++ test_regress/t/t_func_refio_bad.out | 5 +++ test_regress/t/t_func_refio_bad.pl | 19 +++++++++ test_regress/t/t_func_refio_bad.v | 18 +++++++++ 10 files changed, 163 insertions(+), 24 deletions(-) create mode 100755 test_regress/t/t_func_complex.pl create mode 100644 test_regress/t/t_func_complex.v create mode 100755 test_regress/t/t_func_complex_noinl.pl create mode 100644 test_regress/t/t_func_refio_bad.out create mode 100755 test_regress/t/t_func_refio_bad.pl create mode 100644 test_regress/t/t_func_refio_bad.v diff --git a/Changes b/Changes index e740aff86..b2a3a5f9b 100644 --- a/Changes +++ b/Changes @@ -5,16 +5,18 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.105 devel -*** Change -sv option to select 1800-2017 instead of 1800-2005. +** Change -sv option to select 1800-2017 instead of 1800-2005. + +*** Check for proper 'local' and 'protected' (#2228). *** Support $random and $urandom seeds. +*** Support complex function arguments. + *** Support 'super'. *** Support 'with item.index'. -*** Check for proper 'local' and 'protected' (#2228). - **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] **** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index f6cb8dd71..0fd47d274 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -154,6 +154,7 @@ public: // METHODS T_Value& atDefault() { return m_defaultValue; } + const T_Value& atDefault() const { return m_defaultValue; } const Deque& privateDeque() const { return m_deque; } // Size. Verilog: function int size(), or int num() @@ -512,6 +513,7 @@ public: // METHODS T_Value& atDefault() { return m_defaultValue; } + const T_Value& atDefault() const { return m_defaultValue; } // Size of array. Verilog: function int size(), or int num() int size() const { return m_map.size(); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 09d1cdc91..38fa9d26d 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -395,7 +395,8 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } virtual bool similarDType(AstNodeDType* samep) const override { const AstParamTypeDType* sp = static_cast(samep); - return (sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp())); + return type() == samep->type() && sp + && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()); } virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } @@ -545,8 +546,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual string prettyDTypeName() const override; virtual void dumpSmall(std::ostream& str) const override; @@ -643,8 +644,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual string prettyDTypeName() const override; virtual void dumpSmall(std::ostream& str) const override; @@ -753,8 +754,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual void dumpSmall(std::ostream& str) const override; virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } @@ -1013,7 +1014,7 @@ public: return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep); } virtual bool similarDType(AstNodeDType* samep) const override { - return this == samep || same(samep); + return this == samep || (type() == samep->type() && same(samep)); } virtual V3Hash sameHash() const override { return V3Hash(V3Hash(m_classp), V3Hash(m_classOrPackagep)); @@ -1127,8 +1128,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstQueueDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual void dumpSmall(std::ostream& str) const override; virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index af2a557c5..edba6166d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1787,13 +1787,6 @@ private: nodep->dtypep(newp); v3Global.rootp()->typeTablep()->addTypesp(newp); } - } else if (nodep->isIO() - && !(VN_IS(nodep->dtypeSkipRefp(), BasicDType) - || VN_IS(nodep->dtypeSkipRefp(), ClassRefDType) - || VN_IS(nodep->dtypeSkipRefp(), NodeArrayDType) - || VN_IS(nodep->dtypeSkipRefp(), NodeUOrStructDType))) { - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: Inputs and outputs must be simple data types"); } if (VN_IS(nodep->dtypep()->skipRefToConstp(), ConstDType)) nodep->isConst(true); // Parameters if implicit untyped inherit from what they are assigned to @@ -1999,7 +1992,7 @@ private: } virtual void visit(AstConsAssoc* nodep) override { // Type computed when constructed here - auto* vdtypep = VN_CAST(m_vup->dtypep(), AssocArrayDType); + auto* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), AssocArrayDType); UASSERT_OBJ(vdtypep, nodep, "ConsAssoc requires assoc upper parent data type"); if (m_vup->prelim()) { nodep->dtypeFrom(vdtypep); @@ -2011,7 +2004,7 @@ private: } virtual void visit(AstSetAssoc* nodep) override { // Type computed when constructed here - auto* vdtypep = VN_CAST(m_vup->dtypep(), AssocArrayDType); + auto* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), AssocArrayDType); UASSERT_OBJ(vdtypep, nodep, "SetsAssoc requires assoc upper parent data type"); if (m_vup->prelim()) { nodep->dtypeFrom(vdtypep); @@ -2024,7 +2017,7 @@ private: } virtual void visit(AstConsDynArray* nodep) override { // Type computed when constructed here - AstDynArrayDType* vdtypep = VN_CAST(m_vup->dtypep(), DynArrayDType); + AstDynArrayDType* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), DynArrayDType); UASSERT_OBJ(vdtypep, nodep, "ConsDynArray requires queue upper parent data type"); if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(vdtypep, PRELIM).p()); @@ -2056,7 +2049,7 @@ private: } virtual void visit(AstConsQueue* nodep) override { // Type computed when constructed here - AstQueueDType* vdtypep = VN_CAST(m_vup->dtypep(), QueueDType); + AstQueueDType* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), QueueDType); UASSERT_OBJ(vdtypep, nodep, "ConsQueue requires queue upper parent data type"); if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(vdtypep, PRELIM).p()); diff --git a/test_regress/t/t_func_complex.pl b/test_regress/t/t_func_complex.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_func_complex.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_func_complex.v b/test_regress/t/t_func_complex.v new file mode 100644 index 000000000..142088d35 --- /dev/null +++ b/test_regress/t/t_func_complex.v @@ -0,0 +1,54 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(); + typedef integer q_t[$]; + + function void queue_set(ref q_t q); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + q.push_back(42); + endfunction + + function void queue_check_nref(q_t q); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + q[0] = 11; + if (q[0] != 11) $stop; + endfunction + + function void queue_check_ref(const ref q_t q); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + if (q[0] != 42) $stop; + endfunction + + function q_t queue_ret(); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + queue_ret = '{101}; + endfunction + + initial begin + q_t iq; + queue_set(iq); + queue_check_ref(iq); + + iq[0] = 44; + queue_check_nref(iq); + if (iq[0] != 44) $stop; + + iq = queue_ret(); + if (iq[0] != 101) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_func_complex_noinl.pl b/test_regress/t/t_func_complex_noinl.pl new file mode 100755 index 000000000..e7a493593 --- /dev/null +++ b/test_regress/t/t_func_complex_noinl.pl @@ -0,0 +1,24 @@ +#!/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 + +top_filename("t/t_func_complex.v"); + +scenarios(simulator => 1); + +compile( + v_flags2 => ["+define+TEST_NOINLINE"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_refio_bad.out b/test_regress/t/t_func_refio_bad.out new file mode 100644 index 000000000..7d92bd42a --- /dev/null +++ b/test_regress/t/t_func_refio_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_func_refio_bad.v:16:17: Ref argument requires matching types; port 'q' requires VAR 'q' but connection is CONST '?32?sh2a'. + : ... In instance t + 16 | queue_set(42); + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_func_refio_bad.pl b/test_regress/t/t_func_refio_bad.pl new file mode 100755 index 000000000..59ba0d6c6 --- /dev/null +++ b/test_regress/t/t_func_refio_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +lint( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_refio_bad.v b/test_regress/t/t_func_refio_bad.v new file mode 100644 index 000000000..dc117ac4f --- /dev/null +++ b/test_regress/t/t_func_refio_bad.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(); + typedef integer q_t[$]; + + function void queue_set(ref q_t q); + q.push_back(42); + endfunction + + initial begin + q_t iq; + queue_set(42); // 42 is bad, meant iq + end +endmodule From ff262fc4fbfa68127d44fadf6cb2402413d25580 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 17:29:21 -0500 Subject: [PATCH 72/91] Support type(t) static casting --- src/verilog.y | 2 ++ test_regress/t/t_type.v | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/verilog.y b/src/verilog.y index e77ea9086..7026be4bd 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -4219,6 +4219,8 @@ expr: // IEEE: part of expression/constant_expression/primary // // IEEE: cast/constant_cast // // expanded from casting_type | simple_type yP_TICK '(' expr ')' { $$ = new AstCast($1->fileline(), $4, $1); } + | yTYPE '(' exprOrDataType ')' yP_TICK '(' expr ')' + { $$ = new AstCast($1, $7, new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3)); } | ySIGNED yP_TICK '(' expr ')' { $$ = new AstSigned($1, $4); } | yUNSIGNED yP_TICK '(' expr ')' { $$ = new AstUnsigned($1, $4); } | ySTRING yP_TICK '(' expr ')' { $$ = new AstCvtPackString($1, $4); } diff --git a/test_regress/t/t_type.v b/test_regress/t/t_type.v index bb8bd852a..ce40dee79 100644 --- a/test_regress/t/t_type.v +++ b/test_regress/t/t_type.v @@ -15,6 +15,8 @@ module t(/*AUTOARG*/); y = 2.3; z = x + y; if (z != (1.2+2.3)) $stop; + z = type(z)'(22); + if (z != 22.0) $stop; $write("*-* All Finished *-*\n"); $finish; end From e09f039a366288b382e59c582a9f3aa031e23750 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 21:43:37 -0500 Subject: [PATCH 73/91] Internals: Remove dead code. No functional change. --- src/V3Ast.h | 24 +++++++++--------------- src/V3AstNodes.cpp | 2 -- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index e8436767c..a6649441d 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -450,7 +450,6 @@ public: LONGINT, DOUBLE, SHORTINT, - FLOAT, TIME, // Closer to a class type, but limited usage STRING, @@ -468,18 +467,16 @@ public: enum en m_e; const char* ascii() const { static const char* const names[] = { - "%E-unk", // - "bit", "byte", "chandle", "event", "int", "integer", "logic", - "longint", "real", "shortint", "shortreal", "time", "string", "VerilatedScope*", - "char*", "IData", "QData", "LOGIC_IMPLICIT", " MAX"}; + "%E-unk", "bit", "byte", "chandle", "event", "int", "integer", + "logic", "longint", "real", "shortint", "time", "string", "VerilatedScope*", + "char*", "IData", "QData", "LOGIC_IMPLICIT", " MAX"}; return names[m_e]; } const char* dpiType() const { static const char* const names[] - = {"%E-unk", // - "svBit", "char", "void*", "char", "int", "%E-integer", - "svLogic", "long long", "double", "short", "float", "%E-time", - "const char*", "dpiScope", "const char*", "IData", "QData", "%E-logic-implicit", + = {"%E-unk", "svBit", "char", "void*", "char", "int", + "%E-integer", "svLogic", "long long", "double", "short", "%E-time", + "const char*", "dpiScope", "const char*", "IData", "QData", "%E-logic-implicit", " MAX"}; return names[m_e]; } @@ -508,7 +505,6 @@ public: case LOGIC: return 1; // scalar, can't bit extract unless ranged case LONGINT: return 64; case DOUBLE: return 64; // opaque - case FLOAT: return 32; // opaque case SHORTINT: return 16; case TIME: return 64; case STRING: return 64; // opaque // Just the pointer, for today @@ -521,7 +517,7 @@ public: } bool isSigned() const { return m_e == BYTE || m_e == SHORTINT || m_e == INT || m_e == LONGINT || m_e == INTEGER - || m_e == DOUBLE || m_e == FLOAT; + || m_e == DOUBLE; } bool isUnsigned() const { return m_e == CHANDLE || m_e == EVENTVALUE || m_e == STRING || m_e == SCOPEPTR @@ -532,8 +528,7 @@ public: } bool isZeroInit() const { // Otherwise initializes to X return (m_e == BIT || m_e == BYTE || m_e == CHANDLE || m_e == EVENTVALUE || m_e == INT - || m_e == LONGINT || m_e == SHORTINT || m_e == STRING || m_e == DOUBLE - || m_e == FLOAT); + || m_e == LONGINT || m_e == SHORTINT || m_e == STRING || m_e == DOUBLE); } bool isIntNumeric() const { // Enum increment supported return (m_e == BIT || m_e == BYTE || m_e == INT || m_e == INTEGER || m_e == LOGIC @@ -553,8 +548,7 @@ public: || m_e == DOUBLE || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64); } bool isOpaque() const { // IE not a simple number we can bit optimize - return (m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR || m_e == DOUBLE - || m_e == FLOAT); + return (m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR || m_e == DOUBLE); } bool isDouble() const { return m_e == DOUBLE; } bool isEventValue() const { return m_e == EVENTVALUE; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 9978297e5..241d91078 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -671,8 +671,6 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const { info.m_type = "const VerilatedScope*"; } else if (bdtypep->keyword() == AstBasicDTypeKwd::DOUBLE) { info.m_type = "double"; - } else if (bdtypep->keyword() == AstBasicDTypeKwd::FLOAT) { - info.m_type = "float"; } else if (bdtypep->keyword() == AstBasicDTypeKwd::STRING) { info.m_type = "std::string"; } else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width From aa360052a8e1093eee2102fdd7cb2ce816b39fcd Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 22:01:11 -0500 Subject: [PATCH 74/91] Internals: Code movement, no functional change. --- src/V3AstNodes.cpp | 6 ++++++ src/V3AstNodes.h | 3 +++ src/V3WidthCommit.h | 8 +------- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 241d91078..076d94669 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1171,6 +1171,12 @@ void AstClass::repairCache() { clearCache(); for (AstNode* itemp = membersp(); itemp; itemp = itemp->nextp()) { insertCache(itemp); } } +bool AstClass::isClassExtendedFrom(const AstClass* refClassp, const AstClass* baseClassp) { + // TAIL RECURSIVE + if (!refClassp || !baseClassp) return false; + if (refClassp == baseClassp) return true; + return isClassExtendedFrom(refClassp->extendsp()->classp(), baseClassp); +} void AstClass::dump(std::ostream& str) const { this->AstNode::dump(str); if (isExtended()) str << " [EXT]"; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 38fa9d26d..63f91c1a5 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -341,6 +341,9 @@ public: void isExtended(bool flag) { m_extended = flag; } bool isVirtual() const { return m_virtual; } void isVirtual(bool flag) { m_virtual = flag; } + // Return true if this class is an extension of base class (SLOW) + // Accepts nullptrs + static bool isClassExtendedFrom(const AstClass* refClassp, const AstClass* baseClassp); }; class AstClassExtends final : public AstNode { diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 52344c197..b84b5a110 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -133,7 +133,7 @@ private: const char* how = nullptr; if (local && defClassp && refClassp != defClassp) { how = "'local'"; - } else if (prot && defClassp && !classExtendedRecurse(refClassp, defClassp)) { + } else if (prot && defClassp && !AstClass::isClassExtendedFrom(refClassp, defClassp)) { how = "'protected'"; } if (how) { @@ -149,12 +149,6 @@ private: } } } - static bool classExtendedRecurse(const AstClass* refClassp, const AstClass* defClassp) { - // Return true if refClassp is an extends class of defClassp - if (!refClassp || !defClassp) return false; - if (refClassp == defClassp) return true; - return classExtendedRecurse(refClassp->extendsp()->classp(), defClassp); - } // VISITORS virtual void visit(AstNodeModule* nodep) override { From a54ac52a35e4781723f0b0be73cd1f13af022397 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 29 Nov 2020 08:23:36 -0500 Subject: [PATCH 75/91] Internals: Use 'Bit' where mean 2-state type. No functional change. --- src/V3Assert.cpp | 6 +-- src/V3AssertPre.cpp | 8 ++-- src/V3Ast.h | 4 +- src/V3AstNodes.h | 98 +++++++++++++++++++++++-------------------- src/V3Case.cpp | 11 +++-- src/V3Delayed.cpp | 4 +- src/V3LinkDot.cpp | 2 +- src/V3LinkResolve.cpp | 8 ++-- src/V3MergeCond.cpp | 9 ++-- src/V3Trace.cpp | 4 +- src/V3Unknown.cpp | 4 +- src/V3Width.cpp | 60 +++++++++++++------------- src/verilog.y | 12 +++--- 13 files changed, 117 insertions(+), 113 deletions(-) diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index dea371906..de633e7ef 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -73,7 +73,7 @@ private: // This allows syntax errors and such to be detected normally. (v3Global.opt.assertOn() ? static_cast(new AstCMath(fl, "Verilated::assertOn()", 1)) - : static_cast(new AstConst(fl, AstConst::LogicFalse()))), + : static_cast(new AstConst(fl, AstConst::BitFalse()))), nodep, nullptr); newp->user1(true); // Don't assert/cover this if return newp; @@ -207,7 +207,7 @@ private: bool allow_none = nodep->unique0Pragma(); // Empty case means no property - if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); + if (!propp) propp = new AstConst(nodep->fileline(), AstConst::BitFalse()); // Note: if this ends with an 'else', then we don't need to validate that one of the // predicates evaluates to true. @@ -276,7 +276,7 @@ private: } } // Empty case means no property - if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); + if (!propp) propp = new AstConst(nodep->fileline(), AstConst::BitFalse()); bool allow_none = has_default || nodep->unique0Pragma(); AstNode* ohot diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 59a89461a..727e0aafe 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -103,7 +103,7 @@ private: AstNode* past = new AstPast(fl, exprp, nullptr); past->dtypeFrom(exprp); exprp = new AstAnd(fl, past, new AstNot(fl, exprp->cloneTree(false))); - exprp->dtypeSetLogicBool(); + exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep)); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -122,7 +122,7 @@ private: AstNode* past = new AstPast(fl, exprp, nullptr); past->dtypeFrom(exprp); exprp = new AstAnd(fl, new AstNot(fl, past), exprp->cloneTree(false)); - exprp->dtypeSetLogicBool(); + exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep)); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -135,7 +135,7 @@ private: AstNode* past = new AstPast(fl, exprp, nullptr); past->dtypeFrom(exprp); exprp = new AstEq(fl, past, exprp->cloneTree(false)); - exprp->dtypeSetLogicBool(); + exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep)); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -153,7 +153,7 @@ private: AstNode* past = new AstPast(fl, lhsp, nullptr); past->dtypeFrom(lhsp); AstNode* exprp = new AstOr(fl, new AstNot(fl, past), rhsp); - exprp->dtypeSetLogicBool(); + exprp->dtypeSetBit(); nodep->replaceWith(exprp); nodep->sentreep(newSenTree(nodep)); VL_DO_DANGLING(pushDeletep(nodep), nodep); diff --git a/src/V3Ast.h b/src/V3Ast.h index a6649441d..969ea9da2 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1721,7 +1721,7 @@ public: void dtypeSetLogicSized(int width, VSigning numeric) { dtypep(findLogicDType(width, width, numeric)); // Since sized, widthMin is width } - void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); } + void dtypeSetBit() { dtypep(findBitDType()); } void dtypeSetDouble() { dtypep(findDoubleDType()); } void dtypeSetString() { dtypep(findStringDType()); } void dtypeSetSigned32() { dtypep(findSigned32DType()); } @@ -1730,7 +1730,7 @@ public: void dtypeSetVoid() { dtypep(findVoidDType()); } // Data type locators - AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); } + AstNodeDType* findBitDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); } AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); } AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); } AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 63f91c1a5..f93d968d7 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -140,17 +140,23 @@ public: , m_num(V3Number::String(), this, num) { dtypeSetString(); } - class LogicFalse {}; - AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, dtype should be a logic of size 1 + class BitFalse {}; + AstConst(FileLine* fl, BitFalse) // Shorthand const 0, dtype should be a logic of size 1 : ASTGEN_SUPER(fl) , m_num(this, 1, 0) { - dtypeSetLogicBool(); + dtypeSetBit(); } - class LogicTrue {}; - AstConst(FileLine* fl, LogicTrue) // Shorthand const 1, dtype should be a logic of size 1 + class BitTrue {}; + AstConst(FileLine* fl, BitTrue) // Shorthand const 1, dtype should be a logic of size 1 : ASTGEN_SUPER(fl) , m_num(this, 1, 1) { - dtypeSetLogicBool(); + dtypeSetBit(); + } + class BitTrueFalse {}; + AstConst(FileLine* fl, BitTrueFalse, bool on) + : ASTGEN_SUPER(fl) + , m_num(this, 1, on ? 1 : 0) { + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Const) virtual string name() const override { return num().ascii(); } // * = Value @@ -4822,7 +4828,7 @@ public: : ASTGEN_SUPER(fl) { addOp1p(exprp); addOp2p(itemsp); - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Inside) AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with @@ -5545,7 +5551,7 @@ class AstRedAnd final : public AstNodeUniop { public: AstRedAnd(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(RedAnd) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); } @@ -5559,7 +5565,7 @@ class AstRedOr final : public AstNodeUniop { public: AstRedOr(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(RedOr) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); } @@ -5573,7 +5579,7 @@ class AstRedXor final : public AstNodeUniop { public: AstRedXor(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(RedXor) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); } @@ -5592,7 +5598,7 @@ class AstRedXnor final : public AstNodeUniop { public: AstRedXnor(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(RedXnor) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXnor(lhs); } @@ -5626,7 +5632,7 @@ class AstLogNot final : public AstNodeUniop { public: AstLogNot(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LogNot) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); } @@ -5899,7 +5905,7 @@ class AstIsUnknown final : public AstNodeUniop { public: AstIsUnknown(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(IsUnknown) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { @@ -5916,7 +5922,7 @@ class AstIsUnbounded final : public AstNodeUniop { public: AstIsUnbounded(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(IsUnbounded) virtual void numberOperate(V3Number& out, const V3Number&) override { @@ -5934,7 +5940,7 @@ class AstOneHot final : public AstNodeUniop { public: AstOneHot(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(OneHot) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); } @@ -5950,7 +5956,7 @@ class AstOneHot0 final : public AstNodeUniop { public: AstOneHot0(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(OneHot0) virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); } @@ -6523,7 +6529,7 @@ class AstLogOr final : public AstNodeBiop { public: AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LogOr) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6546,7 +6552,7 @@ class AstLogAnd final : public AstNodeBiop { public: AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LogAnd) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6569,7 +6575,7 @@ class AstLogEq final : public AstNodeBiCom { public: AstLogEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LogEq) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6592,7 +6598,7 @@ class AstLogIf final : public AstNodeBiop { public: AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LogIf) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6703,7 +6709,7 @@ class AstEq final : public AstNodeBiCom { public: AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Eq) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6727,7 +6733,7 @@ class AstEqD final : public AstNodeBiCom { public: AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(EqD) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6751,7 +6757,7 @@ class AstEqN final : public AstNodeBiCom { public: AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(EqN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6775,7 +6781,7 @@ class AstNeq final : public AstNodeBiCom { public: AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Neq) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6797,7 +6803,7 @@ class AstNeqD final : public AstNodeBiCom { public: AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(NeqD) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6821,7 +6827,7 @@ class AstNeqN final : public AstNodeBiCom { public: AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(NeqN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6845,7 +6851,7 @@ class AstLt final : public AstNodeBiop { public: AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Lt) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6867,7 +6873,7 @@ class AstLtD final : public AstNodeBiop { public: AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LtD) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6891,7 +6897,7 @@ class AstLtS final : public AstNodeBiop { public: AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LtS) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6914,7 +6920,7 @@ class AstLtN final : public AstNodeBiop { public: AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LtN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6938,7 +6944,7 @@ class AstGt final : public AstNodeBiop { public: AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Gt) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6960,7 +6966,7 @@ class AstGtD final : public AstNodeBiop { public: AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(GtD) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -6984,7 +6990,7 @@ class AstGtS final : public AstNodeBiop { public: AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(GtS) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7007,7 +7013,7 @@ class AstGtN final : public AstNodeBiop { public: AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(GtN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7031,7 +7037,7 @@ class AstGte final : public AstNodeBiop { public: AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Gte) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7055,7 +7061,7 @@ class AstGteD final : public AstNodeBiop { public: AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(GteD) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7079,7 +7085,7 @@ class AstGteS final : public AstNodeBiop { public: AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(GteS) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7102,7 +7108,7 @@ class AstGteN final : public AstNodeBiop { public: AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(GteN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7126,7 +7132,7 @@ class AstLte final : public AstNodeBiop { public: AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(Lte) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7150,7 +7156,7 @@ class AstLteD final : public AstNodeBiop { public: AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LteD) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7174,7 +7180,7 @@ class AstLteS final : public AstNodeBiop { public: AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LteS) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7197,7 +7203,7 @@ class AstLteN final : public AstNodeBiop { public: AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(LteN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7794,7 +7800,7 @@ class AstEqCase final : public AstNodeBiCom { public: AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(EqCase) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7816,7 +7822,7 @@ class AstNeqCase final : public AstNodeBiCom { public: AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(NeqCase) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7839,7 +7845,7 @@ class AstEqWild final : public AstNodeBiop { public: AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(EqWild) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -7863,7 +7869,7 @@ class AstNeqWild final : public AstNodeBiop { public: AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - dtypeSetLogicBool(); + dtypeSetBit(); } ASTNODE_NODE_FUNCS(NeqWild) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 3b36aa6ba..06ece071c 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -318,7 +318,7 @@ private: itemp = VN_CAST(itemp->nextp(), CaseItem)) { if (!itemp->condsp()) { // Default clause. Just make true, we'll optimize it away later - itemp->condsp(new AstConst(itemp->fileline(), AstConst::LogicTrue())); + itemp->condsp(new AstConst(itemp->fileline(), AstConst::BitTrue())); hadDefault = true; } else { // Expressioned clause @@ -336,7 +336,7 @@ private: VL_DANGLING(iconstp); // For simplicity, make expression that is not equal, and let later // optimizations remove it - condp = new AstConst(itemp->fileline(), AstConst::LogicFalse()); + condp = new AstConst(itemp->fileline(), AstConst::BitFalse()); } else if (AstInsideRange* irangep = VN_CAST(icondp, InsideRange)) { // Similar logic in V3Width::visit(AstInside) condp = irangep->newAndFromInside(cexprp, irangep->lhsp()->unlinkFrBack(), @@ -375,9 +375,8 @@ private: if (!hadDefault) { // If there was no default, add a empty one, this greatly simplifies below code // and constant propagation will just eliminate it for us later. - nodep->addItemsp( - new AstCaseItem(nodep->fileline(), - new AstConst(nodep->fileline(), AstConst::LogicTrue()), nullptr)); + nodep->addItemsp(new AstCaseItem( + nodep->fileline(), new AstConst(nodep->fileline(), AstConst::BitTrue()), nullptr)); } if (debug() >= 9) nodep->dumpTree(cout, " _comp_COND: "); // Now build the IF statement tree @@ -419,7 +418,7 @@ private: VL_DANGLING(ifexprp); if (depth == CASE_ENCODER_GROUP_DEPTH) { // End of group - can skip the condition VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp); - itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue()); + itemexprp = new AstConst(itemp->fileline(), AstConst::BitTrue()); } AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, nullptr); if (itemnextp) { diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 096dbe912..60888600e 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -289,7 +289,7 @@ private: new AstConst(nodep->fileline(), 0)); AstAssign* setassignp = new AstAssign( nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, VAccess::WRITE), - new AstConst(nodep->fileline(), AstConst::LogicTrue())); + new AstConst(nodep->fileline(), AstConst::BitTrue())); nodep->addNextHere(setassignp); } if (m_nextDlyp) { // Tell next assigndly it can share the variable @@ -436,7 +436,7 @@ private: prep = new AstAssignPre( nodep->fileline(), new AstVarRef(nodep->fileline(), dlyvscp, VAccess::WRITE), - new AstConst(nodep->fileline(), AstConst::LogicFalse())); + new AstConst(nodep->fileline(), AstConst::BitFalse())); } else { prep = new AstAssignPre( nodep->fileline(), diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 23f600284..c82b3dba5 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2099,7 +2099,7 @@ private: if (start) { AstNode* newp; if (m_ds.m_dotErr) { - newp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); + newp = new AstConst(nodep->fileline(), AstConst::BitFalse()); } else { // RHS is what we're left with newp = nodep->rhsp()->unlinkFrBack(); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 8734e2532..9d8ba6828 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -472,10 +472,10 @@ private: } varoutp = varp; // Tie off - m_modp->addStmtp(new AstAssignW( - varp->fileline(), - new AstVarRef(varp->fileline(), varp, VAccess::WRITE), - new AstConst(varp->fileline(), AstConst::LogicFalse()))); + m_modp->addStmtp( + new AstAssignW(varp->fileline(), + new AstVarRef(varp->fileline(), varp, VAccess::WRITE), + new AstConst(varp->fileline(), AstConst::BitFalse()))); } else { varp->v3error("Only inputs and outputs are allowed in udp modules"); } diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index 73742a3be..d0d23b7bc 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -161,7 +161,7 @@ private: // rarely required (only when trying to merge a "cond & value" with an // earlier ternary), we will just always mask it for safety. AstNode* maskLsb(AstNode* nodep) { - AstNode* const maskp = new AstConst(nodep->fileline(), AstConst::LogicTrue()); + AstNode* const maskp = new AstConst(nodep->fileline(), AstConst::BitTrue()); return new AstAnd(nodep->fileline(), nodep, maskp); } @@ -170,8 +170,7 @@ private: // of the RHS is expected to be deleted by the caller. AstNode* foldAndUnlink(AstNode* rhsp, bool condTrue) { if (rhsp->sameTree(m_mgCondp)) { - return condTrue ? new AstConst(rhsp->fileline(), AstConst::LogicTrue()) - : new AstConst(rhsp->fileline(), AstConst::LogicFalse()); + return new AstConst(rhsp->fileline(), AstConst::BitTrueFalse(), condTrue); } else if (AstNodeCond* const condp = extractCond(rhsp)) { AstNode* const resp = condTrue ? condp->expr1p()->unlinkFrBack() : condp->expr2p()->unlinkFrBack(); @@ -183,12 +182,12 @@ private: } else if (AstAnd* const andp = VN_CAST(rhsp, And)) { if (andp->lhsp()->sameTree(m_mgCondp)) { return condTrue ? maskLsb(andp->rhsp()->unlinkFrBack()) - : new AstConst(rhsp->fileline(), AstConst::LogicFalse()); + : new AstConst(rhsp->fileline(), AstConst::BitFalse()); } else { UASSERT_OBJ(andp->rhsp()->sameTree(m_mgCondp), rhsp, "AstAnd doesn't hold condition expression"); return condTrue ? maskLsb(andp->lhsp()->unlinkFrBack()) - : new AstConst(rhsp->fileline(), AstConst::LogicFalse()); + : new AstConst(rhsp->fileline(), AstConst::BitFalse()); } } rhsp->v3fatalSrc("Don't know how to fold expression"); diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 9a704175b..fcd5e7e03 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -426,7 +426,7 @@ private: void addActivitySetter(AstNode* insertp, uint32_t code) { FileLine* const fl = insertp->fileline(); AstAssign* const setterp = new AstAssign(fl, selectActivity(fl, code, VAccess::WRITE), - new AstConst(fl, AstConst::LogicTrue())); + new AstConst(fl, AstConst::BitTrue())); if (AstCCall* const callp = VN_CAST(insertp, CCall)) { callp->addNextHere(setterp); } else if (AstCFunc* const funcp = VN_CAST(insertp, CFunc)) { @@ -687,7 +687,7 @@ private: // Clear fine grained activity flags for (uint32_t i = 0; i < m_activityNumber; ++i) { AstNode* const clrp = new AstAssign(fl, selectActivity(fl, i, VAccess::WRITE), - new AstConst(fl, AstConst::LogicFalse())); + new AstConst(fl, AstConst::BitFalse())); cleanupFuncp->addStmtsp(clrp); } } diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 6c760998e..0c2dcc553 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -254,7 +254,7 @@ private: iterateChildren(nodep); // Ahh, we're two state, so this is easy UINFO(4, " ISUNKNOWN->0 " << nodep << endl); - AstConst* newp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); + AstConst* newp = new AstConst(nodep->fileline(), AstConst::BitFalse()); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -275,7 +275,7 @@ private: nonXp = nodep->fhsp(); else { // Was all X-s UINFO(4, " COUNTBITS('x)->0 " << nodep << endl); - AstConst* newp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); + AstConst* newp = new AstConst(nodep->fileline(), AstConst::BitFalse()); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); return; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index edba6166d..a781e4c87 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -794,7 +794,7 @@ private: AstConst* widthConstp = VN_CAST(nodep->widthp(), Const); if (!widthConstp) { nodep->v3error("Width of bit extract isn't a constant"); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); return; } int width = nodep->widthConst(); @@ -1085,7 +1085,7 @@ private: virtual void visit(AstFell* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } virtual void visit(AstPast* nodep) override { @@ -1115,7 +1115,7 @@ private: virtual void visit(AstRose* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } @@ -1129,7 +1129,7 @@ private: virtual void visit(AstStable* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } @@ -1137,7 +1137,7 @@ private: if (m_vup->prelim()) { iterateCheckBool(nodep, "LHS", nodep->lhsp(), BOTH); iterateCheckBool(nodep, "RHS", nodep->rhsp(), BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } @@ -1182,7 +1182,7 @@ private: virtual void visit(AstIsUnbounded* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } virtual void visit(AstUCFunc* nodep) override { @@ -1567,7 +1567,7 @@ private: virtual void visit(AstRefDType* nodep) override { if (nodep->doingWidth()) { // Early exit if have circular parameter definition nodep->v3error("Typedef's type is circular: " << nodep->prettyName()); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); nodep->doingWidth(false); return; } @@ -1729,7 +1729,7 @@ private: if (!underDtp) underDtp = underp->dtypep()->basicp(); if (!underDtp) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Size-changing cast on non-basic data type"); - underDtp = VN_CAST(nodep->findLogicBoolDType(), BasicDType); + underDtp = VN_CAST(nodep->findBitDType(), BasicDType); } UASSERT_OBJ(underp == nodep->op1p(), nodep, "Assuming op1 is cast value"); // A cast propagates its size to the lower expression and is included in the maximum @@ -1770,7 +1770,7 @@ private: UASSERT_OBJ(nodep->valuep(), nodep, "circular, but without value"); nodep->v3error("Variable's initial value is circular: " << nodep->prettyNameQ()); pushDeletep(nodep->valuep()->unlinkFrBack()); - nodep->valuep(new AstConst(nodep->fileline(), AstConst::LogicTrue())); + nodep->valuep(new AstConst(nodep->fileline(), AstConst::BitTrue())); nodep->dtypeFrom(nodep->valuep()); nodep->didWidth(true); return; @@ -2116,7 +2116,7 @@ private: for (AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) { iterateCheck(nodep, "Inside Item", itemp, CONTEXT, FINAL, subDTypep, EXTEND_EXP); } - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); if (debug() >= 9) nodep->dumpTree(cout, "-inside-in: "); // Now rip out the inside and replace with simple math AstNode* newp = nullptr; @@ -2140,7 +2140,7 @@ private: newp = inewp; } } - if (!newp) newp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); + if (!newp) newp = new AstConst(nodep->fileline(), AstConst::BitFalse()); if (debug() >= 9) newp->dumpTree(cout, "-inside-out: "); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -2270,7 +2270,7 @@ private: << nodep->fromp()->dtypep()->prettyTypeName() << "'"); } // Error handling - nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::LogicFalse())); + nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::BitFalse())); VL_DO_DANGLING(pushDeletep(nodep), nodep); } AstNode* memberSelClass(AstMemberSel* nodep, AstClassRefDType* adtypep) { @@ -2590,7 +2590,7 @@ private: if (!nodep->firstAbovep()) newp->makeStatement(); } else if (nodep->name() == "find" || nodep->name() == "find_first" || nodep->name() == "find_last") { - AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), + AstWith* withp = methodWithArgument(nodep, true, false, nodep->findBitDType(), adtypep->keyDTypep(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); @@ -2600,7 +2600,7 @@ private: if (!nodep->firstAbovep()) newp->makeStatement(); } else if (nodep->name() == "find_index" || nodep->name() == "find_first_index" || nodep->name() == "find_last_index") { - AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), + AstWith* withp = methodWithArgument(nodep, true, false, nodep->findBitDType(), adtypep->keyDTypep(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); @@ -2695,7 +2695,7 @@ private: if (!nodep->firstAbovep()) newp->makeStatement(); } else if (nodep->name() == "find" || nodep->name() == "find_first" || nodep->name() == "find_last" || nodep->name() == "find_index") { - AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), + AstWith* withp = methodWithArgument(nodep, true, false, nodep->findBitDType(), nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); @@ -2705,7 +2705,7 @@ private: if (!nodep->firstAbovep()) newp->makeStatement(); } else if (nodep->name() == "find_index" || nodep->name() == "find_first_index" || nodep->name() == "find_last_index") { - AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), + AstWith* withp = methodWithArgument(nodep, true, false, nodep->findBitDType(), nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); @@ -2827,7 +2827,7 @@ private: if (!nodep->firstAbovep()) newp->makeStatement(); } else if (nodep->name() == "find" || nodep->name() == "find_first" || nodep->name() == "find_last") { - AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), + AstWith* withp = methodWithArgument(nodep, true, false, nodep->findBitDType(), nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); @@ -2837,7 +2837,7 @@ private: if (!nodep->firstAbovep()) newp->makeStatement(); } else if (nodep->name() == "find_index" || nodep->name() == "find_first_index" || nodep->name() == "find_last_index") { - AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(), + AstWith* withp = methodWithArgument(nodep, true, false, nodep->findBitDType(), nodep->findUInt32DType(), adtypep->subDTypep()); methodOkArguments(nodep, 0, 0); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); @@ -3453,7 +3453,7 @@ private: } if (patp) { // Determine initial values - vdtypep = nodep->findLogicBoolDType(); + vdtypep = nodep->findBitDType(); patp->dtypep(vdtypep); AstNode* valuep = patternMemberValueIterate(patp); { // Packed. Convert to concat for now. @@ -3537,7 +3537,7 @@ private: iterateCheckBool(nodep, "Disable", nodep->disablep(), BOTH); // it's like an if() condition. } - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } @@ -4184,7 +4184,7 @@ private: if (nodep->didWidth()) return; if (nodep->doingWidth()) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Recursive function or task call"); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); nodep->didWidth(true); return; } @@ -4539,7 +4539,7 @@ private: UASSERT_OBJ(!nodep->op2p(), nodep, "For unary ops only!"); if (m_vup->prelim()) { iterateCheckBool(nodep, "LHS", nodep->op1p(), BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } void visit_log_and_or(AstNodeBiop* nodep) { @@ -4551,7 +4551,7 @@ private: if (m_vup->prelim()) { iterateCheckBool(nodep, "LHS", nodep->lhsp(), BOTH); iterateCheckBool(nodep, "RHS", nodep->rhsp(), BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } void visit_red_and_or(AstNodeUniop* nodep) { @@ -4563,7 +4563,7 @@ private: // Sign: unsigned out (11.8.1) if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } void visit_red_unknown(AstNodeUniop* nodep) { @@ -4575,7 +4575,7 @@ private: // Sign: unsigned out (11.8.1) if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } @@ -4638,7 +4638,7 @@ private: iterateCheck(nodep, "RHS", nodep->rhsp(), CONTEXT, FINAL, subDTypep, (signedFl ? EXTEND_LHS : EXTEND_ZERO), warnOn); } - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } void visit_cmp_real(AstNodeBiop* nodep) { @@ -4653,7 +4653,7 @@ private: // See similar handling in visit_cmp_eq_gt where created iterateCheckReal(nodep, "LHS", nodep->lhsp(), BOTH); iterateCheckReal(nodep, "RHS", nodep->rhsp(), BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } void visit_cmp_string(AstNodeBiop* nodep) { @@ -4666,7 +4666,7 @@ private: // See similar handling in visit_cmp_eq_gt where created iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); iterateCheckString(nodep, "RHS", nodep->rhsp(), BOTH); - nodep->dtypeSetLogicBool(); + nodep->dtypeSetBit(); } } @@ -5181,10 +5181,10 @@ private: nodep->v3error("Logical operator " << nodep->prettyTypeName() << " expects a non-complex data type on the " << side << "."); - underp->replaceWith(new AstConst(nodep->fileline(), AstConst::LogicFalse())); + underp->replaceWith(new AstConst(nodep->fileline(), AstConst::BitFalse())); VL_DO_DANGLING(pushDeletep(underp), underp); } else { - bool bad = widthBad(underp, nodep->findLogicBoolDType()); + bool bad = widthBad(underp, nodep->findBitDType()); if (bad) { { // if (warnOn), but not needed here if (debug() > 4) nodep->backp()->dumpTree(cout, " back: "); diff --git a/src/verilog.y b/src/verilog.y index 7026be4bd..31bd79457 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3114,14 +3114,14 @@ statement_item: // IEEE: statement_item | yP_MINUSGT idDotted/*hierarchical_identifier-event*/ ';' { // AssignDly because we don't have stratified queue, and need to // read events, clear next event, THEN apply this set - $$ = new AstAssignDly($1, $2, new AstConst($1, AstConst::LogicTrue())); } + $$ = new AstAssignDly($1, $2, new AstConst($1, AstConst::BitTrue())); } //UNSUP yP_MINUSGTGT delay_or_event_controlE hierarchical_identifier/*event*/ ';' { UNSUP } // // IEEE remove below | yP_MINUSGTGT delayE idDotted/*hierarchical_identifier-event*/ ';' - { $$ = new AstAssignDly($1, $3, new AstConst($1, AstConst::LogicTrue())); } + { $$ = new AstAssignDly($1, $3, new AstConst($1, AstConst::BitTrue())); } // // // IEEE: loop_statement - | yFOREVER stmtBlock { $$ = new AstWhile($1,new AstConst($1,AstConst::LogicTrue()),$2); } + | yFOREVER stmtBlock { $$ = new AstWhile($1,new AstConst($1, AstConst::BitTrue()), $2); } | yREPEAT '(' expr ')' stmtBlock { $$ = new AstRepeat($1,$3,$5);} | yWHILE '(' expr ')' stmtBlock { $$ = new AstWhile($1,$3,$5);} // // for's first ';' is in for_initialization @@ -3179,7 +3179,7 @@ statementFor: // IEEE: part of statement $$->addStmtsp(new AstWhile($1, $4,$8,$6)); } | yFOR '(' for_initialization ';' for_stepE ')' stmtBlock { $$ = new AstBegin($1, "", $3, false, true); - $$->addStmtsp(new AstWhile($1, new AstConst($1,AstConst::LogicTrue()),$7,$5)); } + $$->addStmtsp(new AstWhile($1, new AstConst($1,AstConst::BitTrue()), $7, $5)); } ; statementVerilatorPragmas: @@ -4191,7 +4191,7 @@ expr: // IEEE: part of expression/constant_expression/primary // // IEEE: "... hierarchical_identifier select" see below // // // IEEE: empty_queue (IEEE 1800-2017 empty_unpacked_array_concatenation) - | '{' '}' { $$ = new AstConst($1, AstConst::LogicFalse()); + | '{' '}' { $$ = new AstConst($1, AstConst::BitFalse()); BBUNSUP($1, "Unsupported: empty queues (\"{ }\")"); } // // // IEEE: concatenation/constant_concatenation @@ -4250,7 +4250,7 @@ expr: // IEEE: part of expression/constant_expression/primary // // // IEEE: cond_predicate - here to avoid reduce problems // // Note expr includes cond_pattern - | ~l~expr yP_ANDANDAND ~r~expr { $$ = new AstConst($2, AstConst::LogicFalse()); + | ~l~expr yP_ANDANDAND ~r~expr { $$ = new AstConst($2, AstConst::BitFalse()); BBUNSUP($2, "Unsupported: &&& expression"); } // // // IEEE: cond_pattern - here to avoid reduce problems From aebb54444e6076d1745acf96e57118f7fd048b5c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 29 Nov 2020 09:50:30 -0500 Subject: [PATCH 76/91] Internals: Favor NodeProcedure. No functional change intended. --- src/V3Clock.cpp | 11 +---------- src/V3Gate.cpp | 7 ++----- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index ecb1f939b..31128c4f7 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -293,7 +293,7 @@ private: } m_scopep = nullptr; } - virtual void visit(AstAlways* nodep) override { + virtual void visit(AstNodeProcedure* nodep) override { AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { @@ -328,15 +328,6 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstInitial* nodep) override { - AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); - nodep->replaceWith(cmtp); - if (AstNode* stmtsp = nodep->bodysp()) { - stmtsp->unlinkFrBackWithNext(); - cmtp->addNextHere(stmtsp); - } - VL_DO_DANGLING(nodep->deleteTree(), nodep); - } virtual void visit(AstCFunc* nodep) override { iterateChildren(nodep); // Link to global function diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 7049a14a4..c14bb648d 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -467,9 +467,6 @@ private: } } } - virtual void visit(AstAlways* nodep) override { - iterateNewStmt(nodep, (nodep->isJustOneBodyStmt() ? nullptr : "Multiple Stmts"), nullptr); - } virtual void visit(AstAlwaysPublic* nodep) override { VL_RESTORER(m_inSlow); { @@ -489,10 +486,10 @@ private: } m_inSenItem = false; } - virtual void visit(AstInitial* nodep) override { + virtual void visit(AstNodeProcedure* nodep) override { VL_RESTORER(m_inSlow); { - m_inSlow = true; + m_inSlow = VN_IS(nodep, Initial) || VN_IS(nodep, Final); iterateNewStmt(nodep, (nodep->isJustOneBodyStmt() ? nullptr : "Multiple Stmts"), nullptr); } From 67103d346b700ada4d182ed8181bd498c9152ef1 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 29 Nov 2020 10:53:44 -0500 Subject: [PATCH 77/91] Fix $fwriteh/$fwriteo --- src/verilog.y | 8 ++++---- test_regress/t/t_sys_file_basic.out | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/verilog.y b/src/verilog.y index 31bd79457..b56ea343f 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3596,10 +3596,10 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_FDISPLAYH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'h'); } | yD_FDISPLAYO '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'o'); } | yD_FDISPLAYO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'o'); } - | yD_FWRITE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5); } - | yD_FWRITEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'b'); } - | yD_FWRITEO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'h'); } - | yD_FWRITEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'o'); } + | yD_FWRITE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5); } + | yD_FWRITEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'b'); } + | yD_FWRITEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'h'); } + | yD_FWRITEO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'o'); } | yD_INFO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, nullptr, nullptr); } | yD_INFO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, nullptr, $3); } | yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, nullptr, nullptr); } diff --git a/test_regress/t/t_sys_file_basic.out b/test_regress/t/t_sys_file_basic.out index 7de722707..848109f37 100644 --- a/test_regress/t/t_sys_file_basic.out +++ b/test_regress/t/t_sys_file_basic.out @@ -2,9 +2,9 @@ [0] Hello2 d: 12 12 -h: 00000000014 0000000c +h: 0000000c 0000000c -o: 0000000c 00000000014 +o: 00000000014 00000000014 b: 00000000000000000000000000001100 00000000000000000000000000001100 From 665e8edaff70f1d3d3946b81aa8b8ada6fda92b7 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 29 Nov 2020 11:31:38 -0500 Subject: [PATCH 78/91] Support $monitor and $strobe. --- Changes | 2 + bin/verilator | 5 --- src/V3Active.cpp | 8 ++++ src/V3Assert.cpp | 74 ++++++++++++++++++++++++++++++- src/V3Ast.h | 17 +++++-- src/V3AstNodes.h | 42 ++++++++++++++---- src/V3Clock.cpp | 9 ++++ src/V3MergeCond.cpp | 2 +- src/V3Order.cpp | 9 +++- src/verilog.l | 20 ++++++++- src/verilog.y | 37 ++++++++++++++++ test_regress/t/t_sys_fmonitor.out | 15 +++++++ test_regress/t/t_sys_fmonitor.pl | 24 ++++++++++ test_regress/t/t_sys_fmonitor.v | 57 ++++++++++++++++++++++++ test_regress/t/t_sys_fstrobe.out | 6 +++ test_regress/t/t_sys_fstrobe.pl | 24 ++++++++++ test_regress/t/t_sys_fstrobe.v | 55 +++++++++++++++++++++++ test_regress/t/t_sys_monitor.out | 20 +++++++++ test_regress/t/t_sys_monitor.pl | 23 ++++++++++ test_regress/t/t_sys_monitor.v | 45 +++++++++++++++++++ test_regress/t/t_sys_strobe.out | 7 +++ test_regress/t/t_sys_strobe.pl | 23 ++++++++++ test_regress/t/t_sys_strobe.v | 46 +++++++++++++++++++ 23 files changed, 548 insertions(+), 22 deletions(-) create mode 100644 test_regress/t/t_sys_fmonitor.out create mode 100755 test_regress/t/t_sys_fmonitor.pl create mode 100644 test_regress/t/t_sys_fmonitor.v create mode 100644 test_regress/t/t_sys_fstrobe.out create mode 100755 test_regress/t/t_sys_fstrobe.pl create mode 100644 test_regress/t/t_sys_fstrobe.v create mode 100644 test_regress/t/t_sys_monitor.out create mode 100755 test_regress/t/t_sys_monitor.pl create mode 100644 test_regress/t/t_sys_monitor.v create mode 100644 test_regress/t/t_sys_strobe.out create mode 100755 test_regress/t/t_sys_strobe.pl create mode 100644 test_regress/t/t_sys_strobe.v diff --git a/Changes b/Changes index b2a3a5f9b..e2d2f61f4 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support $random and $urandom seeds. +*** Support $monitor and $strobe. + *** Support complex function arguments. *** Support 'super'. diff --git a/bin/verilator b/bin/verilator index ac88b8e2a..2df1ec7aa 100755 --- a/bin/verilator +++ b/bin/verilator @@ -4107,11 +4107,6 @@ $setup, $setuphold, $skew, $timeskew, $width All specify blocks and timing checks are ignored. -=item $monitor, $strobe - -Monitor and strobe are not supported, convert to always_comb $display or -similar. - =item $random, $urandom, $urandom_range Use +verilator+seed argument to set the seed if there is no $random or diff --git a/src/V3Active.cpp b/src/V3Active.cpp index c2ab0f7cd..50aa672c2 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -364,6 +364,14 @@ private: } visitAlways(nodep, nodep->sensesp(), nodep->keyword()); } + virtual void visit(AstAlwaysPostponed* nodep) override { + UINFO(4, " ALW " << nodep << endl); + if (!nodep->bodysp()) { + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + return; + } + visitAlways(nodep, nullptr, VAlwaysKwd::ALWAYS); + } virtual void visit(AstAlwaysPublic* nodep) override { // Move always to appropriate ACTIVE based on its sense list UINFO(4, " ALWPub " << nodep << endl); diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index de633e7ef..8af7193cc 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -36,7 +36,11 @@ private: // STATE AstNodeModule* m_modp = nullptr; // Last module AstBegin* m_beginp = nullptr; // Last begin + unsigned m_monitorNum = 0; // Global $monitor numbering (not per module) + AstVar* m_monitorNumVarp = nullptr; // $monitor number variable + AstVar* m_monitorOffVarp = nullptr; // $monitoroff variable unsigned m_modPastNum = 0; // Module past numbering + unsigned m_modStrobeNum = 0; // Module $strobe numbering VDouble0 m_statCover; // Statistic tracking VDouble0 m_statAsNotImm; // Statistic tracking VDouble0 m_statAsImm; // Statistic tracking @@ -62,7 +66,26 @@ private: nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline())); } } - + AstVarRef* newMonitorNumVarRefp(AstNode* nodep, VAccess access) { + if (!m_monitorNumVarp) { + m_monitorNumVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP, + "__VmonitorNum", nodep->findUInt64DType()}; + v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorNumVarp); + } + const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorNumVarp, access); + varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); + return varrefp; + } + AstVarRef* newMonitorOffVarRefp(AstNode* nodep, VAccess access) { + if (!m_monitorOffVarp) { + m_monitorOffVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP, + "__VmonitorOff", nodep->findBitDType()}; + v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorOffVarp); + } + const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorOffVarp, access); + varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); + return varrefp; + } AstNode* newIfAssertOn(AstNode* nodep) { // Add a internal if to check assertions are on. // Don't make this a AND term, as it's unlikely to need to test this. @@ -342,9 +365,54 @@ private: } else if (nodep->displayType() == AstDisplayType::DT_ERROR || nodep->displayType() == AstDisplayType::DT_FATAL) { replaceDisplay(nodep, "%%Error"); + } else if (nodep->displayType() == AstDisplayType::DT_MONITOR) { + nodep->displayType(AstDisplayType::DT_DISPLAY); + const auto fl = nodep->fileline(); + const auto monNum = ++m_monitorNum; + // Where $monitor was we do "__VmonitorNum = N;" + const auto newsetp = new AstAssign{fl, newMonitorNumVarRefp(nodep, VAccess::WRITE), + new AstConst{fl, monNum}}; + nodep->replaceWith(newsetp); + // Add "always_comb if (__VmonitorOn && __VmonitorNum==N) $display(...);" + AstNode* stmtsp = nodep; + AstIf* ifp = new AstIf{ + fl, + new AstLogAnd{fl, new AstLogNot{fl, newMonitorOffVarRefp(nodep, VAccess::READ)}, + new AstEq{fl, new AstConst{fl, monNum}, + newMonitorNumVarRefp(nodep, VAccess::READ)}}, + stmtsp, nullptr}; + ifp->branchPred(VBranchPred::BP_UNLIKELY); + AstNode* newp = new AstAlwaysPostponed{fl, ifp}; + m_modp->addStmtp(newp); + } else if (nodep->displayType() == AstDisplayType::DT_STROBE) { + nodep->displayType(AstDisplayType::DT_DISPLAY); + // Need one-shot + const auto fl = nodep->fileline(); + const auto varp + = new AstVar{fl, AstVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++), + nodep->findBitDType()}; + m_modp->addStmtp(varp); + // Where $strobe was we do "__Vstrobe = '1;" + const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, + new AstConst{fl, AstConst::BitTrue{}}}; + nodep->replaceWith(newsetp); + // Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end" + AstNode* stmtsp = nodep; + AstIf* ifp = new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp, nullptr}; + ifp->branchPred(VBranchPred::BP_UNLIKELY); + AstNode* newp = new AstAlwaysPostponed{fl, ifp}; + stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, + new AstConst{fl, AstConst::BitFalse{}}}); + m_modp->addStmtp(newp); } } - + virtual void visit(AstMonitorOff* nodep) override { + const auto newp + = new AstAssign(nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE), + new AstConst(nodep->fileline(), AstConst::BitTrue{}, nodep->off())); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } virtual void visit(AstAssert* nodep) override { iterateChildren(nodep); newPslAssertion(nodep, nodep->failsp()); @@ -362,9 +430,11 @@ private: virtual void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); VL_RESTORER(m_modPastNum); + VL_RESTORER(m_modStrobeNum); { m_modp = nodep; m_modPastNum = 0; + m_modStrobeNum = 0; iterateChildren(nodep); } } diff --git a/src/V3Ast.h b/src/V3Ast.h index 969ea9da2..90c54a434 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -879,12 +879,21 @@ inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == class AstDisplayType final { public: - enum en : uint8_t { DT_DISPLAY, DT_WRITE, DT_INFO, DT_ERROR, DT_WARNING, DT_FATAL }; + enum en : uint8_t { + DT_DISPLAY, + DT_WRITE, + DT_MONITOR, + DT_STROBE, + DT_INFO, + DT_ERROR, + DT_WARNING, + DT_FATAL + }; enum en m_e; - inline AstDisplayType() + AstDisplayType() : m_e{DT_DISPLAY} {} // cppcheck-suppress noExplicitConstructor - inline AstDisplayType(en _e) + AstDisplayType(en _e) : m_e{_e} {} explicit inline AstDisplayType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning @@ -893,7 +902,7 @@ public: bool needScopeTracking() const { return m_e != DT_DISPLAY && m_e != DT_WRITE; } const char* ascii() const { static const char* const names[] - = {"display", "write", "info", "error", "warning", "fatal"}; + = {"display", "write", "monitor", "strobe", "info", "error", "warning", "fatal"}; return names[m_e]; } }; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index f93d968d7..032cee3ee 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -146,16 +146,11 @@ public: , m_num(this, 1, 0) { dtypeSetBit(); } + // Shorthand const 1 (or with argument 0/1), dtype should be a logic of size 1 class BitTrue {}; - AstConst(FileLine* fl, BitTrue) // Shorthand const 1, dtype should be a logic of size 1 + AstConst(FileLine* fl, BitTrue, bool on = true) : ASTGEN_SUPER(fl) - , m_num(this, 1, 1) { - dtypeSetBit(); - } - class BitTrueFalse {}; - AstConst(FileLine* fl, BitTrueFalse, bool on) - : ASTGEN_SUPER(fl) - , m_num(this, 1, on ? 1 : 0) { + , m_num(this, 1, on) { dtypeSetBit(); } ASTNODE_NODE_FUNCS(Const) @@ -3296,6 +3291,14 @@ public: void sensesp(AstSenTree* nodep) { setOp1p(nodep); } VAlwaysKwd keyword() const { return m_keyword; } }; +class AstAlwaysPostponed final : public AstNodeProcedure { + // Like always but postponement scheduling region + +public: + AstAlwaysPostponed(FileLine* fl, AstNode* bodysp) + : ASTGEN_SUPER(fl, bodysp) {} + ASTNODE_NODE_FUNCS(AlwaysPostponed) +}; class AstAlwaysPublic final : public AstNodeStmt { // "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/ @@ -4282,6 +4285,29 @@ public: virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } }; +class AstMonitorOff final : public AstNodeStmt { + bool m_off; // Monitor off. Using 0=on allows faster init and comparison + +public: + AstMonitorOff(FileLine* fl, bool off) + : ASTGEN_SUPER(fl) + , m_off{off} {} + ASTNODE_NODE_FUNCS(MonitorOff) + virtual string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; } + virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt + virtual bool isPredictOptimizable() const override { + return false; + } // Though deleted before opt + virtual bool isPure() const override { return false; } // Though deleted before opt + virtual bool isOutputter() const override { return true; } // Though deleted before opt + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(m_off); } + virtual bool same(const AstNode* samep) const override { + return m_off == static_cast(samep)->m_off; + } + bool off() const { return m_off; } +}; + class AstSystemT final : public AstNodeStmt { // $system used as task public: diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 31128c4f7..e4a5da09f 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -311,6 +311,15 @@ private: } VL_DO_DANGLING(nodep->deleteTree(), nodep); } + virtual void visit(AstAlwaysPostponed* nodep) override { + AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); + nodep->replaceWith(cmtp); + if (AstNode* stmtsp = nodep->bodysp()) { + stmtsp->unlinkFrBackWithNext(); + cmtp->addNextHere(stmtsp); + } + VL_DO_DANGLING(nodep->deleteTree(), nodep); + } virtual void visit(AstCoverToggle* nodep) override { // nodep->dumpTree(cout, "ct:"); // COVERTOGGLE(INC, ORIG, CHANGE) -> diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index d0d23b7bc..771096200 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -170,7 +170,7 @@ private: // of the RHS is expected to be deleted by the caller. AstNode* foldAndUnlink(AstNode* rhsp, bool condTrue) { if (rhsp->sameTree(m_mgCondp)) { - return new AstConst(rhsp->fileline(), AstConst::BitTrueFalse(), condTrue); + return new AstConst(rhsp->fileline(), AstConst::BitTrue{}, condTrue); } else if (AstNodeCond* const condp = extractCond(rhsp)) { AstNode* const resp = condTrue ? condp->expr1p()->unlinkFrBack() : condp->expr2p()->unlinkFrBack(); diff --git a/src/V3Order.cpp b/src/V3Order.cpp index cca5359fe..4060c3c54 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -673,6 +673,7 @@ private: bool m_inClkAss = false; // Underneath AstAssign bool m_inPre = false; // Underneath AstAssignPre bool m_inPost = false; // Underneath AstAssignPost + bool m_inPostponed = false; // Underneath AstAssignPostponed OrderLogicVertex* m_activeSenVxp = nullptr; // Sensitivity vertex std::deque m_orderUserps; // All created OrderUser's for later deletion. // STATE... for inside process @@ -1044,7 +1045,8 @@ private: // We don't want to add extra edges if the logic block has many usages of same var bool gen = false; bool con = false; - if (nodep->access().isWriteOrRW()) gen = !(varscp->user4() & VU_GEN); + if (nodep->access().isWriteOrRW() && !m_inPostponed) + gen = !(varscp->user4() & VU_GEN); if (nodep->access().isReadOrRW()) { con = !(varscp->user4() & VU_CON); if ((varscp->user4() & VU_GEN) && !m_inClocked) { @@ -1174,6 +1176,11 @@ private: iterateNewStmt(nodep); m_inPost = false; } + virtual void visit(AstAlwaysPostponed* nodep) override { + VL_RESTORER(m_inPostponed); + m_inPostponed = true; + iterateNewStmt(nodep); + } virtual void visit(AstAlways* nodep) override { iterateNewStmt(nodep); } virtual void visit(AstAlwaysPublic* nodep) override { iterateNewStmt(nodep); } virtual void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); } diff --git a/src/verilog.l b/src/verilog.l index 0b7301475..422af9538 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -205,11 +205,19 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$fgets" { FL; return yD_FGETS; } "$finish" { FL; return yD_FINISH; } "$floor" { FL; return yD_FLOOR; } + "$fmonitor" { FL; return yD_FMONITOR; } + "$fmonitorb" { FL; return yD_FMONITORB; } + "$fmonitorh" { FL; return yD_FMONITORH; } + "$fmonitoro" { FL; return yD_FMONITORO; } "$fopen" { FL; return yD_FOPEN; } "$fread" { FL; return yD_FREAD; } "$frewind" { FL; return yD_FREWIND; } "$fscanf" { FL; return yD_FSCANF; } "$fseek" { FL; return yD_FSEEK; } + "$fstrobe" { FL; return yD_FSTROBE; } + "$fstrobeb" { FL; return yD_FSTROBEB; } + "$fstrobeh" { FL; return yD_FSTROBEH; } + "$fstrobeo" { FL; return yD_FSTROBEO; } "$ftell" { FL; return yD_FTELL; } "$fullskew" { FL; return yaTIMINGSPEC; } "$fwrite" { FL; return yD_FWRITE; } @@ -221,6 +229,12 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$itor" { FL; return yD_ITOR; } "$ln" { FL; return yD_LN; } "$log10" { FL; return yD_LOG10; } + "$monitor" { FL; return yD_MONITOR; } + "$monitorb" { FL; return yD_MONITORB; } + "$monitorh" { FL; return yD_MONITORH; } + "$monitoro" { FL; return yD_MONITORO; } + "$monitoroff" { FL; return yD_MONITOROFF; } + "$monitoron" { FL; return yD_MONITORON; } "$nochange" { FL; return yaTIMINGSPEC; } "$period" { FL; return yaTIMINGSPEC; } "$pow" { FL; return yD_POW; } @@ -248,6 +262,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$sscanf" { FL; return yD_SSCANF; } "$stime" { FL; return yD_STIME; } "$stop" { FL; return yD_STOP; } + "$strobe" { FL; return yD_STROBE; } + "$strobeb" { FL; return yD_STROBEB; } + "$strobeh" { FL; return yD_STROBEH; } + "$strobeo" { FL; return yD_STROBEO; } "$swrite" { FL; return yD_SWRITE; } "$swriteb" { FL; return yD_SWRITEB; } "$swriteh" { FL; return yD_SWRITEH; } @@ -268,9 +286,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$write" { FL; return yD_WRITE; } "$writeb" { FL; return yD_WRITEB; } "$writeh" { FL; return yD_WRITEH; } - "$writeo" { FL; return yD_WRITEO; } "$writememb" { FL; return yD_WRITEMEMB; } "$writememh" { FL; return yD_WRITEMEMH; } + "$writeo" { FL; return yD_WRITEO; } /* Keywords */ "always" { FL; return yALWAYS; } "and" { FL; return yAND; } diff --git a/src/verilog.y b/src/verilog.y index b56ea343f..fdace335b 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -740,11 +740,19 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yD_FGETS "$fgets" %token yD_FINISH "$finish" %token yD_FLOOR "$floor" +%token yD_FMONITOR "$fmonitor" +%token yD_FMONITORB "$fmonitorb" +%token yD_FMONITORH "$fmonitorh" +%token yD_FMONITORO "$fmonitoro" %token yD_FOPEN "$fopen" %token yD_FREAD "$fread" %token yD_FREWIND "$frewind" %token yD_FSCANF "$fscanf" %token yD_FSEEK "$fseek" +%token yD_FSTROBE "$fstrobe" +%token yD_FSTROBEB "$fstrobeb" +%token yD_FSTROBEH "$fstrobeh" +%token yD_FSTROBEO "$fstrobeo" %token yD_FTELL "$ftell" %token yD_FWRITE "$fwrite" %token yD_FWRITEB "$fwriteb" @@ -761,6 +769,12 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yD_LN "$ln" %token yD_LOG10 "$log10" %token yD_LOW "$low" +%token yD_MONITOR "$monitor" +%token yD_MONITORB "$monitorb" +%token yD_MONITORH "$monitorh" +%token yD_MONITORO "$monitoro" +%token yD_MONITOROFF "$monitoroff" +%token yD_MONITORON "$monitoron" %token yD_ONEHOT "$onehot" %token yD_ONEHOT0 "$onehot0" %token yD_PAST "$past" @@ -789,6 +803,10 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yD_STABLE "$stable" %token yD_STIME "$stime" %token yD_STOP "$stop" +%token yD_STROBE "$strobe" +%token yD_STROBEB "$strobeb" +%token yD_STROBEH "$strobeh" +%token yD_STROBEO "$strobeo" %token yD_SWRITE "$swrite" %token yD_SWRITEB "$swriteb" %token yD_SWRITEH "$swriteh" @@ -3580,6 +3598,14 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_DISPLAYH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'h'); } | yD_DISPLAYO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'o'); } | yD_DISPLAYO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'o'); } + | yD_MONITOR '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3); } + | yD_MONITORB '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'b'); } + | yD_MONITORH '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'h'); } + | yD_MONITORO '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'o'); } + | yD_STROBE '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3); } + | yD_STROBEB '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'b'); } + | yD_STROBEH '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'h'); } + | yD_STROBEO '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'o'); } | yD_WRITE parenE { $$ = nullptr; } // NOP | yD_WRITE '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3); } | yD_WRITEB parenE { $$ = nullptr; } // NOP @@ -3596,6 +3622,14 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_FDISPLAYH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'h'); } | yD_FDISPLAYO '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'o'); } | yD_FDISPLAYO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'o'); } + | yD_FMONITOR '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5); } + | yD_FMONITORB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'b'); } + | yD_FMONITORH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'h'); } + | yD_FMONITORO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'o'); } + | yD_FSTROBE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5); } + | yD_FSTROBEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'b'); } + | yD_FSTROBEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'h'); } + | yD_FSTROBEO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'o'); } | yD_FWRITE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5); } | yD_FWRITEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'b'); } | yD_FWRITEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'h'); } @@ -3610,6 +3644,9 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, nullptr); $$->addNext(new AstStop($1, false)); DEL($3); } | yD_FATAL '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, $5); $$->addNext(new AstStop($1, false)); DEL($3); } // + | yD_MONITOROFF parenE { $$ = new AstMonitorOff($1, true); } + | yD_MONITORON parenE { $$ = new AstMonitorOff($1, false); } + // | yD_PRINTTIMESCALE { $$ = new AstPrintTimeScale($1); } | yD_PRINTTIMESCALE '(' ')' { $$ = new AstPrintTimeScale($1); } | yD_PRINTTIMESCALE '(' idClassSel ')' { $$ = new AstPrintTimeScale($1); DEL($3); } diff --git a/test_regress/t/t_sys_fmonitor.out b/test_regress/t/t_sys_fmonitor.out new file mode 100644 index 000000000..4d75640c2 --- /dev/null +++ b/test_regress/t/t_sys_fmonitor.out @@ -0,0 +1,15 @@ +[110] cyc=11 also +[120] cyc=12 also +[130] cyc=13 also +[140] cyc=14 also +[150] cyc=15 also +[160] cyc=16 also +[170] cyc=17 also +00000000000000000000000000010010b +00000013h +00000000024o +00000000025o +00000000026o +[230] cyc=23 new-monitor +[240] cyc=24 new-monitor +[270] cyc=27 new-monitor diff --git a/test_regress/t/t_sys_fmonitor.pl b/test_regress/t/t_sys_fmonitor.pl new file mode 100755 index 000000000..6bbedacab --- /dev/null +++ b/test_regress/t/t_sys_fmonitor.pl @@ -0,0 +1,24 @@ +#!/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, + ); + +files_identical("$Self->{obj_dir}/open.log", $Self->{golden_filename}); + +ok(1); + +1; diff --git a/test_regress/t/t_sys_fmonitor.v b/test_regress/t/t_sys_fmonitor.v new file mode 100644 index 000000000..dd7f1329f --- /dev/null +++ b/test_regress/t/t_sys_fmonitor.v @@ -0,0 +1,57 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t(/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cyc = 0; + int fd; + + // Test loop + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + fd = $fopen({`STRINGIFY(`TEST_OBJ_DIR),"/open.log"}, "w"); + end + else if (cyc == 10) begin + $fmonitor(fd, "[%0t] cyc=%0d", $time, cyc); + $fmonitor(fd, "[%0t] cyc=%0d also", $time, cyc); + end + else if (cyc == 17) begin + $fmonitorb(fd, cyc, "b"); + end + else if (cyc == 18) begin + $fmonitorh(fd, cyc, "h"); + end + else if (cyc == 19) begin + $fmonitoro(fd, cyc, "o"); + end + else if (cyc == 22) begin + $fmonitor(fd, "[%0t] cyc=%0d new-monitor", $time, cyc); + end + else if (cyc == 24) begin + // IEEE suggests $monitoroff doesn't affect $fmonitor, but + // other simulators believe it does + $monitoroff; + end + else if (cyc == 26) begin + $monitoron; + end + else if (cyc == 27) begin + $fclose(fd); + end + else if (cyc == 30) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule diff --git a/test_regress/t/t_sys_fstrobe.out b/test_regress/t/t_sys_fstrobe.out new file mode 100644 index 000000000..7f9c034de --- /dev/null +++ b/test_regress/t/t_sys_fstrobe.out @@ -0,0 +1,6 @@ +[110] cyc=11 +[110] cyc=11 also +00000000000000000000000000010010b +00000013h +00000000024o +[230] cyc=23 new-strobe diff --git a/test_regress/t/t_sys_fstrobe.pl b/test_regress/t/t_sys_fstrobe.pl new file mode 100755 index 000000000..6bbedacab --- /dev/null +++ b/test_regress/t/t_sys_fstrobe.pl @@ -0,0 +1,24 @@ +#!/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, + ); + +files_identical("$Self->{obj_dir}/open.log", $Self->{golden_filename}); + +ok(1); + +1; diff --git a/test_regress/t/t_sys_fstrobe.v b/test_regress/t/t_sys_fstrobe.v new file mode 100644 index 000000000..de5c664b1 --- /dev/null +++ b/test_regress/t/t_sys_fstrobe.v @@ -0,0 +1,55 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t(/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cyc = 0; + int fd; + + // Test loop + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + fd = $fopen({`STRINGIFY(`TEST_OBJ_DIR),"/open.log"}, "w"); + end + else if (cyc == 10) begin + $fstrobe(fd, "[%0t] cyc=%0d", $time, cyc); + $fstrobe(fd, "[%0t] cyc=%0d also", $time, cyc); + end + else if (cyc == 17) begin + $fstrobeb(fd, cyc, "b"); + end + else if (cyc == 18) begin + $fstrobeh(fd, cyc, "h"); + end + else if (cyc == 19) begin + $fstrobeo(fd, cyc, "o"); + end + else if (cyc == 22) begin + $fstrobe(fd, "[%0t] cyc=%0d new-strobe", $time, cyc); + end + else if (cyc == 24) begin + $monitoroff; + end + else if (cyc == 26) begin + $monitoron; + end + else if (cyc == 27) begin + $fclose(fd); + end + else if (cyc == 30) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule diff --git a/test_regress/t/t_sys_monitor.out b/test_regress/t/t_sys_monitor.out new file mode 100644 index 000000000..50f6f4d16 --- /dev/null +++ b/test_regress/t/t_sys_monitor.out @@ -0,0 +1,20 @@ +[110] cyc=11 +[120] cyc=12 +[130] cyc=13 +[140] cyc=14 +[150] cyc=15 +[160] cyc=16 +[170] cyc=17 +00000000000000000000000000010010b +00000013h +00000000024o +00000000025o +00000000026o +[230] cyc=23 new-monitor +[240] cyc=24 new-monitor +[270] cyc=27 new-monitor +[280] cyc=28 new-monitor +[290] cyc=29 new-monitor +[300] cyc=30 new-monitor +*-* All Finished *-* +[310] cyc=31 new-monitor diff --git a/test_regress/t/t_sys_monitor.pl b/test_regress/t/t_sys_monitor.pl new file mode 100755 index 000000000..88b7809fc --- /dev/null +++ b/test_regress/t/t_sys_monitor.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 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_sys_monitor.v b/test_regress/t/t_sys_monitor.v new file mode 100644 index 000000000..21df4071f --- /dev/null +++ b/test_regress/t/t_sys_monitor.v @@ -0,0 +1,45 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cyc = 0; + + // Test loop + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc == 10) begin + $monitor("[%0t] cyc=%0d", $time, cyc); + end + else if (cyc == 17) begin + $monitorb(cyc, "b"); + end + else if (cyc == 18) begin + $monitorh(cyc, "h"); + end + else if (cyc == 19) begin + $monitoro(cyc, "o"); + end + else if (cyc == 22) begin + $monitor("[%0t] cyc=%0d new-monitor", $time, cyc); + end + else if (cyc == 24) begin + $monitoroff; + end + else if (cyc == 26) begin + $monitoron; + end + else if (cyc == 30) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule diff --git a/test_regress/t/t_sys_strobe.out b/test_regress/t/t_sys_strobe.out new file mode 100644 index 000000000..c38db0c3f --- /dev/null +++ b/test_regress/t/t_sys_strobe.out @@ -0,0 +1,7 @@ +[110] cyc=11 +[110] cyc=11 also +00000000000000000000000000010010b +00000013h +00000000024o +[230] cyc=23 new-strobe +*-* All Finished *-* diff --git a/test_regress/t/t_sys_strobe.pl b/test_regress/t/t_sys_strobe.pl new file mode 100755 index 000000000..88b7809fc --- /dev/null +++ b/test_regress/t/t_sys_strobe.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 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_sys_strobe.v b/test_regress/t/t_sys_strobe.v new file mode 100644 index 000000000..4365344d5 --- /dev/null +++ b/test_regress/t/t_sys_strobe.v @@ -0,0 +1,46 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cyc = 0; + + // Test loop + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc == 10) begin + $strobe("[%0t] cyc=%0d", $time, cyc); + $strobe("[%0t] cyc=%0d also", $time, cyc); + end + else if (cyc == 17) begin + $strobeb(cyc, "b"); + end + else if (cyc == 18) begin + $strobeh(cyc, "h"); + end + else if (cyc == 19) begin + $strobeo(cyc, "o"); + end + else if (cyc == 22) begin + $strobe("[%0t] cyc=%0d new-strobe", $time, cyc); + end + else if (cyc == 24) begin + $monitoroff; + end + else if (cyc == 26) begin + $monitoron; + end + else if (cyc == 30) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule From 77ec2dc875e933c4f013196e2d2ff7dddea43ac5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 29 Nov 2020 15:06:29 -0500 Subject: [PATCH 79/91] Internals: Rename some CI comments --- nodist/code_coverage | 64 ++++++++++++------------- test_regress/t/t_hier_block.pl | 2 +- test_regress/t/t_hier_block_nohier.pl | 2 +- test_regress/t/t_hier_block_sc.pl | 2 +- test_regress/t/t_hier_block_vlt.pl | 2 +- test_regress/t/t_leak.pl | 2 +- test_regress/t/t_split_var_0.pl | 2 +- test_regress/t/t_split_var_2_trace.pl | 2 +- test_regress/t/t_trace_litendian.pl | 2 +- test_regress/t/t_trace_litendian_fst.pl | 2 +- 10 files changed, 41 insertions(+), 41 deletions(-) diff --git a/nodist/code_coverage b/nodist/code_coverage index 869027ecf..598d5b94a 100755 --- a/nodist/code_coverage +++ b/nodist/code_coverage @@ -83,28 +83,28 @@ sub test { require "./nodist/code_coverage.dat"; if ($Opt_Stages{1}) { - travis_fold_start("configure"); + ci_fold_start("configure"); print "Stage 1: configure (coverage on)\n"; run("make distclean || true"); run("autoconf"); # Exceptions can pollute the branch coverage data run("./configure --enable-longtests CXX='g++ --coverage -fno-exceptions -DVL_GCOV'"); - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{2}) { - travis_fold_start("build"); + ci_fold_start("build"); print "Stage 2: build\n"; my $nproc = Unix::Processors->new->max_online; run("make -k -j $nproc VERILATOR_NO_OPT_BUILD=1"); # The optimized versions will not collect good coverage, overwrite them run("cp bin/verilator_bin_dbg bin/verilator_bin"); run("cp bin/verilator_coverage_bin_dbg bin/verilator_coverage_bin"); - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{3}) { - travis_fold_start("test"); + ci_fold_start("test"); print "Stage 3: make tests (with coverage on)\n"; if ($#Opt_Tests < 0) { run("make examples VERILATOR_NO_OPT_BUILD=1") @@ -121,12 +121,12 @@ sub test { run($test); } } - travis_fold_end(); + ci_fold_end(); } my $cc_dir = "nodist/obj_dir/coverage"; if ($Opt_Stages{4}) { - travis_fold_start("gcno"); + ci_fold_start("gcno"); print "Stage 4: Create gcno files under $cc_dir\n"; mkpath($cc_dir); mkpath("$cc_dir/info"); @@ -165,11 +165,11 @@ sub test { } } } - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{5} && $Opt_Fastcov) { - travis_fold_start("fastcov"); + ci_fold_start("fastcov"); # Must run in root directory to find all files mkpath($cc_dir); #run("${RealBin}/fastcov.py -b -c src/obj_dbg -X". @@ -178,11 +178,11 @@ sub test { run("${RealBin}/fastcov.py -b -c src/obj_dbg -X --lcov". " --exclude /usr --exclude test_regress" ." -o ${cc_dir}/app_total.info"); - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{5} && !$Opt_Fastcov) { - travis_fold_start("infos"); + ci_fold_start("infos"); print "Stage 5: make infos\n"; my $dats = `find . -print | grep .gcda`; my %dirs; @@ -199,20 +199,20 @@ sub test { })->run; } $Fork->wait_all; - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{6}) { - travis_fold_start("clone"); + ci_fold_start("clone"); # No control file to override single lines, so replicate the sources # Also lets us see the insertion markers in the HTML source res print "Stage 6: Clone sources under $cc_dir\n"; clone_sources($cc_dir); - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{8} && !$Opt_Fastcov) { - travis_fold_start("copy"); + ci_fold_start("copy"); print "Stage 8: Copy .gcno files\n"; my $dats = `find . -print | grep .gcno`; foreach my $dat (sort (split '\n', $dats)) { @@ -221,11 +221,11 @@ sub test { #print "cp $dat, $outdat);\n"; cp($dat, $outdat); } - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{10} && !$Opt_Fastcov) { - travis_fold_start("combine"); + ci_fold_start("combine"); print "Stage 10: Combine data files\n"; { run("cd $cc_dir ; lcov -c -i -d src/obj_dbg -o app_base.info"); @@ -243,11 +243,11 @@ sub test { } } } - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{11}) { - travis_fold_start("dirs"); + ci_fold_start("dirs"); print "Stage 11: Cleanup paths\n"; if ($Opt_Fastcov) { cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info"); @@ -255,11 +255,11 @@ sub test { } else { cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info"); } - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{12}) { - travis_fold_start("filter"); + ci_fold_start("filter"); print "Stage 12: Filter processed source files\n"; my $inc = ''; foreach my $glob (@Source_Globs) { @@ -282,24 +282,24 @@ sub test { } else { run("cd $cc_dir ; lcov --remove app_total.info $exc -o app_total_f.info"); } - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{17}) { - travis_fold_start("report"); + ci_fold_start("report"); print "Stage 17: Create HTML\n"; run("cd $cc_dir ; genhtml app_total_f.info --demangle-cpp" ." --rc lcov_branch_coverage=1 --rc genhtml_hi_limit=100 --output-directory html"); - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{18}) { - travis_fold_start("upload"); + ci_fold_start("upload"); print "Stage 18: Upload\n"; my $cmd = "bash <(curl -s https://codecov.io/bash) -f $cc_dir/app_total.info"; print "print: Not running: export CODECOV_TOKEN=\n"; print "print: Not running: $cmd\n"; - travis_fold_end(); + ci_fold_end(); } if ($Opt_Stages{19}) { @@ -425,13 +425,13 @@ sub run { ($status == 0) or die "%Error: Command Failed $command, $status, stopped"; } -our $_Travis_Action; -sub travis_fold_start { - $_Travis_Action = shift; - print "travis_fold:start:$_Travis_Action\n"; +our $_Ci_Action; +sub ci_fold_start { + $_Ci_Action = shift; + print "travis_fold:start:$_Ci_Action\n"; } -sub travis_fold_end { - print "travis_fold:end:$_Travis_Action\n"; +sub ci_fold_end { + print "travis_fold:end:$_Ci_Action\n"; } ####################################################################### diff --git a/test_regress/t/t_hier_block.pl b/test_regress/t/t_hier_block.pl index e334fd536..e856d3cd8 100755 --- a/test_regress/t/t_hier_block.pl +++ b/test_regress/t/t_hier_block.pl @@ -12,7 +12,7 @@ clean_objs(); scenarios(vlt_all => 1); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # So use 6 threads here though it's not optimal in performace wise, but ok. diff --git a/test_regress/t/t_hier_block_nohier.pl b/test_regress/t/t_hier_block_nohier.pl index ef6ebf31a..006c981b3 100755 --- a/test_regress/t/t_hier_block_nohier.pl +++ b/test_regress/t/t_hier_block_nohier.pl @@ -16,7 +16,7 @@ clean_objs(); scenarios(vlt_all => 1); top_filename("t/t_hier_block.v"); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # So use 6 threads here though it's not optimal in performace wise, but ok. compile( diff --git a/test_regress/t/t_hier_block_sc.pl b/test_regress/t/t_hier_block_sc.pl index 731aec401..7b85fedd8 100755 --- a/test_regress/t/t_hier_block_sc.pl +++ b/test_regress/t/t_hier_block_sc.pl @@ -12,7 +12,7 @@ clean_objs(); top_filename("t/t_hier_block.v"); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # So use 6 threads here though it's not optimal in performace wise, but ok. scenarios(vlt_all => 1); diff --git a/test_regress/t/t_hier_block_vlt.pl b/test_regress/t/t_hier_block_vlt.pl index fc4e7ccc9..f5231113b 100755 --- a/test_regress/t/t_hier_block_vlt.pl +++ b/test_regress/t/t_hier_block_vlt.pl @@ -13,7 +13,7 @@ clean_objs(); scenarios(vlt_all => 1); top_filename("t/t_hier_block.v"); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # So use 6 threads here though it's not optimal in performace wise, but ok. compile( diff --git a/test_regress/t/t_leak.pl b/test_regress/t/t_leak.pl index 6e0507280..4ab37524e 100755 --- a/test_regress/t/t_leak.pl +++ b/test_regress/t/t_leak.pl @@ -11,7 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di if ($Self->{vltmt} && exists $ENV{TRAVIS_DIST} && $ENV{TRAVIS_DIST} eq "trusty") { - skip("Multithreaded test does not work under Travis w/ Ubuntu Trusty"); + skip("Multithreaded test does not work under CI w/ Ubuntu Trusty"); } scenarios(vlt_all => 1); diff --git a/test_regress/t/t_split_var_0.pl b/test_regress/t/t_split_var_0.pl index ee21699a3..5f07afe64 100755 --- a/test_regress/t/t_split_var_0.pl +++ b/test_regress/t/t_split_var_0.pl @@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # So use 6 threads here though it's not optimal in performace wise, but ok. compile( diff --git a/test_regress/t/t_split_var_2_trace.pl b/test_regress/t/t_split_var_2_trace.pl index 49fd37f82..c79ed778a 100755 --- a/test_regress/t/t_split_var_2_trace.pl +++ b/test_regress/t/t_split_var_2_trace.pl @@ -11,7 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); top_filename("t/t_split_var_0.v"); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # So use 6 threads here though it's not optimal in performace wise, but ok. compile( diff --git a/test_regress/t/t_trace_litendian.pl b/test_regress/t/t_trace_litendian.pl index 6ed5efd1c..91cc2e48f 100755 --- a/test_regress/t/t_trace_litendian.pl +++ b/test_regress/t/t_trace_litendian.pl @@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # Strangely, asking for more threads makes it go away. compile( diff --git a/test_regress/t/t_trace_litendian_fst.pl b/test_regress/t/t_trace_litendian_fst.pl index f13aa0c0d..4918c10bf 100755 --- a/test_regress/t/t_trace_litendian_fst.pl +++ b/test_regress/t/t_trace_litendian_fst.pl @@ -12,7 +12,7 @@ scenarios(simulator => 1); top_filename("t/t_trace_litendian.v"); -# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# CI environment offers 2 VCPUs, 2 thread setting causes the following warning. # %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. # Strangely, asking for more threads makes it go away. compile( From 0818d88113898ee0432ce40fbcb283b6bd153135 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 29 Nov 2020 16:58:34 -0500 Subject: [PATCH 80/91] Tests: Cast enum test --- test_regress/t/t_castdyn.out | 24 +++++++------- test_regress/t/t_castdyn.v | 1 + test_regress/t/t_castdyn_enum.out | 5 +++ test_regress/t/t_castdyn_enum.pl | 23 +++++++++++++ test_regress/t/t_castdyn_enum.v | 54 +++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 test_regress/t/t_castdyn_enum.out create mode 100755 test_regress/t/t_castdyn_enum.pl create mode 100644 test_regress/t/t_castdyn_enum.v diff --git a/test_regress/t/t_castdyn.out b/test_regress/t/t_castdyn.out index 2b0ae4bce..2e5c96249 100644 --- a/test_regress/t/t_castdyn.out +++ b/test_regress/t/t_castdyn.out @@ -2,28 +2,28 @@ : ... In instance t 28 | i = $cast(ao, a); | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:32:7: Unsupported: $cast. Suggest try static cast. +%Error-UNSUPPORTED: t/t_castdyn.v:33:7: Unsupported: $cast. Suggest try static cast. : ... In instance t - 32 | $cast(ao, a); + 33 | $cast(ao, a); | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:35:11: Unsupported: $cast. Suggest try static cast. +%Error-UNSUPPORTED: t/t_castdyn.v:36:11: Unsupported: $cast. Suggest try static cast. : ... In instance t - 35 | i = $cast(ao, 2.1 * 3.7); + 36 | i = $cast(ao, 2.1 * 3.7); | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:39:11: Unsupported: $cast. Suggest try static cast. +%Error-UNSUPPORTED: t/t_castdyn.v:40:11: Unsupported: $cast. Suggest try static cast. : ... In instance t - 39 | i = $cast(bo, null); + 40 | i = $cast(bo, null); | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:45:11: Unsupported: $cast. Suggest try static cast. +%Error-UNSUPPORTED: t/t_castdyn.v:46:11: Unsupported: $cast. Suggest try static cast. : ... In instance t - 45 | i = $cast(bao, b); + 46 | i = $cast(bao, b); | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:51:11: Unsupported: $cast. Suggest try static cast. +%Error-UNSUPPORTED: t/t_castdyn.v:52:11: Unsupported: $cast. Suggest try static cast. : ... In instance t - 51 | i = $cast(bbo, b); + 52 | i = $cast(bbo, b); | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn.v:58:11: Unsupported: $cast. Suggest try static cast. +%Error-UNSUPPORTED: t/t_castdyn.v:59:11: Unsupported: $cast. Suggest try static cast. : ... In instance t - 58 | i = $cast(bao, b); + 59 | i = $cast(bao, b); | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_castdyn.v b/test_regress/t/t_castdyn.v index 123268419..4c8761f96 100644 --- a/test_regress/t/t_castdyn.v +++ b/test_regress/t/t_castdyn.v @@ -28,6 +28,7 @@ module t (/*AUTOARG*/); i = $cast(ao, a); if (i != 1) $stop; if (ao != 1234) $stop; + a = 12345; $cast(ao, a); if (ao != 12345) $stop; diff --git a/test_regress/t/t_castdyn_enum.out b/test_regress/t/t_castdyn_enum.out new file mode 100644 index 000000000..893b3046b --- /dev/null +++ b/test_regress/t/t_castdyn_enum.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_castdyn_enum.v:23:11: Unsupported: $cast. Suggest try static cast. + : ... In instance t + 23 | i = $cast(en, cyc); + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_castdyn_enum.pl b/test_regress/t/t_castdyn_enum.pl new file mode 100755 index 000000000..2ad4a887d --- /dev/null +++ b/test_regress/t/t_castdyn_enum.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 => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +execute( + check_finished => 1, + ) if !$Self->{vlt_all}; + +ok(1); +1; diff --git a/test_regress/t/t_castdyn_enum.v b/test_regress/t/t_castdyn_enum.v new file mode 100644 index 000000000..44cf50098 --- /dev/null +++ b/test_regress/t/t_castdyn_enum.v @@ -0,0 +1,54 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +typedef enum {TEN=10, + ELEVEN=11, + SIXTEEN=16} enum_t; + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + int i; + int cyc; + enum_t en; + + // Test loop + always @ (posedge clk) begin + i = $cast(en, cyc); +`ifdef TEST_VERBOSE + $write("[%0t] cyc==%0d i=%0d en=%0d\n",$time, cyc, i, en); +`endif + cyc <= cyc + 1; + if (cyc == 10) begin + if (i != 1) $stop; + if (en != TEN) $stop; + end + else if (cyc == 11) begin + if (i != 1) $stop; + if (en != ELEVEN) $stop; + end + else if (cyc == 12) begin + if (i != 0) $stop; + if (en != ELEVEN) $stop; + end + else if (cyc == 16) begin + if (i != 1) $stop; + if (en != SIXTEEN) $stop; + end + else if (cyc == 17) begin + if (i != 0) $stop; + if (en != SIXTEEN) $stop; + end + else if (cyc == 99) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule From d21b4e3fc747874e945bd1c3a4d551bdd3280172 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 29 Nov 2020 18:26:06 -0500 Subject: [PATCH 81/91] Internal cast preparatory cleanups. --- src/V3AstNodes.cpp | 1 + src/V3AstNodes.h | 7 ++++++- src/verilog.y | 4 ++-- test_regress/t/t_castdyn_bad.out | 9 --------- test_regress/t/t_castdyn_run_bad.out | 9 +++++++++ .../t/{t_castdyn_bad.pl => t_castdyn_run_bad.pl} | 0 test_regress/t/{t_castdyn_bad.v => t_castdyn_run_bad.v} | 0 7 files changed, 18 insertions(+), 12 deletions(-) delete mode 100644 test_regress/t/t_castdyn_bad.out create mode 100644 test_regress/t/t_castdyn_run_bad.out rename test_regress/t/{t_castdyn_bad.pl => t_castdyn_run_bad.pl} (100%) rename test_regress/t/{t_castdyn_bad.v => t_castdyn_run_bad.v} (100%) diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 076d94669..a8f0bcba0 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1175,6 +1175,7 @@ bool AstClass::isClassExtendedFrom(const AstClass* refClassp, const AstClass* ba // TAIL RECURSIVE if (!refClassp || !baseClassp) return false; if (refClassp == baseClassp) return true; + if (!refClassp->extendsp()) return false; return isClassExtendedFrom(refClassp->extendsp()->classp(), baseClassp); } void AstClass::dump(std::ostream& str) const { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 032cee3ee..909b741fa 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -5997,12 +5997,17 @@ public: class AstCast final : public AstNode { // Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc public: - AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp) + AstCast(FileLine* fl, AstNode* lhsp, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) { setOp1p(lhsp); setOp2p(dtp); dtypeFrom(dtp); } + AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp) + : ASTGEN_SUPER(fl) { + setOp1p(lhsp); + dtypeFrom(dtp); + } ASTNODE_NODE_FUNCS(Cast) virtual bool hasDType() const override { return true; } virtual string emitVerilog() { return "((%d)'(%l))"; } diff --git a/src/verilog.y b/src/verilog.y index fdace335b..b6b54483f 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -4255,9 +4255,9 @@ expr: // IEEE: part of expression/constant_expression/primary // // // IEEE: cast/constant_cast // // expanded from casting_type - | simple_type yP_TICK '(' expr ')' { $$ = new AstCast($1->fileline(), $4, $1); } + | simple_type yP_TICK '(' expr ')' { $$ = new AstCast($1->fileline(), $4, VFlagChildDType{}, $1); } | yTYPE '(' exprOrDataType ')' yP_TICK '(' expr ')' - { $$ = new AstCast($1, $7, new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3)); } + { $$ = new AstCast($1, $7, VFlagChildDType(), new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3)); } | ySIGNED yP_TICK '(' expr ')' { $$ = new AstSigned($1, $4); } | yUNSIGNED yP_TICK '(' expr ')' { $$ = new AstUnsigned($1, $4); } | ySTRING yP_TICK '(' expr ')' { $$ = new AstCvtPackString($1, $4); } diff --git a/test_regress/t/t_castdyn_bad.out b/test_regress/t/t_castdyn_bad.out deleted file mode 100644 index 030a8b1ac..000000000 --- a/test_regress/t/t_castdyn_bad.out +++ /dev/null @@ -1,9 +0,0 @@ -%Error-UNSUPPORTED: t/t_castdyn_bad.v:20:11: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 20 | i = $cast(c, b); - | ^~~~~ -%Error-UNSUPPORTED: t/t_castdyn_bad.v:23:7: Unsupported: $cast. Suggest try static cast. - : ... In instance t - 23 | $cast(c, b); - | ^~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_castdyn_run_bad.out b/test_regress/t/t_castdyn_run_bad.out new file mode 100644 index 000000000..bba531f0e --- /dev/null +++ b/test_regress/t/t_castdyn_run_bad.out @@ -0,0 +1,9 @@ +%Error-UNSUPPORTED: t/t_castdyn_run_bad.v:20:11: Unsupported: $cast. Suggest try static cast. + : ... In instance t + 20 | i = $cast(c, b); + | ^~~~~ +%Error-UNSUPPORTED: t/t_castdyn_run_bad.v:23:7: Unsupported: $cast. Suggest try static cast. + : ... In instance t + 23 | $cast(c, b); + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_castdyn_bad.pl b/test_regress/t/t_castdyn_run_bad.pl similarity index 100% rename from test_regress/t/t_castdyn_bad.pl rename to test_regress/t/t_castdyn_run_bad.pl diff --git a/test_regress/t/t_castdyn_bad.v b/test_regress/t/t_castdyn_run_bad.v similarity index 100% rename from test_regress/t/t_castdyn_bad.v rename to test_regress/t/t_castdyn_run_bad.v From 014e43f0efa6b73118ddf65e16754d3211a7f150 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 1 Dec 2020 18:30:25 -0500 Subject: [PATCH 82/91] Reset index counts on clearing verilated_cov (static removal) --- include/verilated_cov.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/verilated_cov.cpp b/include/verilated_cov.cpp index 9db5eacb7..45f111cd9 100644 --- a/include/verilated_cov.cpp +++ b/include/verilated_cov.cpp @@ -99,6 +99,7 @@ private: ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items + int m_nextIndex VL_GUARDED_BY(m_mutex) = (KEY_UNDEF + 1); ///< Next insert value VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex) = nullptr; ///< Item about to insert const char* m_insertFilenamep VL_GUARDED_BY(m_mutex) = nullptr; ///< Filename about to insert @@ -118,14 +119,13 @@ public: private: // PRIVATE METHODS int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) { - static int nextIndex = KEY_UNDEF + 1; const auto iter = m_valueIndexes.find(value); if (iter != m_valueIndexes.end()) return iter->second; - nextIndex++; - assert(nextIndex > 0); // Didn't rollover - m_valueIndexes.insert(std::make_pair(value, nextIndex)); - m_indexValues.insert(std::make_pair(nextIndex, value)); - return nextIndex; + m_nextIndex++; + assert(m_nextIndex > 0); // Didn't rollover + m_valueIndexes.insert(std::make_pair(value, m_nextIndex)); + m_indexValues.insert(std::make_pair(m_nextIndex, value)); + return m_nextIndex; } static std::string dequote(const std::string& text) VL_PURE { // Quote any special characters @@ -235,6 +235,7 @@ private: m_items.clear(); m_indexValues.clear(); m_valueIndexes.clear(); + m_nextIndex = KEY_UNDEF + 1; } public: From 212e8fb14b6d206323d77ab34c41dd20d16e1362 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 1 Dec 2020 18:49:03 -0500 Subject: [PATCH 83/91] Internals: Cleanup some inlines, use constexpr. No functional change intended. --- include/verilated.h | 6 +++--- include/verilated_save.h | 8 ++++---- include/verilated_trace_imp.cpp | 8 ++++---- include/verilated_vpi.cpp | 32 ++++++++++++++------------------ src/V3Ast.h | 16 ++++++++-------- src/V3Config.cpp | 4 ++-- src/V3Const.cpp | 2 +- src/V3EmitC.cpp | 2 +- src/V3EmitCSyms.cpp | 4 ++-- src/V3Global.h | 6 +++--- src/V3GraphAcyc.cpp | 2 +- src/V3GraphAlg.cpp | 4 ++-- src/V3LinkLevel.cpp | 2 +- src/V3String.cpp | 5 +++-- src/V3SymTable.h | 2 +- src/V3Task.cpp | 2 +- src/VlcBucket.h | 4 ++-- src/VlcTop.cpp | 2 +- 18 files changed, 54 insertions(+), 57 deletions(-) diff --git a/include/verilated.h b/include/verilated.h index 06bcb7741..a9f59436f 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -457,7 +457,7 @@ public: static inline int debug() VL_MT_SAFE { return s_s.s_debug; } #else /// Return constant 0 debug level, so C++'s optimizer rips up - static inline int debug() VL_PURE { return 0; } + static constexpr int debug() VL_PURE { return 0; } #endif /// Enable calculation of unused signals static void calcUnusedSigs(bool flag) VL_MT_SAFE; @@ -572,8 +572,8 @@ public: static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; } static int exportFuncNum(const char* namep) VL_MT_SAFE; - static size_t serialized1Size() VL_PURE { return sizeof(s_s); } - static void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only + static constexpr size_t serialized1Size() VL_PURE { return sizeof(s_s); } + static constexpr void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // For Serialize only static size_t serialized2Size() VL_PURE; static void* serialized2Ptr() VL_MT_UNSAFE; #ifdef VL_THREADED diff --git a/include/verilated_save.h b/include/verilated_save.h index ca12c57ca..bb40d86fc 100644 --- a/include/verilated_save.h +++ b/include/verilated_save.h @@ -38,8 +38,8 @@ protected: std::string m_filename; ///< Filename, for error messages VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread - inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation - inline static size_t bufferInsertSize() { return 16 * 1024; } + static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation + static constexpr size_t bufferInsertSize() { return 16 * 1024; } void header() VL_MT_UNSAFE_ONE; void trailer() VL_MT_UNSAFE_ONE; @@ -98,8 +98,8 @@ protected: std::string m_filename; ///< Filename, for error messages VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread - inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation - inline static size_t bufferInsertSize() { return 16 * 1024; } + static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation + static constexpr size_t bufferInsertSize() { return 16 * 1024; } virtual void fill() = 0; void header() VL_MT_UNSAFE_ONE; diff --git a/include/verilated_trace_imp.cpp b/include/verilated_trace_imp.cpp index ee2a31e35..840eb8be3 100644 --- a/include/verilated_trace_imp.cpp +++ b/include/verilated_trace_imp.cpp @@ -559,7 +559,7 @@ template <> void VerilatedTrace::fullDouble(vluint32_t* oldp, doub // All of these take a destination pointer where the string will be emitted, // and a value to convert. There are a couple of variants for efficiency. -inline static void cvtCDataToStr(char* dstp, CData value) { +static inline void cvtCDataToStr(char* dstp, CData value) { #ifdef VL_HAVE_SSE2 // Similar to cvtSDataToStr but only the bottom 8 byte lanes are used const __m128i a = _mm_cvtsi32_si128(value); @@ -581,7 +581,7 @@ inline static void cvtCDataToStr(char* dstp, CData value) { #endif } -inline static void cvtSDataToStr(char* dstp, SData value) { +static inline void cvtSDataToStr(char* dstp, SData value) { #ifdef VL_HAVE_SSE2 // We want each bit in the 16-bit input value to end up in a byte lane // within the 128-bit XMM register. Note that x86 is little-endian and we @@ -617,7 +617,7 @@ inline static void cvtSDataToStr(char* dstp, SData value) { #endif } -inline static void cvtIDataToStr(char* dstp, IData value) { +static inline void cvtIDataToStr(char* dstp, IData value) { #ifdef VL_HAVE_AVX2 // Similar to cvtSDataToStr but the bottom 16-bits are processed in the // top half of the YMM registerss @@ -636,7 +636,7 @@ inline static void cvtIDataToStr(char* dstp, IData value) { #endif } -inline static void cvtQDataToStr(char* dstp, QData value) { +static inline void cvtQDataToStr(char* dstp, QData value) { cvtIDataToStr(dstp, value >> 32); cvtIDataToStr(dstp + 32, value); } diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 104383c2a..4b47a6c62 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -63,7 +63,7 @@ public: // CONSTRUCTORS VerilatedVpio() = default; virtual ~VerilatedVpio() = default; - inline static void* operator new(size_t size) VL_MT_SAFE { + static void* operator new(size_t size) VL_MT_SAFE { // We new and delete tons of vpi structures, so keep them around // To simplify our free list, we use a size large enough for all derived types // We reserve word zero for the next pointer, as that's safer in case a @@ -79,13 +79,13 @@ public: vluint8_t* newp = reinterpret_cast(::operator new(chunk + 8)); return newp + 8; } - inline static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE { + static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE { vluint8_t* oldp = (static_cast(obj)) - 8; *(reinterpret_cast(oldp)) = t_freeHead; t_freeHead = oldp; } // MEMBERS - static inline VerilatedVpio* castp(vpiHandle h) { + static VerilatedVpio* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } inline vpiHandle castVpiHandle() { return reinterpret_cast(this); } @@ -115,7 +115,7 @@ public: m_cbData.value = &m_value; } virtual ~VerilatedVpioCb() override = default; - static inline VerilatedVpioCb* castp(vpiHandle h) { + static VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiCallback; } @@ -132,7 +132,7 @@ public: explicit VerilatedVpioConst(vlsint32_t num) : m_num{num} {} virtual ~VerilatedVpioConst() override = default; - static inline VerilatedVpioConst* castp(vpiHandle h) { + static VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiConstant; } @@ -150,7 +150,7 @@ public: virtual ~VerilatedVpioParam() override = default; - static inline VerilatedVpioParam* castp(vpiHandle h) { + static VerilatedVpioParam* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiParameter; } @@ -173,7 +173,7 @@ public: explicit VerilatedVpioRange(const VerilatedRange* range) : m_range{range} {} virtual ~VerilatedVpioRange() override = default; - static inline VerilatedVpioRange* castp(vpiHandle h) { + static VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiRange; } @@ -199,7 +199,7 @@ public: explicit VerilatedVpioScope(const VerilatedScope* scopep) : m_scopep{scopep} {} virtual ~VerilatedVpioScope() override = default; - static inline VerilatedVpioScope* castp(vpiHandle h) { + static VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiScope; } @@ -236,7 +236,7 @@ public: virtual ~VerilatedVpioVar() override { if (m_prevDatap) VL_DO_CLEAR(delete[] m_prevDatap, m_prevDatap = nullptr); } - static inline VerilatedVpioVar* castp(vpiHandle h) { + static VerilatedVpioVar* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } const VerilatedVar* varp() const { return m_varp; } @@ -275,7 +275,7 @@ public: m_varDatap = (static_cast(varp->datap())) + entSize() * offset; } virtual ~VerilatedVpioMemoryWord() override = default; - static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { + static VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiMemoryWord; } @@ -299,7 +299,7 @@ public: explicit VerilatedVpioVarIter(const VerilatedScope* scopep) : m_scopep{scopep} {} virtual ~VerilatedVpioVarIter() override = default; - static inline VerilatedVpioVarIter* castp(vpiHandle h) { + static VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiIterator; } @@ -335,7 +335,7 @@ public: , m_iteration{varp->unpacked().right()} , m_direction{VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) ? 1 : -1} {} virtual ~VerilatedVpioMemoryWordIter() override = default; - static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { + static VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiIterator; } @@ -362,7 +362,7 @@ public: if (strncmp(m_fullname, "TOP.", 4) == 0) m_fullname += 4; m_name = m_scopep->identifier(); } - static inline VerilatedVpioModule* castp(vpiHandle h) { + static VerilatedVpioModule* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiModule; } @@ -380,7 +380,7 @@ public: m_it = m_vec->begin(); } virtual ~VerilatedVpioModuleIter() override = default; - static inline VerilatedVpioModuleIter* castp(vpiHandle h) { + static VerilatedVpioModuleIter* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } virtual vluint32_t type() const override { return vpiIterator; } @@ -410,10 +410,6 @@ class VerilatedVpiImp final { typedef std::list VpioCbList; typedef std::set, VerilatedVpiTimedCbsCmp> VpioTimedCbs; - struct product_info { - PLI_BYTE8* product; - }; - VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason VpioTimedCbs m_timedCbs; // Time based callbacks VerilatedVpiError* m_errorInfop = nullptr; // Container for vpi error info diff --git a/src/V3Ast.h b/src/V3Ast.h index 90c54a434..ae9402538 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -989,10 +989,10 @@ public: bool m_littleEndian : 1; // Bit vector is little endian }; }; - inline bool operator==(const VNumRange& rhs) const { + bool operator==(const VNumRange& rhs) const { return m_hi == rhs.m_hi && m_lo == rhs.m_lo && mu_flags == rhs.mu_flags; } - inline bool operator<(const VNumRange& rhs) const { + bool operator<(const VNumRange& rhs) const { if ((m_hi < rhs.m_hi)) return true; if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs if ((m_lo < rhs.m_lo)) return true; @@ -1091,11 +1091,11 @@ public: VSigning m_numeric; // From AstNodeDType: Node is signed AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword) - inline bool operator==(const VBasicTypeKey& rhs) const { + bool operator==(const VBasicTypeKey& rhs) const { return m_width == rhs.m_width && m_widthMin == rhs.m_widthMin && m_numeric == rhs.m_numeric && m_keyword == rhs.m_keyword && m_nrange == rhs.m_nrange; } - inline bool operator<(const VBasicTypeKey& rhs) const { + bool operator<(const VBasicTypeKey& rhs) const { if ((m_width < rhs.m_width)) return true; if (!(m_width == rhs.m_width)) return false; // lhs > rhs if ((m_widthMin < rhs.m_widthMin)) return true; @@ -1148,7 +1148,7 @@ public: AstNode* toNodep() const { return reinterpret_cast(m_u.up); } V3GraphVertex* toGraphVertex() const { return reinterpret_cast(m_u.up); } int toInt() const { return m_u.ui; } - static inline VNUser fromInt(int i) { return VNUser(i); } + static VNUser fromInt(int i) { return VNUser(i); } }; //###################################################################### @@ -1350,9 +1350,9 @@ public: uint32_t depth() const { return (m_both >> 24) & 255; } uint32_t hshval() const { return m_both & M24; } // OPERATORS - inline bool operator==(const V3Hash& rh) const { return m_both == rh.m_both; } - inline bool operator!=(const V3Hash& rh) const { return m_both != rh.m_both; } - inline bool operator<(const V3Hash& rh) const { return m_both < rh.m_both; } + bool operator==(const V3Hash& rh) const { return m_both == rh.m_both; } + bool operator!=(const V3Hash& rh) const { return m_both != rh.m_both; } + bool operator<(const V3Hash& rh) const { return m_both < rh.m_both; } // CONSTRUCTORS class Illegal {}; // for creator type-overload selection class FullValue {}; // for creator type-overload selection diff --git a/src/V3Config.cpp b/src/V3Config.cpp index 3498e66fb..f552b766a 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -234,7 +234,7 @@ public: , m_code{code} , m_on{on} {} ~V3ConfigIgnoresLine() = default; - inline bool operator<(const V3ConfigIgnoresLine& rh) const { + bool operator<(const V3ConfigIgnoresLine& rh) const { if (m_lineno < rh.m_lineno) return true; if (m_lineno > rh.m_lineno) return false; if (m_code < rh.m_code) return true; @@ -356,7 +356,7 @@ class V3ConfigResolver final { ~V3ConfigResolver() = default; public: - inline static V3ConfigResolver& s() { return s_singleton; } + static V3ConfigResolver& s() { return s_singleton; } V3ConfigModuleResolver& modules() { return m_modules; } V3ConfigFileResolver& files() { return m_files; } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 6ec823740..1d0dccd64 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1730,7 +1730,7 @@ private: } struct SenItemCmp { - inline bool operator()(const AstSenItem* lhsp, const AstSenItem* rhsp) const { + bool operator()(const AstSenItem* lhsp, const AstSenItem* rhsp) const { if (lhsp->type() < rhsp->type()) return true; if (lhsp->type() > rhsp->type()) return false; // Looks visually better if we keep sorted by name diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 35b1c4162..a2b6f8519 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -216,7 +216,7 @@ public: } struct CmpName { - inline bool operator()(const AstNode* lhsp, const AstNode* rhsp) const { + bool operator()(const AstNode* lhsp, const AstNode* rhsp) const { return lhsp->name() < rhsp->name(); } }; diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 3c8fb2e6e..168437852 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -79,12 +79,12 @@ class EmitCSyms final : EmitCBaseVisitor { typedef std::vector ScopeNameList; typedef std::map ScopeNameHierarchy; struct CmpName { - inline bool operator()(const ScopeModPair& lhsp, const ScopeModPair& rhsp) const { + bool operator()(const ScopeModPair& lhsp, const ScopeModPair& rhsp) const { return lhsp.first->name() < rhsp.first->name(); } }; struct CmpDpi { - inline bool operator()(const AstCFunc* lhsp, const AstCFunc* rhsp) const { + bool operator()(const AstCFunc* lhsp, const AstCFunc* rhsp) const { if (lhsp->dpiImport() != rhsp->dpiImport()) { // cppcheck-suppress comparisonOfFuncReturningBoolError return lhsp->dpiImport() < rhsp->dpiImport(); diff --git a/src/V3Global.h b/src/V3Global.h index 3075092c4..f9fff4eb6 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -65,12 +65,12 @@ class VWidthMinUsage final { public: enum en : uint8_t { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH }; enum en m_e; - inline VWidthMinUsage() + VWidthMinUsage() : m_e{LINT_WIDTH} {} // cppcheck-suppress noExplicitConstructor - inline VWidthMinUsage(en _e) + VWidthMinUsage(en _e) : m_e{_e} {} - explicit inline VWidthMinUsage(int _e) + explicit VWidthMinUsage(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 5b38813c1..858e4c22d 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -77,7 +77,7 @@ public: //-------------------------------------------------------------------- struct GraphAcycEdgeCmp { - inline bool operator()(const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { + bool operator()(const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { if (lhsp->weight() > rhsp->weight()) return true; // LHS goes first if (lhsp->weight() < rhsp->weight()) return false; // RHS goes first return false; diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index 929dbdcd9..e0046bd21 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -469,12 +469,12 @@ void V3Graph::makeEdgesNonCutable(V3EdgeFuncP edgeFuncp) { // Algorithms - sorting struct GraphSortVertexCmp { - inline bool operator()(const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { + bool operator()(const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { return lhsp->sortCmp(rhsp) < 0; } }; struct GraphSortEdgeCmp { - inline bool operator()(const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { + bool operator()(const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { return lhsp->sortCmp(rhsp) < 0; } }; diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index da3904efb..4a5bc93b7 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -34,7 +34,7 @@ // Levelizing class functions struct CmpLevel { - inline bool operator()(const AstNodeModule* lhsp, const AstNodeModule* rhsp) const { + bool operator()(const AstNodeModule* lhsp, const AstNodeModule* rhsp) const { return lhsp->level() < rhsp->level(); } }; diff --git a/src/V3String.cpp b/src/V3String.cpp index 418101436..edf02a01d 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -307,7 +307,7 @@ uint64_t VHashSha256::digestUInt64() { } string VHashSha256::digestHex() { - static const char* digits = "0123456789abcdef"; + static const char* const digits = "0123456789abcdef"; const string& binhash = digestBinary(); string out; out.reserve(70); @@ -323,7 +323,8 @@ string VHashSha256::digestSymbol() { // has + and / for last two digits, but need C symbol, and we also // avoid conflicts with use of _, so use "AB" at the end. // Thus this function is non-reversible. - static const char* digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"; + static const char* const digits + = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"; const string& binhash = digestBinary(); string out; out.reserve(28); diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 0b0cd7242..de63b816a 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -57,7 +57,7 @@ class VSymEnt final { return level; } #else - static inline int debug() { return 0; } // NOT runtime, too hot of a function + static constexpr int debug() { return 0; } // NOT runtime, too hot of a function #endif public: typedef IdNameMap::const_iterator const_iterator; diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 38afb4c39..131129160 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1671,7 +1671,7 @@ bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& fr } const char* V3Task::dpiTemporaryVarSuffix() { - static const char* suffix = "__Vcvt"; + static const char* const suffix = "__Vcvt"; return suffix; } diff --git a/src/VlcBucket.h b/src/VlcBucket.h index be7245e27..4a2c30afc 100644 --- a/src/VlcBucket.h +++ b/src/VlcBucket.h @@ -32,8 +32,8 @@ private: vluint64_t m_dataSize = 0; ///< Current entries in m_datap vluint64_t m_bucketsCovered = 0; ///< Num buckets with sufficient coverage - static inline vluint64_t covBit(vluint64_t point) { return 1ULL << (point & 63); } - inline vluint64_t allocSize() const { return sizeof(vluint64_t) * m_dataSize / 64; } + static vluint64_t covBit(vluint64_t point) { return 1ULL << (point & 63); } + vluint64_t allocSize() const { return sizeof(vluint64_t) * m_dataSize / 64; } void allocate(vluint64_t point) { vluint64_t oldsize = m_dataSize; if (m_dataSize < point) m_dataSize = (point + 64) & ~63ULL; // Keep power of two diff --git a/src/VlcTop.cpp b/src/VlcTop.cpp index ee7c57153..cd87e5879 100644 --- a/src/VlcTop.cpp +++ b/src/VlcTop.cpp @@ -134,7 +134,7 @@ void VlcTop::writeInfo(const string& filename) { //******************************************************************** struct CmpComputrons { - inline bool operator()(const VlcTest* lhsp, const VlcTest* rhsp) const { + bool operator()(const VlcTest* lhsp, const VlcTest* rhsp) const { if (lhsp->computrons() != rhsp->computrons()) { return lhsp->computrons() < rhsp->computrons(); } From b054d937cb993fec1b92d7e462dafec73b7819b6 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 1 Dec 2020 19:01:20 -0500 Subject: [PATCH 84/91] Rename static/thread misnamed variables. No functional change. --- include/verilated.cpp | 239 +++++++++++++++++++------------------- include/verilated.h | 2 +- include/verilated_vpi.cpp | 116 +++++++++--------- src/V3EmitC.cpp | 6 +- src/V3TSP.cpp | 6 +- 5 files changed, 185 insertions(+), 184 deletions(-) diff --git a/include/verilated.cpp b/include/verilated.cpp index cbe5655fd..6d2dbcb21 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -61,7 +61,7 @@ typedef union { // Global variables // Slow path variables -VerilatedMutex Verilated::m_mutex; +VerilatedMutex Verilated::s_mutex; // Keep below together in one cache line Verilated::Serialized Verilated::s_s; @@ -685,7 +685,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA // Note uses a single buffer internally; presumes only one usage per printf // Note also assumes variables < 64 are not wide, this assumption is // sometimes not true in low-level routines written here in verilated.cpp - static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char t_tmp[VL_VALUE_STRING_MAX_WIDTH]; const char* pctp = nullptr; // Most recent %##.##g format bool inPct = false; bool widthSet = false; @@ -763,11 +763,11 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA if (lbits) {} // UNUSED - always 64 if (fmt == '^') { // Realtime if (!widthSet) width = VerilatedImp::timeFormatWidth(); - output += _vl_vsformat_time(tmp, d, left, width); + output += _vl_vsformat_time(t_tmp, d, left, width); } else { std::string fmts(pctp, pos - pctp + 1); - sprintf(tmp, fmts.c_str(), d); - output += tmp; + sprintf(t_tmp, fmts.c_str(), d); + output += t_tmp; } break; } @@ -811,9 +811,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA int digits = 0; std::string append; if (lbits <= VL_QUADSIZE) { - digits = sprintf(tmp, "%" VL_PRI64 "d", + digits = sprintf(t_tmp, "%" VL_PRI64 "d", static_cast(VL_EXTENDS_QQ(lbits, lbits, ld))); - append = tmp; + append = t_tmp; } else { if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) { WData neg[VL_VALUE_STRING_MAX_WIDTH / 4 + 2]; @@ -840,8 +840,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA int digits = 0; std::string append; if (lbits <= VL_QUADSIZE) { - digits = sprintf(tmp, "%" VL_PRI64 "u", ld); - append = tmp; + digits = sprintf(t_tmp, "%" VL_PRI64 "u", ld); + append = t_tmp; } else { append = VL_DECIMAL_NW(lbits, lwp); digits = append.length(); @@ -860,7 +860,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA } case 't': { // Time if (!widthSet) width = VerilatedImp::timeFormatWidth(); - output += _vl_vsformat_time(tmp, static_cast(ld), left, width); + output += _vl_vsformat_time(t_tmp, static_cast(ld), left, width); break; } case 'b': @@ -1034,7 +1034,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf // Read a Verilog $sscanf/$fscanf style format into the output list // The format must be pre-processed (and lower cased) by Verilator // Arguments are in "width, arg-value (or WDataIn* if wide)" form - static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char t_tmp[VL_VALUE_STRING_MAX_WIDTH]; int floc = fbits - 1; IData got = 0; bool inPct = false; @@ -1098,13 +1098,13 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf } case 's': { _vl_vsss_skipspace(fp, floc, fromp, fstr); - _vl_vsss_read_str(fp, floc, fromp, fstr, tmp, nullptr); - if (!tmp[0]) goto done; + _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, nullptr); + if (!t_tmp[0]) goto done; if (owp) { - int lpos = (static_cast(strlen(tmp))) - 1; + int lpos = (static_cast(strlen(t_tmp))) - 1; int lsb = 0; for (int i = 0; i < obits && lpos >= 0; --lpos) { - _vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]); + _vl_vsss_setbit(owp, obits, lsb, 8, t_tmp[lpos]); lsb += 8; } } @@ -1112,10 +1112,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf } case 'd': { // Signed decimal _vl_vsss_skipspace(fp, floc, fromp, fstr); - _vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_"); - if (!tmp[0]) goto done; + _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_"); + if (!t_tmp[0]) goto done; vlsint64_t ld = 0; - sscanf(tmp, "%30" VL_PRI64 "d", &ld); + sscanf(t_tmp, "%30" VL_PRI64 "d", &ld); VL_SET_WQ(owp, ld); break; } @@ -1123,46 +1123,47 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf case 'e': case 'g': { // Real number _vl_vsss_skipspace(fp, floc, fromp, fstr); - _vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "+-.0123456789eE"); - if (!tmp[0]) goto done; + _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "+-.0123456789eE"); + if (!t_tmp[0]) goto done; // cppcheck-suppress unusedStructMember // It's used union { double r; vlsint64_t ld; } u; - u.r = strtod(tmp, nullptr); + u.r = strtod(t_tmp, nullptr); VL_SET_WQ(owp, u.ld); break; } case 't': // FALLTHRU // Time case '#': { // Unsigned decimal _vl_vsss_skipspace(fp, floc, fromp, fstr); - _vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_"); - if (!tmp[0]) goto done; + _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_"); + if (!t_tmp[0]) goto done; QData ld = 0; - sscanf(tmp, "%30" VL_PRI64 "u", &ld); + sscanf(t_tmp, "%30" VL_PRI64 "u", &ld); VL_SET_WQ(owp, ld); break; } case 'b': { _vl_vsss_skipspace(fp, floc, fromp, fstr); - _vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "01xXzZ?_"); - if (!tmp[0]) goto done; - _vl_vsss_based(owp, obits, 1, tmp, 0, strlen(tmp)); + _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01xXzZ?_"); + if (!t_tmp[0]) goto done; + _vl_vsss_based(owp, obits, 1, t_tmp, 0, strlen(t_tmp)); break; } case 'o': { _vl_vsss_skipspace(fp, floc, fromp, fstr); - _vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "01234567xXzZ?_"); - if (!tmp[0]) goto done; - _vl_vsss_based(owp, obits, 3, tmp, 0, strlen(tmp)); + _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01234567xXzZ?_"); + if (!t_tmp[0]) goto done; + _vl_vsss_based(owp, obits, 3, t_tmp, 0, strlen(t_tmp)); break; } case 'x': { _vl_vsss_skipspace(fp, floc, fromp, fstr); - _vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789abcdefABCDEFxXzZ?_"); - if (!tmp[0]) goto done; - _vl_vsss_based(owp, obits, 4, tmp, 0, strlen(tmp)); + _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, + "0123456789abcdefABCDEFxXzZ?_"); + if (!t_tmp[0]) goto done; + _vl_vsss_based(owp, obits, 4, t_tmp, 0, strlen(t_tmp)); break; } case 'u': { @@ -1205,7 +1206,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf if (obits == 0) { // Due to inIgnore } else if (obits == -1) { // string std::string* p = va_arg(ap, std::string*); - *p = tmp; + *p = t_tmp; } else if (obits <= VL_BYTESIZE) { CData* p = va_arg(ap, CData*); *p = owp[0]; @@ -1329,58 +1330,58 @@ void VL_FCLOSE_I(IData fdi) VL_MT_SAFE { void VL_FFLUSH_ALL() VL_MT_SAFE { fflush(stdout); } void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) VL_MT_SAFE { - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - _VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str()); + _VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str()); } void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) VL_MT_SAFE { - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - _VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str()); + _VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str()); } void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) VL_MT_SAFE { - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - _VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str()); + _VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str()); } void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) VL_MT_SAFE { - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - _VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str()); + _VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str()); } void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) VL_MT_SAFE { - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - _VL_STRING_TO_VINT(obits, destp, output.length(), output.c_str()); + _VL_STRING_TO_VINT(obits, destp, t_output.length(), t_output.c_str()); } void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, ...) VL_MT_SAFE { @@ -1393,38 +1394,38 @@ void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, . } std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE { - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - return output; + return t_output; } void VL_WRITEF(const char* formatp, ...) VL_MT_SAFE { - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - VL_PRINTF_MT("%s", output.c_str()); + VL_PRINTF_MT("%s", t_output.c_str()); } void VL_FWRITEF(IData fpi, const char* formatp, ...) VL_MT_SAFE { // While threadsafe, each thread can only access different file handles - static VL_THREAD_LOCAL std::string output; // static only for speed - output = ""; + static VL_THREAD_LOCAL std::string t_output; // static only for speed + t_output = ""; va_list ap; va_start(ap, formatp); - _vl_vsformat(output, formatp, ap); + _vl_vsformat(t_output, formatp, ap); va_end(ap); - VerilatedImp::fdWrite(fpi, output); + VerilatedImp::fdWrite(fpi, t_output); } IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE { @@ -1645,12 +1646,12 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE { const std::string& match = VerilatedImp::argPlusMatch(prefixp); - static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char t_outstr[VL_VALUE_STRING_MAX_WIDTH]; if (match.empty()) return nullptr; - outstr[0] = '\0'; - strncat(outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+" + t_outstr[0] = '\0'; + strncat(t_outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+" VL_VALUE_STRING_MAX_WIDTH - 1); - return outstr; + return t_outstr; } //=========================================================================== @@ -1756,31 +1757,31 @@ const char* vl_dumpctl_filenamep(bool setit, const std::string& filename) VL_MT_ static const char* memhFormat(int nBits) { assert((nBits >= 1) && (nBits <= 32)); - static VL_THREAD_LOCAL char buf[32]; + static VL_THREAD_LOCAL char t_buf[32]; switch ((nBits - 1) / 4) { - case 0: VL_SNPRINTF(buf, 32, "%%01x"); break; - case 1: VL_SNPRINTF(buf, 32, "%%02x"); break; - case 2: VL_SNPRINTF(buf, 32, "%%03x"); break; - case 3: VL_SNPRINTF(buf, 32, "%%04x"); break; - case 4: VL_SNPRINTF(buf, 32, "%%05x"); break; - case 5: VL_SNPRINTF(buf, 32, "%%06x"); break; - case 6: VL_SNPRINTF(buf, 32, "%%07x"); break; - case 7: VL_SNPRINTF(buf, 32, "%%08x"); break; + case 0: VL_SNPRINTF(t_buf, 32, "%%01x"); break; + case 1: VL_SNPRINTF(t_buf, 32, "%%02x"); break; + case 2: VL_SNPRINTF(t_buf, 32, "%%03x"); break; + case 3: VL_SNPRINTF(t_buf, 32, "%%04x"); break; + case 4: VL_SNPRINTF(t_buf, 32, "%%05x"); break; + case 5: VL_SNPRINTF(t_buf, 32, "%%06x"); break; + case 6: VL_SNPRINTF(t_buf, 32, "%%07x"); break; + case 7: VL_SNPRINTF(t_buf, 32, "%%08x"); break; default: assert(false); break; // LCOV_EXCL_LINE } - return buf; + return t_buf; } static const char* formatBinary(int nBits, vluint32_t bits) { assert((nBits >= 1) && (nBits <= 32)); - static VL_THREAD_LOCAL char buf[64]; + static VL_THREAD_LOCAL char t_buf[64]; for (int i = 0; i < nBits; i++) { bool isOne = bits & (1 << (nBits - 1 - i)); - buf[i] = (isOne ? '1' : '0'); + t_buf[i] = (isOne ? '1' : '0'); } - buf[nBits] = '\0'; - return buf; + t_buf[nBits] = '\0'; + return t_buf; } VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end) @@ -2200,7 +2201,7 @@ void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix, // Verilated:: Methods void Verilated::debug(int level) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_debug = level; if (level) { #ifdef VL_DEBUG @@ -2214,11 +2215,11 @@ void Verilated::debug(int level) VL_MT_SAFE { } } void Verilated::randReset(int val) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_randReset = val; } void Verilated::randSeed(int val) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_randSeed = val; vluint64_t newEpoch = s_s.s_randSeedEpoch + 1; if (VL_UNLIKELY(newEpoch == 0)) newEpoch = 1; @@ -2238,41 +2239,41 @@ vluint64_t Verilated::randSeedDefault64() VL_MT_SAFE { } } void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_calcUnusedSigs = flag; } void Verilated::errorCount(int val) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_errorCount = val; } void Verilated::errorCountInc() VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); ++s_s.s_errorCount; } void Verilated::errorLimit(int val) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_errorLimit = val; } void Verilated::gotFinish(bool flag) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_gotFinish = flag; } void Verilated::assertOn(bool flag) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_assertOn = flag; } void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_fatalOnVpiError = flag; } void Verilated::timeunit(int value) VL_MT_SAFE { if (value < 0) value = -value; // Stored as 0..15 - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_timeunit = value; } void Verilated::timeprecision(int value) VL_MT_SAFE { if (value < 0) value = -value; // Stored as 0..15 - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_s.s_timeprecision = value; #ifdef SYSTEMC_VERSION sc_time sc_res = sc_get_time_resolution(); @@ -2303,15 +2304,15 @@ void Verilated::timeprecision(int value) VL_MT_SAFE { #endif } void Verilated::profThreadsStart(vluint64_t flag) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_ns.s_profThreadsStart = flag; } void Verilated::profThreadsWindow(vluint64_t flag) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); s_ns.s_profThreadsWindow = flag; } void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); if (s_ns.s_profThreadsFilenamep) free(const_cast(s_ns.s_profThreadsFilenamep)); s_ns.s_profThreadsFilenamep = strdup(flagp); } @@ -2319,18 +2320,18 @@ void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE { const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE { // Returns new'ed data // Used by symbol table creation to make module names - static VL_THREAD_LOCAL char* strp = nullptr; - static VL_THREAD_LOCAL size_t len = 0; + static VL_THREAD_LOCAL char* t_strp = nullptr; + static VL_THREAD_LOCAL size_t t_len = 0; size_t newlen = strlen(n1) + strlen(n2) + strlen(delimiter) + 1; - if (!strp || newlen > len) { - if (strp) delete[] strp; - strp = new char[newlen]; - len = newlen; + if (!t_strp || newlen > t_len) { + if (t_strp) delete[] t_strp; + t_strp = new char[newlen]; + t_len = newlen; } - strcpy(strp, n1); - if (*n1) strcat(strp, delimiter); - strcat(strp, n2); - return strp; + strcpy(t_strp, n1); + if (*n1) strcat(t_strp, delimiter); + strcat(t_strp, n2); + return t_strp; } //========================================================================= @@ -2356,15 +2357,15 @@ static void runCallbacks(VoidPCbList& cbs) VL_MT_SAFE { } void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); addCb(cb, datap, g_flushCbs); } void Verilated::removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); removeCb(cb, datap, g_flushCbs); } void Verilated::runFlushCallbacks() VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); runCallbacks(g_flushCbs); fflush(stderr); fflush(stdout); @@ -2375,15 +2376,15 @@ void Verilated::runFlushCallbacks() VL_MT_SAFE { } void Verilated::addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); addCb(cb, datap, g_exitCbs); } void Verilated::removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); removeCb(cb, datap, g_exitCbs); } void Verilated::runExitCallbacks() VL_MT_SAFE { - const VerilatedLockGuard lock(m_mutex); + const VerilatedLockGuard lock(s_mutex); runCallbacks(g_exitCbs); } @@ -2399,11 +2400,11 @@ void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE { const char* Verilated::commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE { const std::string& match = VerilatedImp::argPlusMatch(prefixp); - static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char t_outstr[VL_VALUE_STRING_MAX_WIDTH]; if (match.empty()) return ""; - outstr[0] = '\0'; - strncat(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH - 1); - return outstr; + t_outstr[0] = '\0'; + strncat(t_outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH - 1); + return t_outstr; } void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE { diff --git a/include/verilated.h b/include/verilated.h index a9f59436f..d8e8badb0 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -371,7 +371,7 @@ public: class Verilated final { // MEMBERS // Slow path variables - static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED + static VerilatedMutex s_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED static struct Serialized { // All these members serialized/deserialized // Fast path diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 4b47a6c62..fe730dbfa 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -159,9 +159,9 @@ public: const VerilatedScope* scopep() const { return m_scopep; } virtual const char* name() const override { return m_varp->name(); } virtual const char* fullname() const override { - static VL_THREAD_LOCAL std::string out; - out = std::string(m_scopep->name()) + "." + name(); - return out.c_str(); + static VL_THREAD_LOCAL std::string t_out; + t_out = std::string(m_scopep->name()) + "." + name(); + return t_out.c_str(); } }; @@ -252,9 +252,9 @@ public: virtual const VerilatedRange* rangep() const override { return &get_range(); } virtual const char* name() const override { return m_varp->name(); } virtual const char* fullname() const override { - static VL_THREAD_LOCAL std::string out; - out = std::string(m_scopep->name()) + "." + name(); - return out.c_str(); + static VL_THREAD_LOCAL std::string t_out; + t_out = std::string(m_scopep->name()) + "." + name(); + return t_out.c_str(); } void* prevDatap() const { return m_prevDatap; } void* varDatap() const { return m_varDatap; } @@ -282,11 +282,11 @@ public: virtual vluint32_t size() const override { return varp()->packed().elements(); } virtual const VerilatedRange* rangep() const override { return &(varp()->packed()); } virtual const char* fullname() const override { - static VL_THREAD_LOCAL std::string out; + static VL_THREAD_LOCAL std::string t_out; char num[20]; sprintf(num, "%d", m_index); - out = std::string(scopep()->name()) + "." + name() + "[" + num + "]"; - return out.c_str(); + t_out = std::string(scopep()->name()) + "." + name() + "[" + num + "]"; + return t_out.c_str(); } }; @@ -568,14 +568,14 @@ public: } void setMessage(const std::string& file, PLI_INT32 line, const char* message, ...) { // message cannot be a const string& as va_start cannot use a reference - static VL_THREAD_LOCAL std::string filehold; + static VL_THREAD_LOCAL std::string t_filehold; va_list args; va_start(args, message); VL_VSNPRINTF(m_buff, sizeof(m_buff), message, args); va_end(args); m_errorInfo.state = vpiPLI; - filehold = file; - setError((PLI_BYTE8*)m_buff, nullptr, const_cast(filehold.c_str()), line); + t_filehold = file; + setError((PLI_BYTE8*)m_buff, nullptr, const_cast(t_filehold.c_str()), line); } p_vpi_error_info getError() { if (m_flag) return &m_errorInfo; @@ -1419,34 +1419,34 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep, const char* fullname) { if (!vl_check_format(varp, valuep, fullname, true)) return; // Maximum required size is for binary string, one byte per bit plus null termination - static VL_THREAD_LOCAL char outStr[1 + VL_MULS_MAX_WORDS * 32]; + static VL_THREAD_LOCAL char t_outStr[1 + VL_MULS_MAX_WORDS * 32]; // cppcheck-suppress variableScope - static VL_THREAD_LOCAL int outStrSz = sizeof(outStr) - 1; + static VL_THREAD_LOCAL int t_outStrSz = sizeof(t_outStr) - 1; // We used to presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal // This may cause backward compatibility issues with older code. if (valuep->format == vpiVectorVal) { // Vector pointer must come from our memory pool // It only needs to persist until the next vpi_get_value - static VL_THREAD_LOCAL t_vpi_vecval out[VL_MULS_MAX_WORDS * 2]; - valuep->value.vector = out; + static VL_THREAD_LOCAL t_vpi_vecval t_out[VL_MULS_MAX_WORDS * 2]; + valuep->value.vector = t_out; if (varp->vltype() == VLVT_UINT8) { - out[0].aval = *(reinterpret_cast(varDatap)); - out[0].bval = 0; + t_out[0].aval = *(reinterpret_cast(varDatap)); + t_out[0].bval = 0; return; } else if (varp->vltype() == VLVT_UINT16) { - out[0].aval = *(reinterpret_cast(varDatap)); - out[0].bval = 0; + t_out[0].aval = *(reinterpret_cast(varDatap)); + t_out[0].bval = 0; return; } else if (varp->vltype() == VLVT_UINT32) { - out[0].aval = *(reinterpret_cast(varDatap)); - out[0].bval = 0; + t_out[0].aval = *(reinterpret_cast(varDatap)); + t_out[0].bval = 0; return; } else if (varp->vltype() == VLVT_UINT64) { QData data = *(reinterpret_cast(varDatap)); - out[1].aval = static_cast(data >> 32ULL); - out[1].bval = 0; - out[0].aval = static_cast(data); - out[0].bval = 0; + t_out[1].aval = static_cast(data >> 32ULL); + t_out[1].bval = 0; + t_out[0].aval = static_cast(data); + t_out[0].bval = 0; return; } else if (varp->vltype() == VLVT_WDATA) { int words = VL_WORDS_I(varp->packed().elements()); @@ -1457,47 +1457,47 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep, } WDataInP datap = (reinterpret_cast(varDatap)); for (int i = 0; i < words; ++i) { - out[i].aval = datap[i]; - out[i].bval = 0; + t_out[i].aval = datap[i]; + t_out[i].bval = 0; } return; } } else if (valuep->format == vpiBinStrVal) { - valuep->value.str = outStr; + valuep->value.str = t_outStr; int bits = varp->packed().elements(); CData* datap = (reinterpret_cast(varDatap)); int i; - if (bits > outStrSz) { + if (bits > t_outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. - bits = outStrSz; + bits = t_outStrSz; _VL_VPI_WARNING( __FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz, + VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, t_outStrSz, VL_MULS_MAX_WORDS, bits); } for (i = 0; i < bits; ++i) { char val = (datap[i >> 3] >> (i & 7)) & 1; - outStr[bits - i - 1] = val ? '1' : '0'; + t_outStr[bits - i - 1] = val ? '1' : '0'; } - outStr[i] = '\0'; + t_outStr[i] = '\0'; return; } else if (valuep->format == vpiOctStrVal) { - valuep->value.str = outStr; + valuep->value.str = t_outStr; int chars = (varp->packed().elements() + 2) / 3; int bytes = VL_BYTES_I(varp->packed().elements()); CData* datap = (reinterpret_cast(varDatap)); int i; - if (chars > outStrSz) { + if (chars > t_outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. _VL_VPI_WARNING( __FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz, + VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, t_outStrSz, VL_MULS_MAX_WORDS, chars); - chars = outStrSz; + chars = t_outStrSz; } for (i = 0; i < chars; ++i) { div_t idx = div(i * 3, 8); @@ -1518,44 +1518,44 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep, val &= (1 << rem) - 1; } } - outStr[chars - i - 1] = '0' + (val & 7); + t_outStr[chars - i - 1] = '0' + (val & 7); } - outStr[i] = '\0'; + t_outStr[i] = '\0'; return; } else if (valuep->format == vpiDecStrVal) { - valuep->value.str = outStr; + valuep->value.str = t_outStr; // outStrSz does not include nullptr termination so add one if (varp->vltype() == VLVT_UINT8) { - VL_SNPRINTF(outStr, outStrSz + 1, "%hhu", + VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%hhu", static_cast(*(reinterpret_cast(varDatap)))); return; } else if (varp->vltype() == VLVT_UINT16) { - VL_SNPRINTF(outStr, outStrSz + 1, "%hu", + VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%hu", static_cast(*(reinterpret_cast(varDatap)))); return; } else if (varp->vltype() == VLVT_UINT32) { - VL_SNPRINTF(outStr, outStrSz + 1, "%u", + VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%u", static_cast(*(reinterpret_cast(varDatap)))); return; } else if (varp->vltype() == VLVT_UINT64) { - VL_SNPRINTF(outStr, outStrSz + 1, "%llu", + VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%llu", static_cast(*(reinterpret_cast(varDatap)))); return; } } else if (valuep->format == vpiHexStrVal) { - valuep->value.str = outStr; + valuep->value.str = t_outStr; int chars = (varp->packed().elements() + 3) >> 2; CData* datap = (reinterpret_cast(varDatap)); int i; - if (chars > outStrSz) { + if (chars > t_outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. _VL_VPI_WARNING( __FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz, + VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, t_outStrSz, VL_MULS_MAX_WORDS, chars); - chars = outStrSz; + chars = t_outStrSz; } for (i = 0; i < chars; ++i) { char val = (datap[i >> 1] >> ((i & 1) << 2)) & 15; @@ -1568,35 +1568,35 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep, val &= (1 << rem) - 1; } } - outStr[chars - i - 1] = "0123456789abcdef"[static_cast(val)]; + t_outStr[chars - i - 1] = "0123456789abcdef"[static_cast(val)]; } - outStr[i] = '\0'; + t_outStr[i] = '\0'; return; } else if (valuep->format == vpiStringVal) { if (varp->vltype() == VLVT_STRING) { valuep->value.str = reinterpret_cast(varDatap); return; } else { - valuep->value.str = outStr; + valuep->value.str = t_outStr; int bytes = VL_BYTES_I(varp->packed().elements()); CData* datap = (reinterpret_cast(varDatap)); int i; - if (bytes > outStrSz) { + if (bytes > t_outStrSz) { // limit maximum size of output to size of buffer to prevent overrun. _VL_VPI_WARNING( __FILE__, __LINE__, "%s: Truncating string value of %s for %s" " as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz, - VL_MULS_MAX_WORDS, bytes); - bytes = outStrSz; + VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, + t_outStrSz, VL_MULS_MAX_WORDS, bytes); + bytes = t_outStrSz; } for (i = 0; i < bytes; ++i) { char val = datap[bytes - i - 1]; // other simulators replace [leading?] zero chars with spaces, replicate here. - outStr[i] = val ? val : ' '; + t_outStr[i] = val ? val : ' '; } - outStr[i] = '\0'; + t_outStr[i] = '\0'; return; } } else if (valuep->format == vpiIntVal) { diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index a2b6f8519..db5a803f5 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -1275,13 +1275,13 @@ class EmitVarTspSorter final : public V3TSP::TspStateBase { private: // MEMBERS const MTaskIdSet& m_mtaskIds; // Mtask we're ordering - static unsigned m_serialNext; // Unique ID to establish serial order + static unsigned s_serialNext; // Unique ID to establish serial order unsigned m_serial; // Serial ordering public: // CONSTRUCTORS explicit EmitVarTspSorter(const MTaskIdSet& mtaskIds) : m_mtaskIds(mtaskIds) { // Cannot be {} or GCC 4.8 false warning - m_serial = ++m_serialNext; // Cannot be ()/{} or GCC 4.8 false warning + m_serial = ++s_serialNext; // Cannot be ()/{} or GCC 4.8 false warning } virtual ~EmitVarTspSorter() = default; // METHODS @@ -1308,7 +1308,7 @@ public: } }; -unsigned EmitVarTspSorter::m_serialNext = 0; +unsigned EmitVarTspSorter::s_serialNext = 0; //###################################################################### // Internal EmitC implementation diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 140815c74..95348cbbb 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -499,7 +499,7 @@ public: TspTestState(unsigned xpos, unsigned ypos) : m_xpos{xpos} , m_ypos{ypos} - , m_serial{++m_serialNext} {} + , m_serial{++s_serialNext} {} ~TspTestState() = default; virtual int cost(const TspStateBase* otherp) const override { return cost(dynamic_cast(otherp)); @@ -530,10 +530,10 @@ private: unsigned m_xpos; unsigned m_ypos; unsigned m_serial; - static unsigned m_serialNext; + static unsigned s_serialNext; }; -unsigned TspTestState::m_serialNext = 0; +unsigned TspTestState::s_serialNext = 0; void V3TSP::selfTestStates() { // Linear test -- coords all along the x-axis From e3c32adad45686785db2f00064c774aa4fed3a08 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 1 Dec 2020 19:32:01 -0500 Subject: [PATCH 85/91] Rename static/thread misnamed variables. No functional change. --- include/verilated.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/verilated.cpp b/include/verilated.cpp index 6d2dbcb21..101054439 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -75,7 +75,7 @@ VerilatedImp::VerilatedImpU VerilatedImp::s_s; struct VerilatedImpInitializer { VerilatedImpInitializer() { VerilatedImp::setup(); } ~VerilatedImpInitializer() { VerilatedImp::teardown(); } -} g_VerilatedImpInitializer; +} s_VerilatedImpInitializer; //=========================================================================== // User definable functions @@ -2340,8 +2340,8 @@ const char* Verilated::catName(const char* n1, const char* n2, const char* delim // Keeping these out of class Verilated to avoid having to include // in verilated.h (for compilation speed) typedef std::list> VoidPCbList; -static VoidPCbList g_flushCbs; -static VoidPCbList g_exitCbs; +static VoidPCbList s_flushCbs; +static VoidPCbList s_exitCbs; static void addCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) { std::pair pair(cb, datap); @@ -2358,15 +2358,15 @@ static void runCallbacks(VoidPCbList& cbs) VL_MT_SAFE { void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { const VerilatedLockGuard lock(s_mutex); - addCb(cb, datap, g_flushCbs); + addCb(cb, datap, s_flushCbs); } void Verilated::removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { const VerilatedLockGuard lock(s_mutex); - removeCb(cb, datap, g_flushCbs); + removeCb(cb, datap, s_flushCbs); } void Verilated::runFlushCallbacks() VL_MT_SAFE { const VerilatedLockGuard lock(s_mutex); - runCallbacks(g_flushCbs); + runCallbacks(s_flushCbs); fflush(stderr); fflush(stdout); // When running internal code coverage (gcc --coverage, as opposed to @@ -2377,15 +2377,15 @@ void Verilated::runFlushCallbacks() VL_MT_SAFE { void Verilated::addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { const VerilatedLockGuard lock(s_mutex); - addCb(cb, datap, g_exitCbs); + addCb(cb, datap, s_exitCbs); } void Verilated::removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { const VerilatedLockGuard lock(s_mutex); - removeCb(cb, datap, g_exitCbs); + removeCb(cb, datap, s_exitCbs); } void Verilated::runExitCallbacks() VL_MT_SAFE { const VerilatedLockGuard lock(s_mutex); - runCallbacks(g_exitCbs); + runCallbacks(s_exitCbs); } const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; } From faa5edc06876aa65fdfe2e5ea5fad1d09cde7c03 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 2 Dec 2020 07:37:34 -0500 Subject: [PATCH 86/91] Add TspStateBase destructor (#2620). --- src/V3TSP.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/V3TSP.h b/src/V3TSP.h index b3cc20808..e44295150 100644 --- a/src/V3TSP.h +++ b/src/V3TSP.h @@ -39,6 +39,8 @@ public: // key maps so that iteration is stable, without relying // on pointer values that could lead to nondeterminism. virtual bool operator<(const TspStateBase& otherp) const = 0; + + virtual ~TspStateBase() = default; }; typedef std::vector StateVec; From 1e69167191ff3ec71dc55a3b4ef5fcc2eb626b12 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 2 Dec 2020 18:51:19 -0500 Subject: [PATCH 87/91] Internals: Move function in V3Width. No functional change. --- src/V3Width.cpp | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index a781e4c87..5fcac846d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2488,33 +2488,16 @@ private: return; } // Need a runtime lookup table. Yuk. - // Most enums unless overridden are 32 bits, so we size array - // based on max enum value used. - // Ideally we would have a fast algorithm when a number is - // of small width and complete and so can use an array, and - // a map for when the value is many bits and sparse. - uint64_t msbdim = 0; - { - for (AstEnumItem* itemp = adtypep->itemsp(); itemp; - itemp = VN_CAST(itemp->nextp(), EnumItem)) { - const AstConst* vconstp = VN_CAST(itemp->valuep(), Const); - UASSERT_OBJ(vconstp, nodep, "Enum item without constified value"); - if (vconstp->toUQuad() >= msbdim) msbdim = vconstp->toUQuad(); - } - if (adtypep->itemsp()->width() > 64 || msbdim >= (1 << 16)) { - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: enum next/prev method on enum with > 10 bits"); - return; - } - } + uint64_t msbdim = enumMaxValue(nodep, adtypep); int selwidth = V3Number::log2b(msbdim) + 1; // Width to address a bit AstVar* varp = enumVarp(adtypep, attrType, (1ULL << selwidth) - 1); AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); AstNode* newp = new AstArraySel( nodep->fileline(), varrefp, - // Select in case widths are - // off due to msblen!=width + // Select in case widths are off due to msblen!=width + // We return "random" values if outside the range, which is fine + // as next/previous on illegal values just need something good out new AstSel(nodep->fileline(), nodep->fromp()->unlinkFrBack(), 0, selwidth)); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -5267,7 +5250,8 @@ private: << " expected non-interface on " << side << " but '" << underp->name() << "' is an interface."); } else { - // Hope it just works out + // Hope it just works out (perhaps a cast will deal with it) + underp = userIterateSubtreeReturnEdits(underp, WidthVP(expDTypep, FINAL).p()); } } return underp; @@ -5717,6 +5701,26 @@ private: m_tableMap.insert(make_pair(make_pair(nodep, attrType), varp)); return varp; } + uint64_t enumMaxValue(const AstNode* errNodep, const AstEnumDType* adtypep) { + // Most enums unless overridden are 32 bits, so we size array + // based on max enum value used. + // Ideally we would have a fast algorithm when a number is + // of small width and complete and so can use an array, and + // a map for when the value is many bits and sparse. + uint64_t maxval = 0; + for (const AstEnumItem* itemp = adtypep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), EnumItem)) { + const AstConst* vconstp = VN_CAST(itemp->valuep(), Const); + UASSERT_OBJ(vconstp, errNodep, "Enum item without constified value"); + if (vconstp->toUQuad() >= maxval) maxval = vconstp->toUQuad(); + } + if (adtypep->itemsp()->width() > 64 || maxval >= (1 << 16)) { + errNodep->v3warn(E_UNSUPPORTED, + "Unsupported: enum next/prev method on enum with > 10 bits"); + return 0; + } + return maxval; + } AstVar* enumVarp(AstEnumDType* nodep, AstAttrType attrType, uint32_t msbdim) { // Return a variable table which has specified dimension properties for this variable const auto pos = m_tableMap.find(make_pair(nodep, attrType)); From fa20614277e8454c9da868934ccc5d78a1056ad5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 2 Dec 2020 19:20:03 -0500 Subject: [PATCH 88/91] Fix Ubuntu 16.04 LTS warning --- src/V3Partition.cpp | 3 ++- src/V3SplitVar.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 78ee3e236..c48f8737a 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -306,7 +306,8 @@ private: } void go() { // Generate a pseudo-random graph - std::array rngState = {0x12345678ULL, 0x9abcdef0ULL}; + std::array rngState + = {{0x12345678ULL, 0x9abcdef0ULL}}; // GCC 3.8.0 wants {{}} // Create 50 vertices for (auto& i : m_vx) i = new V3GraphVertex(&m_graph); // Create 250 edges at random. Edges must go from diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 3d36af63d..83ae80e89 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -1006,7 +1006,8 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl { UASSERT_OBJ(varp->attrSplitVar(), varp, "split_var attribute must be attached"); std::array consts - = {VN_CAST(nodep->lsbp(), Const), VN_CAST(nodep->widthp(), Const)}; + = {{VN_CAST(nodep->lsbp(), Const), + VN_CAST(nodep->widthp(), Const)}}; // GCC 3.8.0 wants {{}} if (consts[0] && consts[1]) { // OK refit->second.append( PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lsb(), From 016611021d6f243f41fc906d756ff96275842337 Mon Sep 17 00:00:00 2001 From: Yuri Victorovich Date: Wed, 2 Dec 2020 19:26:42 -0500 Subject: [PATCH 89/91] Fix the default GNU Make executable name on FreeBSD (#2553) --- src/V3Options.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 3b49377ed..8ccbd5c56 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -603,7 +603,11 @@ string V3Options::getenvBuiltins(const string& var) { } } +#ifdef __FreeBSD__ +string V3Options::getenvMAKE() { return V3Os::getenvStr("MAKE", "gmake"); } +#else string V3Options::getenvMAKE() { return V3Os::getenvStr("MAKE", "make"); } +#endif string V3Options::getenvPERL() { // return V3Os::getenvStr("PERL", "perl"); From 80564a8f89363f9fd667503dc200d7b8201569af Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 2 Dec 2020 20:06:07 -0500 Subject: [PATCH 90/91] Remove vgen test to avoid Bit::Vector for testing. --- ci/docker/buildenv/Dockerfile | 2 +- ci/travis-install.bash | 1 - docs/install.adoc | 1 - docs/internals.adoc | 2 - test_regress/t/t_vgen.pl | 32 - test_regress/vgen.pl | 1068 --------------------------------- 6 files changed, 1 insertion(+), 1105 deletions(-) delete mode 100755 test_regress/t/t_vgen.pl delete mode 100755 test_regress/vgen.pl diff --git a/ci/docker/buildenv/Dockerfile b/ci/docker/buildenv/Dockerfile index f3008bb97..6f9dd3539 100644 --- a/ci/docker/buildenv/Dockerfile +++ b/ci/docker/buildenv/Dockerfile @@ -40,7 +40,7 @@ RUN apt-get update \ WORKDIR /tmp -RUN cpan install -fi Unix::Processors Parallel::Forker Bit::Vector +RUN cpan install -fi Unix::Processors Parallel::Forker RUN git clone https://github.com/veripool/vcddiff.git && \ make -C vcddiff && \ diff --git a/ci/travis-install.bash b/ci/travis-install.bash index 27adf42ec..9178e66b5 100755 --- a/ci/travis-install.bash +++ b/ci/travis-install.bash @@ -94,7 +94,6 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then if [ "$TRAVIS_DIST" != "trusty" ]; then TRAVIS_CPAN_REPO=https://cpan.org fi - # Not listing Bit::Vector as slow to install, and only skips one test yes yes | sudo cpan -M $TRAVIS_CPAN_REPO -fi Unix::Processors Parallel::Forker install-vcddiff else diff --git a/docs/install.adoc b/docs/install.adoc index dfe5c0e75..65ae632f3 100644 --- a/docs/install.adoc +++ b/docs/install.adoc @@ -102,7 +102,6 @@ Those developing Verilator itself may also want these (see internals.adoc): cpan install Pod::Perldoc cpan install Unix::Processors cpan install Parallel::Forker - cpan install Bit::Vector ==== Install SystemC diff --git a/docs/internals.adoc b/docs/internals.adoc index 557d33b5e..aab4d8099 100644 --- a/docs/internals.adoc +++ b/docs/internals.adoc @@ -628,8 +628,6 @@ https://github.com/veripool/vcddiff * Cmake for build paths that use it. -* Bit::Vector to test vgen.pl - === Controlling the Test Driver Test drivers are written in PERL. All invoke the main test driver script, diff --git a/test_regress/t/t_vgen.pl b/test_regress/t/t_vgen.pl deleted file mode 100755 index a488b5a3f..000000000 --- a/test_regress/t/t_vgen.pl +++ /dev/null @@ -1,32 +0,0 @@ -#!/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); - -if (eval "use Bit::Vector; return 2;" != 2) { - skip("Vgen test requires Bit::Vector"); -} else { - - top_filename("$Self->{obj_dir}/vgen.v"); - - run(cmd => ["./vgen.pl", - "-o $Self->{top_filename}", - #"--seed 0", - ]); - - compile( - ); - - execute( - check_finished => 1, - ); -} -ok(1); -1; diff --git a/test_regress/vgen.pl b/test_regress/vgen.pl deleted file mode 100755 index 112e083ba..000000000 --- a/test_regress/vgen.pl +++ /dev/null @@ -1,1068 +0,0 @@ -#!/usr/bin/env perl -# See copyright, etc in below POD section. -###################################################################### - -require 5.006_001; -use warnings; - -use Getopt::Long; -use IO::File; -use Pod::Usage; -use Data::Dumper; $Data::Dumper::Indent = 1; -use Bit::Vector; -use strict; -use vars qw($Debug); - -our @Orig_ARGV = @ARGV; -our $Rerun_Args = $0." ".join(' ',@Orig_ARGV); -$Rerun_Args =~ s/\s+$//; - -use vars qw(@Blocks - %Vars - %VarAttrs - %VarsBlock - %Tree - @Commit - $Depth - %IdWidth - %Ops); - -#====================================================================== - -# width=> Number of bits the output size is, 0=you tell me. -# func=> What to put in output file -# signed=> 0=unsigned output, 1=signed output, '%1'=signed if op1 signed -# lsb=> LSB for variable declarations -# em=> How to calculate emulated return value -# %w Width of this output op ($treeref->{width}) -# %v Output value ($treeref->{val}) -# %1r First operand ($treeref->{op1}) -# %1v First operand value ($treeref->{op1}{val}) -# %1w First operand width ($treeref->{op1}{width}) - -our $Raise_Weight_Max = 50; -%Ops = -( - 'VCONST'=> {weight=>1&&20, width=>0, sc=>1, terminal=>1, v=>'%v', }, - 'VIDNEW'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'%i', }, - 'VIDOLD'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', }, - 'VIDSAME'=> {weight=>1&&20, width=>0, sc=>1, terminal=>0, v=>'%i', }, - 'VRANGE'=> {weight=>1&&30, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2:%3]', }, - 'VBITSEL'=> {weight=>1&&10, width=>1, signed=>0,sc=>0, terminal=>0, v=>'%i[%2]', }, - 'VBITSELP'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2+:%3]', }, - 'VBITSELM'=> {weight=>1&&10, width=>0, signed=>0,sc=>0, terminal=>0, v=>'%i[%2-:%3]', }, - # Unary - 'VEXTEND'=> {weight=>1&&3, width=>-2, signed=>0,sc=>0, terminal=>0, v=>'{%xd\'h0,%1}', }, - 'VLOGNOT'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(! %1)', }, - 'VREDAND'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(& %1)', }, - 'VREDOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(| %1)', }, - 'VREDNAND'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(~& %1)', }, - 'VREDNOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(~| %1)', }, - 'VREDXNOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^~ %1)', }, - 'VREDXOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^ %1)', }, - 'VNOT'=> {weight=>1&&3, width=>0, sc=>1, terminal=>0, v=>'(~ %1)', }, - 'VNEGATE'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(- %1)', }, - 'VCOUNTONES'=> {weight=>0&&2, width=>32, signed=>0, sc=>0, terminal=>0, v=>'\$countones(%1)', }, # No ncv support - 'VONEHOT'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot(%1)', }, # No ncv support - 'VONEHOT0'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot0(%1)', }, # No ncv support - # Binary - 'VAND'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 & %2)', }, - 'VOR'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 | %2)', }, - 'VNAND'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ~& %2)', }, #FIX vcs bug! - 'VNOR'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ~| %2)', }, #FIX vcs bug! - 'VXOR'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(%1 ^ %2)', }, - 'VXNOR'=> {weight=>1&&0, width=>0, sc=>0, terminal=>0, v=>'(%1 ^~ %2)', }, #FIX vcs bug! - 'VEQ'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 == %2)', }, - 'VNEQ'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 != %2)', }, - 'VGT'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 > %2)', }, - 'VGTE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 >= %2)', }, - 'VLT'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 < %2)', }, - 'VLTE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 <= %2)', }, - 'VEQCASE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 === %2)', }, # FIX just a = for now - 'VNEQCASE'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 !== %2)', }, # FIX just a != for now - 'VLOGOR'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 || %2)', }, - 'VLOGAND'=> {weight=>1&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(%1 && %2)', }, - 'VADD'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 + %2)', }, - 'VSUB'=> {weight=>1&&10, width=>0, sc=>1, terminal=>0, v=>'(%1 - %2)', }, - 'VMUL'=> {weight=>1&&15,width=>0, sc=>1, terminal=>0, v=>'(%1 * %2)', }, # High % as rarely applyable - # Unspecified behavior with == (a-signed / b) -- see t_math_signed5.v test - 'VDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 / %2))', }, - 'VMODDIV'=> {weight=>1&&8, width=>0, signed=>0, sc=>1, terminal=>0, v=>'((%2)==%xw\'h0 ? %xw\'%xsh0:(%1 %% %2))', }, - #'VPOW'=> {weight=>2&&0,width=>-64, sc=>0, terminal=>0, v=>'(%1 ** %2)', }, - 'VSHIFTL'=> {weight=>1&&8, width=>0, signed=>0, sc=>0, terminal=>0, v=>'(%1 << %2)', }, - 'VSHIFTLS'=> {weight=>1&&8, width=>0, signed=>1, sc=>0, terminal=>0, v=>'(%1 <<< %2)', }, - 'VSHIFTR'=> {weight=>1&&8, width=>0, signed=>0, sc=>0, terminal=>0, v=>'(%1 >> %2)', }, - 'VSHIFTRS'=> {weight=>1&&15,width=>0, signed=>1, sc=>0, terminal=>0, v=>'(%1 >>> %2)', }, # ShiftR seems to sign extend differently for <=32 and >32 bits - 'VCONCAT'=> {weight=>1&&4, width=>-2,signed=>0, sc=>0, terminal=>0, v=>'{%1,%2}', }, - 'VREPLIC'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'{%1{%2}}', }, - 'VREPLIC1W'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'{%1{%2}}', }, - 'VSIGNED'=> {weight=>1&&2, width=>0, signed=>1, sc=>0, terminal=>0, v=>'\$signed(%1)', }, - 'VUNSIGNED'=> {weight=>1&&2, width=>0, signed=>0, sc=>0, terminal=>0, v=>'\$unsigned(%1)', }, - # Triops - 'VCOND'=> {weight=>1&&4, width=>0, sc=>0, terminal=>0, v=>'(%1 ? %2 : %3)', }, - # Control flow - #VIF - #VFOR - #VCASE - #VCASEX - #VCASEZ - ); - -my %ops2 = -( - 'VCONST'=> {pl=>'', rnd=>'rnd_const(%tr);'}, - 'VIDNEW'=> {pl=>'%tv=$Vars{%i}{val};', - rnd=>'%i=next_id(%tw);' - .' $Vars{%i}=gen_leaf(width=>%tw,trunc=>1,signed=>%tg);' - .' $VarAttrs{%i}{lsb} = rnd_lsb();' - .' id_commit(%tr,"%i");1;',}, - 'VIDOLD'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_old(%tr);', ok_id_width=>1,}, - 'VIDSAME'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_same(%tr);', ok_id_width=>1,}, - # These create IDs they then extract from - 'VRANGE'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});', - rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' - .' my $lsb=rnd(128-%tw); my $msb=$lsb+%tw-1;' - .' %2r=val_leaf($msb); %3r=val_leaf($lsb);' - .' $Vars{%i}=gen_leaf(width=>($msb+1));'}, - 'VBITSEL'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%2v,$VarAttrs{%i}{lsb});', - rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' - .' my $wid=min(128,rnd_width()|3);' - .' %2r=gen_leaf(width=>(log2($wid)-1),signed=>0);' - .' $Vars{%i}=gen_leaf(width=>$wid);'}, - 'VBITSELP'=> {pl=>'VBITSELP(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});', - rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' - .' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-%tw; %2r=(($maxval<4)?val_leaf($maxval):gen_leaf(width=>(log2($maxval)-1),signed=>0));' - .' $Vars{%i}=gen_leaf(width=>$wid);'}, - 'VBITSELM'=> {pl=>'VBITSELM(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});', - rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();' - .' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-1; my $minval=%tw-1; %2r=val_leaf(rnd($maxval-$minval)+$minval);' - .' $Vars{%i}=gen_leaf(width=>$wid);'}, # No easy way to make expr with specified minimum - # Unary - 'VEXTEND'=> {pl=>'VRESIZE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>rnd_width(%tw-1));'}, - 'VLOGNOT'=> {pl=>'VLOGNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VREDAND'=> {pl=>'VREDAND (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VREDOR'=> {pl=>'VREDOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VREDNAND'=> {pl=>'VREDNAND (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VREDNOR'=> {pl=>'VREDNOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VREDXOR'=> {pl=>'VREDXOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VREDXNOR'=> {pl=>'VREDXNOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VNOT'=> {pl=>'VNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VNEGATE'=> {pl=>'VNEGATE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VCOUNTONES'=> {pl=>'VCOUNTONES(%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VONEHOT'=> {pl=>'VONEHOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - 'VONEHOT0'=> {pl=>'VONEHOT0 (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'}, - # Binary - 'VAND'=> {pl=>'VAND (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VOR'=> {pl=>'VOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VNAND'=> {pl=>'VNAND (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VNOR'=> {pl=>'VNOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VXOR'=> {pl=>'VXOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VXNOR'=> {pl=>'VXNOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VEQ'=> {pl=>'VEQ (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VNEQ'=> {pl=>'VNE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VGT'=> {pl=>'VGT (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VGTE'=> {pl=>'VGE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VLT'=> {pl=>'VLT (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VLTE'=> {pl=>'VLE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VEQCASE'=> {pl=>'VEQ (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VNEQCASE'=> {pl=>'VNE (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>%1w,signed=>%1g);'}, - 'VLOGOR'=> {pl=>'VLOGOR (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>0);'}, - 'VLOGAND'=> {pl=>'VLOGAND(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>0); %2r=gen_leaf(width=>0);'}, - 'VADD'=> {pl=>'VADD (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,}, - 'VSUB'=> {pl=>'VSUB (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,}, - 'VMUL'=> {pl=>'VMUL (%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);', trunc=>1,}, # Multiply generates larger width, so need truncate for safety - 'VDIV'=> {pl=>'VDIV (%tr,%1r,%2r,0);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - 'VMODDIV'=> {pl=>'VDIV (%tr,%1r,%2r,1);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>%tw,signed=>%tg);'}, - #'VPOW'=> {pl=>'VPOW (%tr,%1r,%2r);', rnd=>'%1r=gen_leaf(width=>min(%tw,6),signed=>%tg); %2r=gen_leaf(width=>min(%tw,8),signed=>%tg);', trunc=>1,}, # Generates larger width, so need truncate for safety - 'VSHIFTL'=> {pl=>'VSHIFTL(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, - 'VSHIFTLS'=> {pl=>'VSHIFTL(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, - 'VSHIFTR'=> {pl=>'VSHIFTR(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, - 'VSHIFTRS'=> {pl=>'VSHIFTRS(%tr,%1v,%2v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg); %2r=gen_leaf(width=>log2(%tw)+1,signed=>%tg);'}, - 'VCONCAT'=> {pl=>'VCONCAT(%tr,%1v,%2v);', rnd=>'my $d=(rnd(%tw-2)+1); %1r=gen_leaf(width=>$d,signed=>0); %2r=gen_leaf(width=>(%tw-$d),signed=>0);'}, - 'VREPLIC'=> {pl=>'VREPLIC(%tr,%1v,%2v);', rnd=>'my $d=rnd_rep_width(%tw); %1r=val_leaf($d); %2r=gen_leaf(width=>(%tw/$d),signed=>0);'}, - 'VREPLIC1W'=> {pl=>'VREPLIC(%tr,%1v,%2v);', rnd=>'%1r=val_leaf(%tw); %2r=gen_leaf(width=>1,signed=>0);'}, - 'VSIGNED'=> {pl=>'VCLONE (%tr,%1v,0);', rnd=>'%1r=gen_leaf(width=>%tw);'}, - 'VUNSIGNED'=> {pl=>'VCLONE (%tr,%1v,0);', rnd=>'%1r=gen_leaf(width=>%tw);'}, - # Triops - 'VCOND'=> {pl=>'VCOND(%tr,%1v,%2v,%3v);', rnd=>'%1r=gen_leaf(width=>1); %2r=gen_leaf(width=>%tw,signed=>%tg); %3r=gen_leaf(width=>%tw,signed=>%tg);'}, - ); - -foreach my $op (keys %ops2) { - while ((my $key,my $val) = each %{$ops2{$op}}) { - $Ops{$op}{$key} = $val; - } -} - -#====================================================================== -# main - -#Bit::Vector->Configuration("ops=arithmetic"); - - -my $opt_seed=5; -our $Opt_NumOps = 30; -our $Opt_Depth = 4; -our $Opt_Output; -our $Opt_Signed = 1; -our $Opt_Raise; -our $Opt_BlockStmts = 2; -our $Signed_Pct = 60; -$Debug = 0; -if (! GetOptions ( - "help" => \&usage, - "debug" => \&debug, - "depth=i" => \$Opt_Depth, - "blockstmts=i"=> \$Opt_BlockStmts, - "numops=i" => \$Opt_NumOps, - "o=s" => \$Opt_Output, - "raise=i" => \$Opt_Raise, - "seed=i" => \$opt_seed, - "signed!" => \$Opt_Signed, - "<>" => \¶meter, - )) { - usage(); -} - -if ($opt_seed==0) { - srand(); - $opt_seed = rnd(1<<20)+1; - $Rerun_Args =~ s/-seed[= ]+0/-seed=$opt_seed/; - print " $Rerun_Args\n"; -} -srand($opt_seed); -init(); -selftest(); -gentest(); -$Opt_Output or die "%Error: Need -o option,"; -write_output_v($Opt_Output); - -#---------------------------------------------------------------------- - -sub usage { - pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT); - exit(1); # Unreachable -} - -sub debug { - $Debug = 1; -} - -sub parameter { - my $param = shift; - die "%Error: Unknown parameter: $param\n"; -} - -####################################################################### -####################################################################### -####################################################################### -####################################################################### -# Global Functions - -sub init { - for my $op (keys %Ops) { - my $opref = $Ops{$op}; - $opref->{name} = $op; - gen_v($opref); - gen_pl($opref); - gen_rnd($opref); - } - raise(); -} - -sub raise { - for (my $i=0; $i<($Opt_Raise||0); $i++) { - my @ops = (values %Ops); - while (1) { - my $rndop = $ops[rnd($#ops + 1)]; - next if !$rndop->{weight}; # Don't turn on disabled ops - $rndop->{weight} += rnd($Raise_Weight_Max); - printf "\tWeight %-15s +%d\n",$rndop->{name},$rndop->{weight}; - last; - } - } -} - -sub gentest { - for (my $opn=0; $opn<$Opt_NumOps/$Opt_BlockStmts; $opn++) { - do_a_test(); - } -} - -####################################################################### -# Randomization - -sub _rnd_op_ok { - my $opref = shift; - my $paramref = shift; - return (($opref->{width} == 0 - || $opref->{width} == $paramref->{width} - # Note -2 means >, while -32 means {width}==-31 && $paramref->{width}<=31) # -31... must be <31 bits - || ($opref->{width}==-32 && $paramref->{width}<=32) # -32... must be <32 bits - || ($opref->{width}==-63 && $paramref->{width}<=63) # -63... must be <63 bits - || ($opref->{width}==-64 && $paramref->{width}<=64) # -64... must be <64 bits - || ($opref->{width}==-2 && $paramref->{width}>=2) # -2... must be >2 bits - ) - && (!$opref->{ok_id_width} || $IdWidth{$paramref->{width}}{$paramref->{signed}||0}) - && (!defined $opref->{signed} || ($opref->{signed} == ($paramref->{signed}||0))) - && (!$opref->{trunc} || $paramref->{trunc}) - && (!$opref->{opt_signed} || $Opt_Signed) - && (($Depth < $Opt_Depth && !$paramref->{need_terminal}) - || $opref->{terminal})); -} - -sub rnd_op { - my $paramref = shift; - - my $totweight = 0; - foreach my $opref (values %Ops) { - if (_rnd_op_ok($opref,$paramref)) { - $totweight += $opref->{weight}; - } - } - my $chooseweight = rnd($totweight); - $totweight = 0; - foreach my $opref (sort {$a->{name} cmp $b->{name}} values %Ops) { - if (_rnd_op_ok($opref,$paramref)) { - $totweight += $opref->{weight}; - if ($chooseweight < $totweight) { - return $opref; - } - } - } - die "%Error: No instructions match,"; -} - -sub rnd_width { - my $max = shift; - my $v = rnd(100); - my $n = (0 - || (($v<20) && 1) - || (($v<25) && 2) - || (($v<30) && 31) - || (($v<35) && 32) - || (($v<40) && 63) - || (($v<45) && 64) - || (($v<50) && 95) - || (($v<55) && 96) - || (rnd(128)+1)); - if ($max && $n>=$max) { $n = rnd($max-1)+1; } - return $n; -} - -sub rnd_rep_width { - my $out = shift; - return 1 if $out==1; - # We'd like to pick any divisor that works. - my @factors; - for (my $div=1; $div<$out; $div++) { - if (int($out/$div)==($out/$div)) { - push @factors, $div; - } - } - my $fac = $factors[rnd($#factors+1)]; - #print "RND REP $out -> $fac (@factors)\n" if $Debug; - return $fac; -} - -sub rnd_const { - my $treeref = shift; - my $width = $treeref->{width} or die; - my $v = rnd(100); - - my $val = Bit::Vector->new($width); - if ($v<25) { # zero - } elsif ($v<50) { # ones - for (my $w=0; $w<$val->Word_Size; ++$w) { - $val->Word_Store(0,~0); - } - } elsif ($v<60) { # one - $val->Word_Store(0,1); - } else { # random - for (my $w=0; $w<$val->Word_Size; ++$w) { - $val->Word_Store($w,rnd_int()); - } - } - $treeref->{val} = $val; -} - -sub rnd_int { - my $v = rnd(100); - return 0 if ($v<25); - return ~0 if ($v<50); - return 1 if ($v<60); - return rnd32(); -} - -sub rnd_lsb { - return 0; - #return rnd(8)-4; # Not working yet -} - -sub rnd { - return (int(rand($_[0]))) if ($_[0] < (1<<15)); - return (rnd32() % $_[0]); -} -sub rnd32 { - my $vp = int(rand(1<<16)); - $vp ^= (int(rand(1<<8)))<<16; # Single 1<<16 doesn't work - $vp ^= (int(rand(1<<8)))<<24; - return ($vp); -} - -####################################################################### - -our $Next_Id = 0; -sub next_id { - # Note width hasn't been determined yet - $Next_Id++; - my $id = sprintf("W%04d",$Next_Id); - return $id; -} -sub id_commit { - my $treeref = shift; - my $width = $treeref->{width}; - my $signed = $treeref->{signed}; - my $id = shift; - push @Commit, sub { - $IdWidth{$width}{$signed} = [] if !$IdWidth{$width}{$signed}; - push @{$IdWidth{$width}{$signed}}, $id; - $VarsBlock{$id}{set} = 1; - 1; - }; -} - -sub id_old { - my $treeref = shift; - my $width = $treeref->{width}; - my $signed = $treeref->{signed}; - - my $n = $#{$IdWidth{$width}{$signed}} + 1; - my $idn = rnd($n); - my $id = $IdWidth{$width}{$signed}[$idn]; - $VarsBlock{$id}{used} = 1; - return $id; -} - -sub id_same { - my $treeref = shift; - my $width = $treeref->{width}; - my $signed = $treeref->{signed}; - - my @possible; - foreach my $id (keys %VarsBlock) { - next if !$VarsBlock{$id}{used}; - my $varref = $Vars{$id}; - next if $varref->{signed} != $signed; - next if $varref->{width} != $width; - push @possible, $id; - } - my $n = $#possible + 1; - if ($n<1) { # Nothing, grab another! - return id_old($treeref,$width,$signed); - } - my $idn = rnd($n); - my $id = $possible[$idn]; - $VarsBlock{$id}{used} = 1; - return $id; -} - -sub write_output_v { - my $filename = shift; - - my $fh = IO::File->new($filename, "w") or die("%Error: $! $filename,\n"); - print $fh "// Created by: $Rerun_Args\n"; - - print $fh "module vgen (clk);\n"; - print $fh " input clk;\n"; - print $fh " reg check; initial check = '0;\n"; - print $fh ' initial $write("\n*** Vgen.v starting, seed = ',$opt_seed,'\n");',"\n"; - - print $fh " // verilator lint_off UNSIGNED\n"; - print $fh " // verilator lint_off CMPCONST\n"; - print $fh " // verilator lint_off WIDTH\n"; - print $fh "\n"; - - my $cycles = 2; - - foreach my $var (sort (keys %Vars)) { - print $fh "",decl_text ($var),"\n"; - } - - foreach my $block (@Blocks) { - print $fh "\t//".('='x60)."\n"; - my $style = rnd(100); - if ($style < 15) { - # This allows statements to get split up, and constants to propagate - print $fh " always @(", join(" or ", ('check', @{$block->{inputs}})); - print $fh ") begin : $block->{name}\n"; - print $fh @{$block->{preass}}; - print $fh " end\n"; - print $fh " always @(posedge clk) begin : $block->{name}Check\n"; - print $fh @{$block->{body}}; - print $fh " end\n"; - } - elsif ($style < 40) { - print $fh " always @(", join(" or ", ('check', @{$block->{inputs}})); - print $fh ") begin : $block->{name}\n"; - print $fh @{$block->{preass}}; - print $fh @{$block->{body}}; - print $fh " end\n"; - } - else { - foreach my $stmt (@{$block->{preass}}) { - $cycles++; - print $fh " always @(posedge clk) begin\n"; - $stmt =~ s/ = / <= /mg; - print $fh $stmt; - print $fh " end\n"; - } - print $fh " always @(posedge clk) begin\n"; - print $fh @{$block->{body}}; - print $fh " end\n"; - } - } - - print $fh "\n"; - print $fh " parameter [31:0] CYCLES /*verilator public*/ = $cycles;\n"; - print $fh "\n"; - print $fh " integer cyc; initial cyc = 0;\n"; - print $fh " always @(posedge clk) begin\n"; - print $fh "`ifdef TEST_VERBOSE\n"; - print $fh ' $write("[%0t] cyc=%0d check=%d\n", $time, cyc, check);',"\n"; - print $fh "`endif\n"; - print $fh " cyc <= cyc + 1;\n"; - print $fh " if (cyc < CYCLES) begin\n"; - print $fh " check <= 1'b0;\n"; - print $fh " end\n"; - print $fh " else if (cyc >= CYCLES) begin\n"; - print $fh " check <= 1'b1;\n"; - print $fh " if (cyc >= (CYCLES+10)) begin\n"; - print $fh ' $write("*-* All Finished *-*\n");',"\n"; - print $fh ' $finish;',"\n"; - print $fh " end\n"; - print $fh " end\n"; - print $fh " end\n"; - - print $fh "endmodule\n"; - - $fh->close(); -} - -###################################################################### - -sub callers { - for (my $i=0; ; $i++) { - my @c = caller($i); - last if !$c[0]; - print "Caller $i: ",join(' ',@c[0..3]),"\n"; - } -} - -####################################################################### -####################################################################### -####################################################################### -####################################################################### -# Code generation/emitting Functions - -sub do_a_test { - local $Depth = 0; - @Commit = (); - %VarsBlock = (); - - my $block = { - name=>"Block".($#Blocks+2), - body=>[], - preass=>[], - inputs=>[], - outputs=>[], - }; - - for (my $i=0; $i<$Opt_BlockStmts; $i++) { - my $treeref = gen_leaf(width=>0); - push @{$block->{body}}, - "\tif ($treeref->{text} != ".$treeref->val_to_text().") if (check) ".stop_text().";\n"; - } - - foreach my $var (keys %VarsBlock) { - push @{$block->{inputs}}, $var - if $VarsBlock{$var}{used} && !$VarsBlock{$var}{set}; - } - - foreach my $var (reverse (sort (keys %Vars))) { - my $varref = $Vars{$var}; - next if $varref->{printedit}; - $varref->{printedit} = 1; - push @{$block->{outputs}}, $var; - push @{$block->{preass}}, sprintf ("\t$var = %s;\n" - ,$varref->{text}); - } - - foreach my $com (@Commit) { - &{$com} or die "%Error: Can't eval:\n$com\n $@ "; - } - - push @Blocks, $block; -} - -sub gen_leaf { - my $inforef = {width=>0, # Anything - need_terminal=>0, - #trunc=>undef, # Allow multiply op - @_}; - - $inforef->{width} ||= rnd_width(); - $inforef->{signed} = ($Opt_Signed && $inforef->{width}>1 && (rnd(100)<$Signed_Pct))?1:0 - if !defined $inforef->{signed}; - print +((" "x$Depth)."Leaf of width $inforef->{width}\n") if $Debug; - my $op = rnd_op($inforef); - - my $treeref = new Vg::Base; - while ((my $key,my $val) = each %{$op}) { - $treeref->{$key} = $val; - } - while ((my $key,my $val) = each %{$inforef}) { - $treeref->{$key} = $val; - } - - local $Depth = $Depth+1; - print "RndSub $treeref->{rnd_sub_text}\n" if $Debug; - $treeref->{rnd_sub}($treeref); - $treeref->tree_dump() if $Debug; - - print "RndPl\n" if $Debug; - $treeref->{pl_sub}($treeref); - print "RndV\n" if $Debug; - $treeref->{text} = $treeref->{v_sub}($treeref); - print "Done\n" if $Debug; - print " Value ",$treeref->{val}," = ",$treeref->val_to_text(),"\n" if $Debug; - #$treeref->tree_dump() if $Debug; - - $treeref->{val_size} = $treeref->{val}->Size; # Debugging - $treeref->{val_text} = $treeref->{val}->to_Hex; # Debugging - - ($treeref->{val}->Size == $treeref->{width}) - or die "%Error: Size mismatch ",$treeref->{val}->Size,"!=",$treeref->{width},"\n",Dumper($treeref); - - return $treeref; -} - -sub gen_v { - my $opref = shift; - - my $fmt = $opref->{v}; - $fmt =~ s/%1/%s/g; - $fmt =~ s/%2/%s/g; - $fmt =~ s/%3/%s/g; - $fmt =~ s/%v/%s/g; - $fmt =~ s/%i/%s/g; - $fmt =~ s/%x[wds]/%s/g; - - my $argl = $opref->{v}; - my @args; - while ($argl =~ s/(%x.|%.)//) { - my $arg = $1; - push @args, '$treeref->{op1}{text}' if $arg =~ /%1/; - push @args, '$treeref->{op2}{text}' if $arg =~ /%2/; - push @args, '$treeref->{op3}{text}' if $arg =~ /%3/; - push @args, '$treeref->val_to_text' if $arg =~ /%v/; - push @args, '$treeref->{id}' if $arg =~ /%i/; - push @args, '$treeref->{signed}?"s":""' if $arg =~ /%xs/; - push @args, '$treeref->{width}' if $arg =~ /%xw/; - push @args, '$treeref->{width}-$treeref->{op1}{width}' if $arg =~ /%xd/; - } - - my $func = ("sub { " - ." my \$treeref = shift;" - ." sprintf(\"$fmt\",".join(',',@args).");" - ."}"); - my $set = ("\$opref->{v_sub} = $func; 1;"); - $opref->{v_sub_text} = $func; # For seeing it in debugging dumps - #print "Op V $opref->{name} $set\n"; - eval($set) or die "%Error: Can't eval:\n$set\n $@ "; -} - -sub escapes { - my $str = shift; - my $cmt = shift; - $str =~ s/%tr/\$treeref/g; - $str =~ s/%tg/\$treeref->{signed}/g; - $str =~ s/%tv/\$treeref->{val}/g; - $str =~ s/%tw/\$treeref->{width}/g; - # - $str =~ s/%1r/\$treeref->{op1}/g; - $str =~ s/%1g/\$treeref->{op1}{signed}/g; - $str =~ s/%1n/(\$treeref->{op1}{val}->Word_Read(0))/g; - $str =~ s/%1v/\$treeref->{op1}{val}/g; - $str =~ s/%1w/\$treeref->{op1}{width}/g; - # - $str =~ s/%2r/\$treeref->{op2}/g; - $str =~ s/%2g/\$treeref->{op2}{signed}/g; - $str =~ s/%2n/(\$treeref->{op2}{val}->Word_Read(0))/g; - $str =~ s/%2v/\$treeref->{op2}{val}/g; - $str =~ s/%2w/\$treeref->{op2}{width}/g; - # - $str =~ s/%3r/\$treeref->{op3}/g; - $str =~ s/%3g/\$treeref->{op3}{signed}/g; - $str =~ s/%3n/(\$treeref->{op3}{val}->Word_Read(0))/g; - $str =~ s/%3v/\$treeref->{op3}{val}/g; - $str =~ s/%3w/\$treeref->{op3}{width}/g; - # - $str =~ s/%i/\$treeref->{id}/g; - ($str !~ /%/) or die "%Error: $cmt: Unknown %% escape in $str,"; - return $str; -} - -sub gen_pl { - my $opref = shift; - - my $str = escapes($opref->{pl}, $opref->{name}); - my $func = ("sub { " - ." my \$treeref = shift;" - ." $str;" - ."}"); - my $set = ("\$opref->{pl_sub} = $func; 1;"); - $opref->{pl_sub_text} = $func; # For seeing it in debugging dumps - #print "Op PL $opref->{name} $set\n"; - eval($set) or die "%Error: Can't eval:\n$set\n $@ "; -} - -sub gen_rnd { - my $opref = shift; - - my $str = escapes($opref->{rnd}, $opref->{name}); - - my $func = ("sub { " - ." my \$treeref = shift;" - ." $str;" - ."}"); - my $set = ("\$opref->{rnd_sub} = $func; 1;"); - $opref->{rnd_sub_text} = $func; # For seeing it in debugging dumps - #print "Op RND $opref->{name} $set\n"; - eval($set) or die "%Error: Can't eval:\n$set\n $@ "; -} - -sub stop_text { - return '$stop'; -} - -sub decl_text { - my $var = shift; - my $decl_with = shift; - - my $varref = $Vars{$var}; - return sprintf(" reg %s [%3d:%3d] %s %s; //=%d'h%s" - , ($varref->{signed}?"signed":" ") - , ($varref->{val}->Size)-1+$VarAttrs{$var}{lsb}, - , $VarAttrs{$var}{lsb} - , $var - , (rnd(100)<30 ? "/*verilator public*/":(" "x length("/*verilator public*/"))) - , $varref->{val}->Size - , lc $varref->{val}->to_Hex); -} - -####################################################################### -####################################################################### -####################################################################### -####################################################################### -# Math Functions - -sub selftest { - my $o = {}; - VDIV($o, {val=>Bit::Vector->new_Dec(8,0xff)}, {val=>Bit::Vector->new_Dec(8,0x13)}, 0); - ($o->{val}->Word_Read(0) == 0x0d) or die; - VDIV($o, {val=>Bit::Vector->new_Dec(8,0xff)}, {val=>Bit::Vector->new_Dec(8,0x13)}, 1); - ($o->{val}->Word_Read(0) == 0x08) or die; - VDIV($o, {val=>Bit::Vector->new_Dec(8,0xff), signed=>1}, {val=>Bit::Vector->new_Dec(8,0x13), signed=>1}, 0); - ($o->{val}->Word_Read(0) == 0x00) or die; - VDIV($o, {val=>Bit::Vector->new_Dec(8,0xff), signed=>1}, {val=>Bit::Vector->new_Dec(8,0x13), signed=>1}, 1); - ($o->{val}->Word_Read(0) == 0xff) or die; - VDIV($o, {val=>Bit::Vector->new_Dec(8,0xff), signed=>1}, {val=>Bit::Vector->new_Dec(8,0xdb), signed=>1}, 1); - ($o->{val}->Word_Read(0) == 0xff) or die; - VDIV($o, {val=>Bit::Vector->new_Dec(8,0x72), signed=>1}, {val=>Bit::Vector->new_Dec(8,0xdb), signed=>1}, 1); - ($o->{val}->Word_Read(0) == 0x3) or die; -} -sub val_leaf { return {width=>32, signed=>0, val=>Bit::Vector->new_Dec(32,$_[0]), text=>$_[0],}; } - -sub makebool { return (Bit::Vector->new_Dec(1,$_[0])); } -sub newsized { return (Bit::Vector->new($_[0]->Size)); } -sub max { return $_[0]<$_[1] ? $_[1] : $_[0]; } -sub min { return $_[0]>$_[1] ? $_[1] : $_[0]; } - -sub log2 { - for (my $i=31; $i>=0; $i--) { - return $i+1 if $_[0]>(1<<$i); - } - return 0; -} - -sub countones { - my $out = 0; - for (my $bit=0; $bit < $_[0]->Size; $bit++) { - $out ++ if $_[0]->bit_test($bit); - } - return $out; -} - - -sub VLOGNOT { $_[0]{val} = makebool(($_[1]->is_empty)?1:0); } -sub VNEGATE { $_[0]{val} = my $o = newsized($_[1]); $o->Negate($_[1]); } -sub VCOUNTONES { $_[0]{val} = Bit::Vector->new_Dec(32,countones($_[1])); } -sub VONEHOT { $_[0]{val} = makebool((countones($_[1])==1)?1:0); } -sub VONEHOT0 { $_[0]{val} = makebool((countones($_[1])<=1)?1:0); } -sub VLOGAND { $_[0]{val} = makebool((!($_[1]->is_empty) && !($_[2]->is_empty))?1:0); } -sub VLOGOR { $_[0]{val} = makebool((!($_[1]->is_empty) || !($_[2]->is_empty))?1:0); } - -sub VCOND { if (!($_[1]->is_empty)) { $_[0]{val}=$_[2]->Clone; } else { $_[0]{val}=$_[3]->Clone; } } - -sub VREDAND { $_[0]{val} = makebool(($_[1]->is_full)?1:0); } -sub VREDOR { $_[0]{val} = makebool(($_[1]->is_empty)?0:1); } -sub VREDNAND { $_[0]{val} = makebool(($_[1]->is_full)?0:1); } -sub VREDNOR { $_[0]{val} = makebool(($_[1]->is_empty)?1:0); } -sub VREDXOR { - my $out = 0; - for (my $bit=0; $bit < $_[1]->Size; $bit++) { - $out ^= $_[1]->bit_test($bit); - } - $_[0]{val} = makebool($out); -} -sub VREDXNOR { - my $out = 1; - for (my $bit=0; $bit < $_[1]->Size; $bit++) { - $out ^= $_[1]->bit_test($bit); - } - $_[0]{val} = makebool($out); -} -sub eithercompare { ($_[1]->{signed} && $_[2]->{signed}) - ? $_[1]{val}->Compare($_[2]{val}) - : $_[1]{val}->Lexicompare($_[2]{val}); } -sub VEQ { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])==0) ?1:0); } -sub VNE { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])!=0) ?1:0); } -sub VLT { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])< 0) ?1:0); } -sub VLE { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])<=0) ?1:0); } -sub VGT { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])> 0) ?1:0); } -sub VGE { $_[0]{val} = makebool( (eithercompare($_[0],$_[1],$_[2])>=0) ?1:0); } - -sub VSHIFTLxx { - print "$Vars{vq}->ShiftL($_[0],$_[1]);\n"; - print " ",$_[0]->to_Hex," ",$_[1]->to_Hex,";\n"; - my $out = $_[0]->Clone; - $out->Move_Left($_[1]->Word_Read(0)); - print $out->to_Hex,"\n"; - return $out; } -sub VAND { $_[0]{val}=my $o=newsized($_[1]); $o->Intersection($_[1],$_[2]); } -sub VOR { $_[0]{val}=my $o=newsized($_[1]); $o->Union($_[1],$_[2]); } -sub VNAND { $_[0]{val}=my $o=newsized($_[1]); $o->Intersection($_[1],$_[2]); $o->Complement($o); } -sub VNOR { $_[0]{val}=my $o=newsized($_[1]); $o->Union($_[1],$_[2]); $o->Complement($o); } -sub VXOR { $_[0]{val}=my $o=newsized($_[1]); $o->ExclusiveOr($_[1],$_[2]); } -sub VXNOR{ $_[0]{val}=my $o=newsized($_[1]); $o->ExclusiveOr($_[1],$_[2]); $o->Complement($o); } -sub VNOT { $_[0]{val}=my $o=newsized($_[1]); $o->Complement($_[1]); } -sub VSHIFTL{ $_[0]{val}=my $o=$_[1]->Clone; $o->Move_Left ($_[2]->Word_Read(0)); } -sub VSHIFTR{ $_[0]{val}=my $o=$_[1]->Clone; $o->Move_Right($_[2]->Word_Read(0)); } -sub VSHIFTRS{$_[0]{val}=my $o=$_[1]->Clone; $o->Move_Right($_[2]->Word_Read(0)); - if ($_[1]->msb() && $_[2]->Word_Read(0)>0) {$o->Interval_Fill(max(0,$o->Size-1-$_[2]->Word_Read(0)), $o->Size-1); } - #print (" SHI ",$_[0]{val}->to_Hex,' = ',$_[1]->to_Hex,' >>> ',$_[2]->Word_Read(0),"\n"); -} -sub VCLONE { $_[0]{val}=$_[1]->Clone; } -sub VRESIZE { - $_[0]{val}=$_[1]->Clone; - $_[0]{val}->Resize($_[0]{width}); -} -sub VADD { $_[0]{val}=my $o=newsized($_[1]); $o->add($_[1],$_[2],0); } -sub VSUB { $_[0]{val}=my $o=newsized($_[1]); $o->subtract($_[1],$_[2],0); } -sub VMUL { - # Multiply is signed, so need an additional sign bit - my $a=$_[1]->Clone; $a->Resize($a->Size + 1); - my $b=$_[2]->Clone; $b->Resize($b->Size + 1); - my $mo=Bit::Vector->new($_[1]->Size + $_[2]->Size + 1); - $mo->Multiply($a,$b); - my $o=newsized($_[1]); $o->Interval_Copy($mo,0,0,$_[1]->Size); - $_[0]{val}=$o; -} -sub VDIV { - my $is_mod = $_[3]; - if ($_[2]{val}->is_empty) { # Avoid divide by zero - $_[0]{val}=newsized($_[1]{val}); - return; - } - my $a=$_[1]{val}->Clone; if (!$_[1]->{signed}) { $a->Resize($a->Size + 1); } - my $b=$_[2]{val}->Clone; if (!$_[2]->{signed}) { $b->Resize($b->Size + 1); } - #print ("//DIVpp ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[1]->Size,'.',$_[2]->Size," \n"); - #print ("//DIVpp ",$a->to_Hex,' ',$b->to_Hex,' ',$a->Size,'.',$b->Size," \n"); - my $quo=newsized($a); my $rem=newsized($a); - $quo->Divide($a,$b,$rem); # No division by zero - handled by if above - my $o=newsized($_[1]{val}); - $o->Interval_Copy($is_mod ? $rem : $quo,0,0,$_[1]{val}->Size); - #print "//DIV",($_[1]->{signed}?"S":" "),' w',$a->Size,' ',$_[1]{val}->to_Hex,' ',$_[2]{val}->to_Hex,' =',$quo->to_Hex,'.',$rem->to_Hex," \n"; - $_[0]{val}=$o; -} -sub VPOW { # Power is a signed operation - my $a=$_[1]{val}->Clone; if (!$_[1]->{signed}) { $a->Resize($_[1]{val}->Size + 1); } - my $b=$_[2]{val}->Clone; if (!$_[2]->{signed}) { $b->Resize($_[2]{val}->Size + 1); } - print "VVpow = ",$_[1]{val}->to_Hex," ** ",$_[2]{val}->to_Hex,"\n"; - my $mo=Bit::Vector->new($_[1]{val}->Size + 1); - $mo->Power($a,$b); - my $o=Bit::Vector->new($_[0]{width}); $o->Interval_Copy($mo,0,0,$_[1]{val}->Size); - $_[0]{val}=$o; - print "VV = $o\n"; -} -sub VRANGE { - #print "RANGE ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[3]->to_Hex," \n"; - return VRANGE_CONST($_[0], $_[1], $_[2]->Word_Read(0), - $_[3]->Word_Read(0), $_[4]); -} -sub VBITSELP { - return VRANGE_CONST($_[0], $_[1], $_[2]->Word_Read(0)+$_[3]->Word_Read(0)-1, - $_[2]->Word_Read(0), $_[4]); -} -sub VBITSELM { - return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0), - $_[2]->Word_Read(0)-$_[3]->Word_Read(0)+1, $_[4]); -} -sub VRANGE_CONST { - # to, from, msb, lsb, variable_lsb_to_subtract - #print "RANGE ",$_[1]->to_Hex,' ',$_[2],' ',$_[3],' ',$_[4]," \n"; - my $size = $_[2] - $_[3] + 1; - my $o=Bit::Vector->new($size); - if ($_[3] < $_[1]->Size) { - $o->Interval_Copy($_[1],0,$_[3]-$_[4],$size); - } - $_[0]{val}=$o; } -sub VCONCAT { - my $o=Bit::Vector->new($_[1]->Size + $_[2]->Size); - $o->Interval_Copy($_[1],$_[2]->Size,0,$_[1]->Size); - $o->Interval_Copy($_[2],0,0,$_[2]->Size); - $_[0]{val}=$o; -} -sub VREPLIC { - my $o=Bit::Vector->new($_[1]->Word_Read(0) * $_[2]->Size); - my $pos = 0; - for (my $time=0; $time<($_[1]->Word_Read(0)); $time++) { - $o->Interval_Copy($_[2],$pos,0,$_[2]->Size); - $pos += $_[2]->Size; - } - $_[0]{val}=$o; -} - -####################################################################### -####################################################################### -####################################################################### - -package Vg::Base; -use Data::Dumper; -use strict; - -#------------------------------------------------------------ -# CREATORS - -sub new { - my $class = shift; - my $self = { - width=>0, # Width of expression, 0=Pick a width - #signed=>0/1, # Undef = pick a sign - @_}; - bless $self, $class; - return $self; -} - -# ACCESSORS - -#------------------------------------------------------------ -# OUTPUTTING - -sub val_to_text { - my $treeref = shift; - my $val = lc $treeref->{val}->to_Hex(); - $val = "0" if $treeref->{val}->is_empty; - return ($treeref->{width} - .($treeref->{signed}?"'sh":"'h") - .$val); -} - -sub tree_dump { - my $treeref = shift; - print Dumper($treeref); -} - -####################################################################### -__END__ - -=pod - -=head1 NAME - -vgen.pl - Generate random verilog code - -=head1 SYNOPSIS - - vgen.pl -o vgen.v - -=head1 DESCRIPTION - -vgen.pl generates automatic random verilog programs. - -=head1 ARGUMENTS - -=over 4 - -=item --help - -Displays this message and program version and exits. - -=item --blockstmts - -Number of statements per block. Defaults to 2. - -=item --depth - -Maximum depth of generated expressions. - -=item --initial - -Put all statements into an initial block. This will probably be optimized -down to a NOP. - -=item --numops - -Number of operations to create. - -=item -o I - -Specify output filename. - -=item --raise - -Pick the specified number of random opcodes, and raise their frequency. - -=item --seed - -Seed for the random number generator. Defaults to 5, 0=randomize. - -=item --signed - -Include some signed arithmetic in the generated code. Experimental. - -=back - -=head1 DISTRIBUTION - -Copyright 2001-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 - -=head1 AUTHORS - -Wilson Snyder - -=head1 SEE ALSO - -=cut - -###################################################################### -### Local Variables: -### compile-command: "./vgen.pl --depth=10 --blockstmts=10 -o obj_dir/vgen.v" -### compile-command: "v4make test_regress/t/t_vgen.pl " -### End: From b350b6a0ffdebe47c1681ec6a868daf47b7a1f9a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 2 Dec 2020 20:09:23 -0500 Subject: [PATCH 91/91] Version bump --- Changes | 4 +++- configure.ac | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index e2d2f61f4..3e06d6263 100644 --- a/Changes +++ b/Changes @@ -3,7 +3,7 @@ Revision history for Verilator The contributors that suggested a given feature are shown in []. Thanks! -* Verilator 4.105 devel +* Verilator 4.106 2020-12-02 ** Change -sv option to select 1800-2017 instead of 1800-2005. @@ -19,6 +19,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support 'with item.index'. +**** Fix the default GNU Make executable name on FreeBSD (#2553). [Yuri Victorovich] + **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] **** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] diff --git a/configure.ac b/configure.ac index dada8de1e..563c93a29 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### devel]) -AC_INIT([Verilator],[4.105 devel], +AC_INIT([Verilator],[4.106 2020-12-02], [https://verilator.org], [verilator],[https://verilator.org]) # When releasing, also update header of Changes file