diff --git a/Changes b/Changes index f9a79bec6..822275bef 100644 --- a/Changes +++ b/Changes @@ -35,6 +35,7 @@ Verilator 5.001 devel * Support tristate select/extend (#3604). [Ryszard Rozak, Antmicro Ltd> * Support linting for top module interfaces (#3635). [Kanad Kanhere] * Add --dump-tree-dot to enable dumping Ast Tree .dot files (#3636). [Marcel Chang] +* Add --get-supported to determine what features are in Verilator. * Add error on real edge event control. * Fix LSB error on --hierarchical submodules (#3539). [danbone] * Fix $display of fixed-width numbers (#3565). [Iztok Jeras] diff --git a/bin/verilator b/bin/verilator index 0e5a4bc7b..cd3a25c35 100755 --- a/bin/verilator +++ b/bin/verilator @@ -335,6 +335,7 @@ detailed descriptions of these arguments. --gdbbt Run Verilator under GDB for backtrace --generate-key Create random key for --protect-key --getenv Get environment variable with defaults + --get-supported Get if feature is supported --help Display this help --hierarchical Enable hierarchical Verilation -I Directory to search for includes diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 727371a69..bae014be9 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -648,6 +648,15 @@ Summary: a newline and exit immediately. This can be useful in makefiles. See also :vlopt:`-V`, and the various :file:`*.mk` files. +.. option:: --get-supported + + If the given feature is supported, print "1" and exit + immediately. Otherwise, print a newline and exit immediately. This can + be useful in makefiles. See also :vlopt:`-V`, and the various + :file:`*.mk` files. + + Feature may be one of the following: COROUTINES, SYSTEMC. + .. option:: --help Displays this message and program version and exits. diff --git a/examples/cmake_hello_sc/Makefile b/examples/cmake_hello_sc/Makefile index 540a32fec..9ec875aba 100644 --- a/examples/cmake_hello_sc/Makefile +++ b/examples/cmake_hello_sc/Makefile @@ -39,30 +39,12 @@ ifneq ($(CMAKE_GT_3_8),true) TARGET := oldcmake else -# Test existence of SYSTEMC_INCLUDE and SYSTEMC_LIBDIR environment variabless -ifneq (,$(SYSTEMC_INCLUDE)) -ifneq (,${SYSTEMC_LIBDIR}) -SYSTEMC_SET := true -endif -endif - -# Test existence of SYSTEMC_ROOT environment variable -ifneq (SYSTEMC_SET, true) -ifneq (,${SYSTEMC_ROOT}) -SYSTEMC_SET := true -endif -endif - -# Test existence of SYSTEMC environment variable -ifneq (SYSTEMC_SET, true) -ifneq (,${SYSTEMC}) -SYSTEMC_SET := true -endif -endif +# Check if SC exists via a verilator call (empty if not) +SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) # Test whether SystemC is installed with CMake support # This will print a CMake error about processing arguments that can (currently) be ignored. -ifneq (SYSTEMC_SET, true) +ifneq (,$(SYSTEMC_EXISTS)) FINDSC := $(shell mkdir -p build && cd build && cmake --find-package -DNAME=SystemCLanguage -DCMAKE_USE_PTHREADS_INIT=ON -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST -DThreads_FOUND=ON) ifneq (,$(findstring SystemCLanguage found,$(FINDSC))) SYSTEMC_SET := true diff --git a/examples/cmake_tracing_sc/Makefile b/examples/cmake_tracing_sc/Makefile index 65868d5bf..fb10802cc 100644 --- a/examples/cmake_tracing_sc/Makefile +++ b/examples/cmake_tracing_sc/Makefile @@ -39,30 +39,12 @@ ifneq ($(CMAKE_GT_3_8),true) TARGET := oldcmake else -# Test existence of SYSTEMC_INCLUDE and SYSTEMC_LIBDIR environment variabless -ifneq (,$(SYSTEMC_INCLUDE)) -ifneq (,${SYSTEMC_LIBDIR}) -SYSTEMC_SET := true -endif -endif - -# Test existence of SYSTEMC_ROOT environment variable -ifneq (SYSTEMC_SET, true) -ifneq (,${SYSTEMC_ROOT}) -SYSTEMC_SET := true -endif -endif - -# Test existence of SYSTEMC environment variable -ifneq (SYSTEMC_SET, true) -ifneq (,${SYSTEMC}) -SYSTEMC_SET := true -endif -endif +# Check if SC exists via a verilator call (empty if not) +SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) # Test whether SystemC is installed with CMake support # This will print a CMake error about processing arguments that can (currently) be ignored. -ifneq (SYSTEMC_SET, true) +ifneq (,$(SYSTEMC_EXISTS)) FINDSC := $(shell mkdir -p build && cd build && cmake --find-package -DNAME=SystemCLanguage -DCMAKE_USE_PTHREADS_INIT=ON -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST -DThreads_FOUND=ON) ifneq (,$(findstring SystemCLanguage found,$(FINDSC))) SYSTEMC_SET := true diff --git a/examples/make_hello_sc/Makefile b/examples/make_hello_sc/Makefile index 9548d716c..20a26d034 100644 --- a/examples/make_hello_sc/Makefile +++ b/examples/make_hello_sc/Makefile @@ -33,7 +33,7 @@ VERILATOR = $(VERILATOR_ROOT)/bin/verilator endif # Check if SC exists via a verilator call (empty if not) -SYSTEMC_EXISTS := $(shell $(VERILATOR) --getenv SYSTEMC_INCLUDE) +SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) ifneq ($(SYSTEMC_EXISTS),) default: run diff --git a/examples/make_tracing_sc/Makefile b/examples/make_tracing_sc/Makefile index 5f90a5ebf..cf61c8b7a 100644 --- a/examples/make_tracing_sc/Makefile +++ b/examples/make_tracing_sc/Makefile @@ -55,7 +55,7 @@ VERILATOR_FLAGS += --coverage VERILATOR_INPUT = -f input.vc top.v sc_main.cpp # Check if SC exists via a verilator call (empty if not) -SYSTEMC_EXISTS := $(shell $(VERILATOR) --getenv SYSTEMC_INCLUDE) +SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) ###################################################################### diff --git a/src/V3Options.cpp b/src/V3Options.cpp index cd556a21f..deb565700 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -604,6 +604,7 @@ V3LangCode V3Options::fileLanguage(const string& filename) { // Environment string V3Options::getenvBuiltins(const string& var) { + // If update below, also update V3Options::showVersion() if (var == "MAKE") { return getenvMAKE(); } else if (var == "PERL") { @@ -711,6 +712,17 @@ string V3Options::getenvVERILATOR_ROOT() { return var; } +string V3Options::getSupported(const string& var) { + // If update below, also update V3Options::showVersion() + if (var == "COROUTINES" && coroutineSupport()) { + return "1"; + } else if (var == "SYSTEMC" && systemCFound()) { + return "1"; + } else { + return ""; + } +} + bool V3Options::systemCSystemWide() { #ifdef HAVE_SYSTEMC return true; @@ -1179,6 +1191,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char cout << V3Options::getenvBuiltins(valp) << endl; std::exit(0); }); + DECL_OPTION("-get-supported", CbVal, [](const char* valp) { + cout << V3Options::getSupported(valp) << endl; + std::exit(0); + }); DECL_OPTION("-hierarchical", OnOff, &m_hierarchical); DECL_OPTION("-hierarchical-block", CbVal, [this](const char* valp) { @@ -1800,6 +1816,7 @@ void V3Options::showVersion(bool verbose) { cout << " VERILATOR_ROOT = " << DEFENV_VERILATOR_ROOT << endl; cout << " SystemC system-wide = " << cvtToStr(systemCSystemWide()) << endl; + // If update below, also update V3Options::getenvBuiltins() cout << endl; cout << "Environment:\n"; cout << " MAKE = " << V3Os::getenvStr("MAKE", "") << endl; @@ -1812,10 +1829,11 @@ void V3Options::showVersion(bool verbose) { cout << " VERILATOR_BIN = " << V3Os::getenvStr("VERILATOR_BIN", "") << endl; cout << " VERILATOR_ROOT = " << V3Os::getenvStr("VERILATOR_ROOT", "") << endl; + // If update below, also update V3Options::getSupported() cout << endl; - cout << "Features (based on environment or compiled-in support):\n"; - cout << " SystemC found = " << cvtToStr(systemCFound()) << endl; - cout << " Coroutine support = " << cvtToStr(coroutineSupport()) << endl; + cout << "Supported features (compiled-in or forced by environment):\n"; + cout << " COROUTINES = " << getSupported("COROUTINES") << endl; + cout << " SYSTEMC = " << getSupported("SYSTEMC") << endl; } //====================================================================== diff --git a/src/V3Options.h b/src/V3Options.h index a19c85269..c2c3852fc 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -666,6 +666,7 @@ public: static string getenvSYSTEMC_INCLUDE(); static string getenvSYSTEMC_LIBDIR(); static string getenvVERILATOR_ROOT(); + static string getSupported(const string& var); static bool systemCSystemWide(); static bool systemCFound(); // SystemC installed, or environment points to it static bool coroutineSupport(); // Compiler supports coroutines diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 3d71ef7dc..4bd739304 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -1476,13 +1476,13 @@ sub sc { sub have_sc { my $self = (ref $_[0] ? shift : $Self); return 1 if (defined $ENV{SYSTEMC} || defined $ENV{SYSTEMC_INCLUDE} || $ENV{CFG_HAVE_SYSTEMC}); - return 1 if $self->verilator_version =~ /systemc found *= *1/i; + return 1 if $self->verilator_get_supported('SYSTEMC'); return 0; } sub have_coroutines { my $self = (ref $_[0] ? shift : $Self); - return 1 if $self->verilator_version =~ /coroutine support *= *1/i; + return 1 if $self->verilator_get_supported('COROUTINES'); return 0; } @@ -2162,17 +2162,20 @@ sub _read_inputs_vhdl { ####################################################################### # Verilator utilities -our $_Verilator_Version; -sub verilator_version { - # Returns verbose version, line 1 contains actual version - if (!defined $_Verilator_Version) { - my @args = ("perl", "$ENV{VERILATOR_ROOT}/bin/verilator", "-V"); +our %_Verilator_Supported; +sub verilator_get_supported { + my $self = (ref $_[0] ? shift : $Self); + my $feature = shift; + # Returns if given feature is supported + if (!defined $_Verilator_Supported{$feature}) { + my @args = ("perl", "$ENV{VERILATOR_ROOT}/bin/verilator", "-get-supported", $feature); my $args = join(' ', @args); - $_Verilator_Version = `$args`; - $_Verilator_Version or die "can't fork: $! " . join(' ', @args); - chomp $_Verilator_Version; + my $out = `$args`; + $out or die "couldn't run: $! " . join(' ', @args); + chomp $out; + $_Verilator_Supported{$feature} = ($out =~ /1/ ? 1 : 0); } - return $_Verilator_Version if defined $_Verilator_Version; + return $_Verilator_Supported{$feature}; } ####################################################################### diff --git a/test_regress/t/t_flag_supported.pl b/test_regress/t/t_flag_supported.pl new file mode 100755 index 000000000..3effe6003 --- /dev/null +++ b/test_regress/t/t_flag_supported.pl @@ -0,0 +1,42 @@ +#!/usr/bin/env 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(vlt => 1); + +if ($Self->have_coroutines) { + run( + cmd => ["../bin/verilator --get-supported COROUTINES"], + expect => '1 +', + logfile => "$Self->{obj_dir}/vlt_coroutines.log", + verilator_run => 1, + ); +} + +if ($Self->have_sc) { + run( + cmd => ["../bin/verilator --get-supported SYSTEMC"], + expect => '1 +', + logfile => "$Self->{obj_dir}/vlt_systemc.log", + verilator_run => 1, + ); +} + +run( + cmd => ["../bin/verilator --get-supported DOES_NOT_EXIST"], + expect => '', + logfile => "$Self->{obj_dir}/vlt_does_not_exist.log", + verilator_run => 1, + ); + + +ok(1); +1;