diff --git a/bin/verilator b/bin/verilator index d49fc5e08..2f554a77c 100755 --- a/bin/verilator +++ b/bin/verilator @@ -271,6 +271,7 @@ detailed descriptions in L for more information. --bbox-sys Blackbox unknown $system calls --bbox-unsup Blackbox unsupported language features --bin Override Verilator binary + --build Call make system to build executable after Verilation -CFLAGS C++ Compiler flags for makefile --cc Create C++ output --cdc Clock domain crossing analysis @@ -309,6 +310,7 @@ detailed descriptions in L for more information. --getenv Get environment variable with defaults --help Display this help -I Directory to search for includes + -j Parallelism for --build --gate-stmts Tune gate optimizer depth --if-depth Tune IFDEPTH warning +incdir+ Directory to search for includes @@ -319,6 +321,7 @@ detailed descriptions in L for more information. --language Default language standard to parse +libext++[ext]... Extensions for finding modules --lint-only Lint, but do not make output + -MAKEFLAGS Options to make/cmake during --build --max-num-width Maximum number width (default: 64K) --MMD Create .d dependency files --MP Create phony dependency targets @@ -334,6 +337,7 @@ detailed descriptions in L for more information. -O Selectable optimizations -o 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 Split .cpp files into pieces --output-split-cfuncs Split .cpp functions --output-split-ctrace 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 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 @@ -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 + +Specify the parallelism for make system. This option is used when --build +options is specified. must be a positive integer or can be omitted. +Build system exploits maximum parallelism when is omitted. + =item -LDFLAGS I 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 + +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 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 =item +verilog2001ext+I @@ -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 diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 36a54708b..e39e52449 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -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; diff --git a/src/V3Options.h b/src/V3Options.h index b51d4e48f..f9f17ef88 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -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(); diff --git a/src/V3Os.cpp b/src/V3Os.cpp index 03f7dc142..86e5b266d 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -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; + } +} diff --git a/src/V3Os.h b/src/V3Os.h index cfebdfc7e..8e511257d 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -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 diff --git a/src/Verilator.cpp b/src/Verilator.cpp index d27137487..a5b2afa2b 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -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(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(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"); } diff --git a/test_regress/t/t_flag_build_cmake.pl b/test_regress/t/t_flag_build_cmake.pl new file mode 100755 index 000000000..2f4c919d8 --- /dev/null +++ b/test_regress/t/t_flag_build_cmake.pl @@ -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; diff --git a/test_regress/t/t_flag_build_make.pl b/test_regress/t/t_flag_build_make.pl new file mode 100755 index 000000000..400e3c51e --- /dev/null +++ b/test_regress/t/t_flag_build_make.pl @@ -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; diff --git a/test_regress/t/t_flag_verilate.pl b/test_regress/t/t_flag_verilate.pl new file mode 100755 index 000000000..c28d235b6 --- /dev/null +++ b/test_regress/t/t_flag_verilate.pl @@ -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;