Add --build option to call make/cmake as subprocess (#2249)

* Add --build, -j, -MAKEFLAGS, and --no-verilate options
* Verilator: Can build on both gmake and cmake
This commit is contained in:
Yutetsu TAKATSUKASA 2020-04-16 06:44:21 +09:00 committed by GitHub
parent 1883ab29cb
commit 18412f9322
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 313 additions and 28 deletions

View File

@ -271,6 +271,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--bbox-sys Blackbox unknown $system calls
--bbox-unsup Blackbox unsupported language features
--bin <filename> Override Verilator binary
--build Call make system to build executable after Verilation
-CFLAGS <flags> C++ Compiler flags for makefile
--cc Create C++ output
--cdc Clock domain crossing analysis
@ -309,6 +310,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--getenv <var> Get environment variable with defaults
--help Display this help
-I<dir> Directory to search for includes
-j <jobs> Parallelism for --build
--gate-stmts <value> Tune gate optimizer depth
--if-depth <value> Tune IFDEPTH warning
+incdir+<dir> Directory to search for includes
@ -319,6 +321,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--language <lang> Default language standard to parse
+libext+<ext>+[ext]... Extensions for finding modules
--lint-only Lint, but do not make output
-MAKEFLAGS <flags> Options to make/cmake during --build
--max-num-width <value> Maximum number width (default: 64K)
--MMD Create .d dependency files
--MP Create phony dependency targets
@ -334,6 +337,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
-O<optimization-letter> Selectable optimizations
-o <executable> Name of final executable
--no-order-clock-delay Disable ordering clock enable assignments
--no-verilate Skip verilation and just compile previously verilated code.
--output-split <statements> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .cpp functions
--output-split-ctrace <statements> Split tracing functions
@ -533,6 +537,11 @@ dependency (.d) file is created, this filename will become a source
dependency, such that a change in this binary will have make rebuild the
output files.
=item --build
After generating the SystemC/C++ code, Verilator will use the make system
to build a library or executable. See also C<--make> and C<--exe>.
=item -CFLAGS I<flags>
Add specified C compiler flag to the generated makefiles. For multiple
@ -584,6 +593,9 @@ Generates a script for the specified make system.
Supported make systems are gmake and cmake. Both can be specified.
If no make system is specified, gmake is assumed.
The executable of gmake can be configured via environment variable "MAKE".
See also --build.
=item --compiler I<compiler-name>
@ -925,6 +937,12 @@ values, or a value < 1 will inline everything, will lead to longer compile
times, but potentially faster simulation runtimes. This setting is ignored
for very small modules; they will always be inlined, if allowed.
=item -j <value>
Specify the parallelism for make system. This option is used when --build
options is specified. <value> must be a positive integer or can be omitted.
Build system exploits maximum parallelism when <value> is omitted.
=item -LDFLAGS I<flags>
Add specified C linker flags to the generated makefiles. For multiple
@ -970,6 +988,13 @@ stylistic and not enabled by default.
If the design is not to be completely Verilated see also the --bbox-sys and
--bbox-unsup options.
=item -MAKEFLAGS <string>
When using --build, add the specified flag to the make/cmake command line.
For multiple flags either pass them as a single argument with space separators
quoted in the shell (e.g. C<-MAKEFLAGS "-a -b">), or use multiple -MAKEFLAGS
arguments (e.g. C<-MAKEFLAGS -l -MAKEFLAGS -k>).
=item --max-num-width I<value>
Set the maximum number literal width (e.g. in 1024'd22 this it the 1024).
@ -1510,6 +1535,10 @@ Read the filename as a Verilog library. Any modules in the file may be
used to resolve cell instantiations in the top level module, else ignored.
Note -v is fairly standard across Verilog tools.
=item --no-verilate
When using --build, disable generation of C++/SC code, and only run make/cmake.
=item +verilog1995ext+I<ext>
=item +verilog2001ext+I<ext>
@ -2126,6 +2155,12 @@ A generic Linux/OS variable specifying what directories have shared object
(.so) files. This path should include SystemC and any other shared objects
needed at simulation runtime.
=item MAKE
Executable of the make command used in --build option.
Some operating systems may require "gmake" to this variable to launch GNU make.
If this variable is not specified, "make" is used.
=item OBJCACHE
Optionally specifies a caching or distribution program to place in front of

View File

@ -198,6 +198,7 @@ void V3Options::checkParameters() {
void V3Options::addCppFile(const string& filename) { m_cppFiles.insert(filename); }
void V3Options::addCFlags(const string& filename) { m_cFlags.push_back(filename); }
void V3Options::addLdLibs(const string& filename) { m_ldLibs.push_back(filename); }
void V3Options::addMakeFlags(const string& filename) { m_makeFlags.push_back(filename); }
void V3Options::addFuture(const string& flag) { m_futures.insert(flag); }
bool V3Options::isFuture(const string& flag) const {
return m_futures.find(flag) != m_futures.end();
@ -393,7 +394,9 @@ V3LangCode V3Options::fileLanguage(const string& filename) {
// Environment
string V3Options::getenvBuiltins(const string& var) {
if (var == "PERL") {
if (var == "MAKE") {
return getenvMAKE();
} else if (var == "PERL") {
return getenvPERL();
} else if (var == "SYSTEMC") {
return getenvSYSTEMC();
@ -410,6 +413,8 @@ string V3Options::getenvBuiltins(const string& var) {
}
}
string V3Options::getenvMAKE() { return V3Os::getenvStr("MAKE", "make"); }
string V3Options::getenvPERL() { //
return V3Os::getenvStr("PERL", "perl");
}
@ -723,6 +728,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-autoflush", flag/*ref*/)) { m_autoflush = flag; }
else if ( onoff (sw, "-bbox-sys", flag/*ref*/)) { m_bboxSys = flag; }
else if ( onoff (sw, "-bbox-unsup", flag/*ref*/)) { m_bboxUnsup = flag; }
else if (!strcmp(sw, "-build")) { m_build = true; }
else if (!strcmp(sw, "-cc")) { m_outFormatOk = true; m_systemC = false; }
else if ( onoff (sw, "-cdc", flag/*ref*/)) { m_cdc = flag; }
else if ( onoff (sw, "-coverage", flag/*ref*/)) { coverage(flag); }
@ -783,6 +789,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-trace-structs", flag/*ref*/)) { m_traceStructs = flag; }
else if ( onoff (sw, "-trace-underscore", flag/*ref*/)) { m_traceUnderscore = flag; }
else if ( onoff (sw, "-underline-zero", flag/*ref*/)) { m_underlineZero = flag; } // Undocumented, old Verilator-2
else if ( onoff (sw, "-verilate", flag/*ref*/)) { m_verilate = flag; }
else if ( onoff (sw, "-vpi", flag/*ref*/)) { m_vpi = flag; }
else if ( onoff (sw, "-Wpedantic", flag/*ref*/)) { m_pedantic = flag; }
else if ( onoff (sw, "-x-initial-edge", flag/*ref*/)) { m_xInitialEdge = flag; }
@ -889,6 +896,17 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
} else if (!strcmp(sw, "-inline-mult") && (i + 1) < argc) {
shift;
m_inlineMult = atoi(argv[i]);
} else if (!strcmp(sw, "-j")) {
if ((i + 1) >= argc || !isdigit(argv[i + 1][0])) { // No value is given
m_buildJobs = 0; // Unlimited parallelism
} else {
shift;
m_buildJobs = atoi(argv[i]);
if (m_buildJobs <= 0) {
fl->v3error("-j accepts positive integer, but " << argv[i]
<< " is passed");
}
}
} else if (!strcmp(sw, "-LDFLAGS") && (i + 1) < argc) {
shift;
addLdLibs(argv[i]);
@ -906,6 +924,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
} else {
fl->v3fatal("Unknown --make system specified: '" << argv[i] << "'");
}
} else if (!strcmp(sw, "-MAKEFLAGS") && (i + 1) < argc) {
shift;
addMakeFlags(argv[i]);
} else if (!strcmp(sw, "-max-num-width")) {
shift;
m_maxNumWidth = atoi(argv[i]);
@ -1355,6 +1376,7 @@ void V3Options::showVersion(bool verbose) {
cout << endl;
cout << "Environment:\n";
cout << " MAKE = " << V3Os::getenvStr("MAKE", "") << endl;
cout << " PERL = " << V3Os::getenvStr("PERL", "") << endl;
cout << " SYSTEMC = " << V3Os::getenvStr("SYSTEMC", "") << endl;
cout << " SYSTEMC_ARCH = " << V3Os::getenvStr("SYSTEMC_ARCH", "") << endl;
@ -1374,6 +1396,7 @@ V3Options::V3Options() {
m_autoflush = false;
m_bboxSys = false;
m_bboxUnsup = false;
m_build = false;
m_cdc = false;
m_cmake = false;
m_context = true;
@ -1434,10 +1457,12 @@ V3Options::V3Options() {
m_traceStructs = false;
m_traceUnderscore = false;
m_underlineZero = false;
m_verilate = true;
m_vpi = false;
m_xInitialEdge = false;
m_xmlOnly = false;
m_buildJobs = 1;
m_convergeLimit = 100;
m_dumpTree = 0;
m_gateStmts = 100;

View File

@ -114,6 +114,7 @@ private:
V3StringSet m_cppFiles; // argument: C++ files to link against
V3StringList m_cFlags; // argument: user CFLAGS
V3StringList m_ldLibs; // argument: user LDFLAGS
V3StringList m_makeFlags; // argument: user MAKEFLAGS
V3StringSet m_futures; // argument: -Wfuture- list
V3StringSet m_libraryFiles; // argument: Verilog -v files
V3StringSet m_clockers; // argument: Verilog -clk signals
@ -131,6 +132,7 @@ private:
bool m_autoflush; // main switch: --autoflush
bool m_bboxSys; // main switch: --bbox-sys
bool m_bboxUnsup; // main switch: --bbox-unsup
bool m_build; // main switch: --build
bool m_cdc; // main switch: --cdc
bool m_cmake; // main switch: --make cmake
bool m_context; // main switch: --Wcontext
@ -184,10 +186,12 @@ private:
bool m_traceStructs; // main switch: --trace-structs
bool m_traceUnderscore;// main switch: --trace-underscore
bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2
bool m_verilate; // main swith: --verilate
bool m_vpi; // main switch: --vpi
bool m_xInitialEdge; // main switch: --x-initial-edge
bool m_xmlOnly; // main switch: --xml-netlist
int m_buildJobs; // main switch: -j
int m_convergeLimit;// main switch: --converge-limit
int m_dumpTree; // main switch: --dump-tree
int m_gateStmts; // main switch: --gate-stmts
@ -292,6 +296,7 @@ public:
void addCppFile(const string& filename);
void addCFlags(const string& filename);
void addLdLibs(const string& filename);
void addMakeFlags(const string& filename);
void addLibraryFile(const string& filename);
void addClocker(const string& signame);
void addNoClocker(const string& signame);
@ -316,6 +321,7 @@ public:
bool autoflush() const { return m_autoflush; }
bool bboxSys() const { return m_bboxSys; }
bool bboxUnsup() const { return m_bboxUnsup; }
bool build() const { return m_build; }
bool cdc() const { return m_cdc; }
bool cmake() const { return m_cmake; }
bool context() const { return m_context; }
@ -364,10 +370,12 @@ public:
bool quietExit() const { return m_quietExit; }
bool relativeCFuncs() const { return m_relativeCFuncs; }
bool reportUnoptflat() const { return m_reportUnoptflat; }
bool verilate() const { return m_verilate; }
bool vpi() const { return m_vpi; }
bool xInitialEdge() const { return m_xInitialEdge; }
bool xmlOnly() const { return m_xmlOnly; }
int buildJobs() const { return m_buildJobs; }
int convergeLimit() const { return m_convergeLimit; }
int dumpTree() const { return m_dumpTree; }
int gateStmts() const { return m_gateStmts; }
@ -422,6 +430,7 @@ public:
const V3StringSet& cppFiles() const { return m_cppFiles; }
const V3StringList& cFlags() const { return m_cFlags; }
const V3StringList& ldLibs() const { return m_ldLibs; }
const V3StringList& makeFlags() const { return m_makeFlags; }
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
const V3StringList& vFiles() const { return m_vFiles; }
const V3StringList& forceIncs() const { return m_forceIncs; }
@ -478,6 +487,7 @@ public:
// see the README. If adding new variables, also see src/Makefile_obj.in
// Also add to V3Options::showVersion()
static string getenvBuiltins(const string& var);
static string getenvMAKE();
static string getenvPERL();
static string getenvSYSTEMC();
static string getenvSYSTEMC_ARCH();

View File

@ -242,6 +242,8 @@ void V3Os::unlinkRegexp(const string& dir, const string& regexp) {
}
}
std::string V3Os::getcwd() { return filenameRealPath("."); }
//######################################################################
// METHODS (random)
@ -333,3 +335,21 @@ void V3Os::u_sleep(int64_t usec) {
::usleep(usec);
#endif
}
//######################################################################
// METHODS (sub command)
int V3Os::system(const string& command) {
UINFO(1, "Running system: " << command << endl);
const int ret = ::system(command.c_str());
if (ret == -1) {
v3fatal("Failed to execute command:" << command << " " << strerror(errno));
return -1;
} else {
UASSERT(WIFEXITED(ret), "system(" << command << ") returned unexpected value of " << ret);
const int exit_code = WEXITSTATUS(ret);
UINFO(1, command << " returned exit code of " << exit_code << std::endl);
UASSERT(exit_code >= 0, "exit code must not be negative");
return exit_code;
}
}

View File

@ -53,6 +53,7 @@ public:
// METHODS (directory utilities)
static void createDir(const string& dirname);
static void unlinkRegexp(const string& dir, const string& regexp);
static std::string getcwd(); // Return the current working directory
// METHODS (random)
static vluint64_t rand64(vluint64_t* statep);
@ -63,6 +64,10 @@ public:
/// Return wall time since epoch in microseconds, or 0 if not implemented
static uint64_t timeUsecs();
static uint64_t memUsageBytes(); ///< Return memory usage in bytes, or 0 if not implemented
// METHODS (sub command)
/// Run system command, returns the exit code of the child process.
static int system(const string& command);
};
#endif // Guard

View File

@ -492,32 +492,8 @@ static void process() {
// Note early return above when opt.cdc()
}
//######################################################################
int main(int argc, char** argv, char** env) {
// General initialization
std::ios::sync_with_stdio();
time_t randseed;
time(&randseed);
srand(static_cast<int>(randseed));
// Post-constructor initialization of netlists
v3Global.boot();
// Preprocessor
// Before command parsing so we can handle -Ds on command line.
V3PreShell::boot(env);
// Command option parsing
v3Global.opt.bin(argv[0]);
string argString = V3Options::argString(argc - 1, argv + 1);
v3Global.opt.parseOpts(new FileLine(FileLine::commandLineFilename()), argc - 1, argv + 1);
// Validate settings (aka Boost.Program_options)
v3Global.opt.notify();
V3Error::abortIfErrors();
static void verilate(const string& argString) {
UINFO(1, "Option --verilate: Start Verilation\n");
// Can we skip doing everything if times are ok?
V3File::addSrcDepend(v3Global.opt.bin());
@ -526,7 +502,7 @@ int main(int argc, char** argv, char** env) {
+ "__verFiles.dat",
argString)) {
UINFO(1, "--skip-identical: No change to any source files, exiting\n");
exit(0);
return;
}
// Undocumented debugging - cannot be a switch as then command line
// would mismatch forcing non-identicalness when we set it
@ -584,6 +560,86 @@ int main(int argc, char** argv, char** env) {
v3Global.clear();
#endif
FileLine::deleteAllRemaining();
}
static void execBuildJob() {
UASSERT(v3Global.opt.build(), "--build is not specified.");
UINFO(1, "Start Build\n");
std::stringstream cmd;
const V3StringList& makeFlags = v3Global.opt.makeFlags();
const int jobs = v3Global.opt.buildJobs();
UASSERT(jobs >= 0, "-j option parser in V3Options.cpp filters out negative value");
if (v3Global.opt.gmake()) { // If both gmake and cmake are chosen, use gmake to build.
cmd << v3Global.opt.getenvMAKE();
cmd << " -C " << v3Global.opt.makeDir();
cmd << " -f " << v3Global.opt.prefix() << ".mk";
if (jobs == 0) {
cmd << " -j";
} else if (jobs > 1) {
cmd << " -j " << jobs;
}
for (V3StringList::const_iterator it = makeFlags.begin(); it != makeFlags.end(); ++it) {
cmd << ' ' << *it;
}
} else {
UASSERT(v3Global.opt.cmake(), "cmake or gmake must be chosen in V3Options.cpp");
cmd << "cd " << v3Global.opt.makeDir() << " && ";
cmd << "cmake";
for (V3StringList::const_iterator it = makeFlags.begin(); it != makeFlags.end(); ++it) {
cmd << ' ' << *it;
}
cmd << ' ' << V3Os::getcwd() << " && ";
cmd << "cmake --build . ";
if (jobs == 0) {
cmd << " -j";
} else if (jobs > 1) {
cmd << " -j " << jobs;
}
}
const std::string cmdStr = cmd.str();
const int exit_code = V3Os::system(cmdStr);
if (exit_code != 0) {
v3error(cmdStr << " exitted with " << exit_code << std::endl);
exit(exit_code);
}
}
//######################################################################
int main(int argc, char** argv, char** env) {
// General initialization
std::ios::sync_with_stdio();
time_t randseed;
time(&randseed);
srand(static_cast<int>(randseed));
// Post-constructor initialization of netlists
v3Global.boot();
// Preprocessor
// Before command parsing so we can handle -Ds on command line.
V3PreShell::boot(env);
// Command option parsing
v3Global.opt.bin(argv[0]);
string argString = V3Options::argString(argc - 1, argv + 1);
v3Global.opt.parseOpts(new FileLine(FileLine::commandLineFilename()), argc - 1, argv + 1);
// Validate settings (aka Boost.Program_options)
v3Global.opt.notify();
V3Error::abortIfErrors();
if (v3Global.opt.verilate()) {
verilate(argString);
} else {
UINFO(1, "Option --no-verilate: Skip Verilation\n");
}
if (v3Global.opt.build()) execBuildJob();
UINFO(1, "Done, Exiting...\n");
}

View File

@ -0,0 +1,42 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2008 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);
top_filename("t/t_flag_make_cmake.v");
compile( # Don't call cmake nor gmake from driver.pl
verilator_make_cmake => 0,
verilator_make_gmake => 0,
verilator_flags2 => ['--exe --cc --build -j 2 --make cmake',
'../' . $Self->{main_filename},
' -MAKEFLAGS "-DTEST_NAME=' . $Self->{name} . '"',
' -MAKEFLAGS "-DTEST_CSOURCES=' . $Self->{main_filename} . '"',
' -MAKEFLAGS "-DTEST_OPT_FAST=-Os"',
' -MAKEFLAGS "-DTEST_VERILATOR_ROOT=' . $ENV{VERILATOR_ROOT} . '"',
' -MAKEFLAGS "-DTEST_VERILATOR_ARGS=\"--prefix ' . $Self->{VM_PREFIX} . ' --cc \""',
' -MAKEFLAGS "-DTEST_VERILATOR_SOURCES=./t/t_flag_make_cmake.v"',
' -MAKEFLAGS "-DTEST_SYSTEMC=0"',
' -MAKEFLAGS "-DTEST_VERBOSE=0"',
' -MAKEFLAGS "-DTEST_VERILATION=1"',
' -MAKEFLAGS -DCMAKE_BUILD_TYPE=Debug',
' -MAKEFLAGS -L'],
);
execute(
check_finished => 1,
);
# If '-MAKEFLAGS -DCMAKE_BUILD_TYPE=Debug' and '-MAKEFLAGS -L' are not properly processed,
# the log will not contain 'CMAKE_BUILD_TYPE:STRING=Debug'.
file_grep($Self->{obj_dir} . '/vlt_compile.log', /^CMAKE_BUILD_TYPE:STRING=(\w+)$/, 'Debug');
ok(1);
1;

View File

@ -0,0 +1,32 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2008 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);
top_filename("t/t_flag_make_cmake.v");
compile( # Don't call cmake nor gmake from driver.pl
verilator_make_cmake => 0,
verilator_make_gmake => 0,
verilator_flags2 => ['--exe --cc --build -j 2 --make gmake',
'../' . $Self->{main_filename},
'-MAKEFLAGS --trace'],
);
execute(
check_finished => 1,
);
# If '-MAKEFLAGS --trace' is not properly processed,
# the log will not contain 'CMAKE_BUILD_TYPE:STRING=Debug'.
file_grep($Self->{obj_dir} . '/vlt_compile.log', /^Vt_flag_build_make.mk:\d+: update target \'(\w+)\' due to:/, 'Vt_flag_build_make');
ok(1);
1;

View File

@ -0,0 +1,60 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2008 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);
top_filename("t/t_flag_make_cmake.v");
compile( # Don't call cmake nor gmake from driver.pl. Nothing should be done here.
verilator_make_cmake => 0,
verilator_make_gmake => 0,
verilator_flags2 => ['--exe --cc --no-verilate',
'../' . $Self->{main_filename}]
);
# --no-verilate should skip verilation
if ( -e $Self->{obj_dir} . '/Vt_flag_verilate.mk' ) {
$Self->error('Vt_flag_verilate.mk is unexpectedly created');
}
# --verilate this time
compile( # Don't call cmake nor gmake from driver.pl. Just verilate here.
verilator_make_cmake => 0,
verilator_make_gmake => 0,
verilator_flags2 => ['--exe --cc --make gmake --verilate',
'../' . $Self->{main_filename}]
);
# must be verilated this time
if ( ! -e $Self->{obj_dir} . '/Vt_flag_verilate.mk' ) {
$Self->error('Vt_flag_verilate.mk does not exist');
}
# Just build, no verilation. .tree must not be saved even with --dump-tree option.
compile( # Don't call cmake nor gmake from driver.pl. Just build here
verilator_make_cmake => 0,
verilator_make_gmake => 0,
verilator_flags2 => ['--exe --cc --build --make gmake --no-verilate',
'../' . $Self->{main_filename},
'--debugi 1 --dump-tree'],
);
# The previous run must not verilated, only build is expected.
if ( -e $Self->{obj_dir} . '/Vt_flag_verilate_990_final.tree' ) {
$Self->error('Unexpectedly verilated.');
}
execute(
check_finished => 1,
);
ok(1);
1;