From 3c1b82255e91962ffdc1d2737b4898faf18e2270 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 7 Oct 2017 21:29:57 -0400 Subject: [PATCH] Change VL_THREADED to use C++11, and compute and test related GCC flags automatically --- Changes | 2 ++ MANIFEST.SKIP | 1 + configure.ac | 32 ++++++++++++++++++++++---- examples/tracing_c/Makefile_obj | 1 - examples/tracing_sc/Makefile_obj | 1 - include/verilated.cpp | 32 +++++++++++++------------- include/verilated.h | 6 ++--- include/verilated.mk.in | 4 ++++ include/verilated_vpi.cpp | 9 ++++---- include/verilated_vpi.h | 6 ++--- include/verilatedos.h | 22 +++++++++++------- src/V3Broken.cpp | 4 ++-- test_regress/Makefile_obj | 9 ++++++++ test_regress/t/t_include_all_newest.pl | 25 ++++++++++++++++++++ test_regress/t/t_include_all_oldest.pl | 25 ++++++++++++++++++++ 15 files changed, 136 insertions(+), 43 deletions(-) create mode 100755 test_regress/t/t_include_all_newest.pl create mode 100755 test_regress/t/t_include_all_oldest.pl diff --git a/Changes b/Changes index a0fba546c..4e9b5fc0a 100644 --- a/Changes +++ b/Changes @@ -17,6 +17,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** The internal test_verilated test directory is moved to be part of test_regress. +**** The experimental VL_THREADED setting (only, not normal mode) now requires C++11. + **** Fix over-aggressive inlining, bug1223. [John Coiner] **** Fix Ubuntu 17.10 issues, bug1223 partial. [John Coiner] diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index 0c901cad4..aef9199c6 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -39,5 +39,6 @@ nodist/ /vc_hdrs.h$ /csrc/ doxygen-doc/.* +obj_dir/.* TAGS .*~ diff --git a/configure.ac b/configure.ac index 41fc5e50a..f6233c3c1 100644 --- a/configure.ac +++ b/configure.ac @@ -140,10 +140,12 @@ AC_DEFUN([_MY_CXX_CHECK_FLAG], AC_DEFUN([_MY_CXX_CHECK_SET], [# _MY_CXX_CHECK_SET(variable,flag) -- Check if compiler supports specific options - # If it does, set variable to flag - _MY_CXX_CHECK_FLAG($2) - if test "$_my_result" = "yes" ; then - $1="$$1 $2" + # If it does, set variable to flag, only if not previously set + if test "$$1" = ""; then + _MY_CXX_CHECK_FLAG($2) + if test "$_my_result" = "yes" ; then + $1="$2" + fi fi ]) @@ -156,6 +158,28 @@ AC_DEFUN([_MY_CXX_CHECK_OPT], fi ]) +# Flag to select newest language standard supported +# Macros work such that first option that passes is the one we take +# gnu++14 is the newest that Verilator supports +# std++03 is the oldest that Verilator supports +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++14) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++11) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++03) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++14) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++11) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++03) +AC_SUBST(CFG_CXXFLAGS_STD_NEWEST) +# And likewise oldest standard (same list above, backwards) +# This is used for internal testing +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++03) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++11) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++14) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++03) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++11) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++14) +_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++17) +AC_SUBST(CFG_CXXFLAGS_STD_OLDEST) + # Flags for compiling Verilator internals including parser, and Verilated files # These turn on extra warnings and are only used with 'configure --enable-ccwarn' _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wextra) diff --git a/examples/tracing_c/Makefile_obj b/examples/tracing_c/Makefile_obj index 7fa08631e..610a9394c 100644 --- a/examples/tracing_c/Makefile_obj +++ b/examples/tracing_c/Makefile_obj @@ -25,7 +25,6 @@ CPPFLAGS += -MMD -MP CPPFLAGS += -DVL_DEBUG=1 # Turn on some more flags (when configured appropriately) ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users -CPPFLAGS += -DVL_THREADED=1 CPPFLAGS += -W -Werror -Wall endif diff --git a/examples/tracing_sc/Makefile_obj b/examples/tracing_sc/Makefile_obj index cd984f7b9..4a19800d7 100644 --- a/examples/tracing_sc/Makefile_obj +++ b/examples/tracing_sc/Makefile_obj @@ -27,7 +27,6 @@ CPPFLAGS += -DVL_DEBUG=1 CPPFLAGS += -Wno-deprecated # Turn on some more flags (when configured appropriately) ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users -CPPFLAGS += -DVL_THREADED=1 CPPFLAGS += -W -Werror -Wall endif diff --git a/include/verilated.cpp b/include/verilated.cpp index d44b50beb..bb44e8efb 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -37,9 +37,9 @@ VerilatedVoidCb Verilated::s_flushCb = NULL; // Keep below together in one cache line Verilated::Serialized Verilated::s_s; -VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL; -VL_THREAD const char* Verilated::t_dpiFilename = ""; -VL_THREAD int Verilated::t_dpiLineno = 0; +VL_THREAD_LOCAL const VerilatedScope* Verilated::t_dpiScopep = NULL; +VL_THREAD_LOCAL const char* Verilated::t_dpiFilename = ""; +VL_THREAD_LOCAL int Verilated::t_dpiLineno = 0; struct Verilated::CommandArgValues Verilated::s_args = {0, NULL}; VerilatedImp VerilatedImp::s_s; @@ -372,8 +372,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) { // 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 char tmp[VL_VALUE_STRING_MAX_WIDTH]; - static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char tmpf[VL_VALUE_STRING_MAX_WIDTH]; const char* pctp = NULL; // Most recent %##.##g format bool inPct = false; bool widthSet = false; @@ -657,7 +657,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 char tmp[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH]; int floc = fbits - 1; IData got = 0; bool inPct = false; @@ -881,7 +881,7 @@ void VL_FCLOSE_I(IData fdi) { } void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; va_start(ap,formatp); @@ -892,7 +892,7 @@ void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) { } void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; va_start(ap,formatp); @@ -903,7 +903,7 @@ void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) { } void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; va_start(ap,formatp); @@ -914,7 +914,7 @@ void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) { } void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; va_start(ap,formatp); @@ -925,7 +925,7 @@ void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) { } void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; va_start(ap,formatp); @@ -945,7 +945,7 @@ void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, . } std::string VL_SFORMATF_NX(const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; va_start(ap,formatp); @@ -956,7 +956,7 @@ std::string VL_SFORMATF_NX(const char* formatp, ...) { } void VL_WRITEF(const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; va_list ap; va_start(ap,formatp); @@ -968,7 +968,7 @@ void VL_WRITEF(const char* formatp, ...) { } void VL_FWRITEF(IData fpi, const char* formatp, ...) { - VL_STATIC_OR_THREAD std::string output; // static only for speed + static VL_THREAD_LOCAL std::string output; // static only for speed output = ""; FILE* fp = VL_CVT_I_FP(fpi); if (VL_UNLIKELY(!fp)) return; @@ -1247,7 +1247,7 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) { const char* vl_mc_scan_plusargs(const char* prefixp) { const std::string& match = VerilatedImp::argPlusMatch(prefixp); - static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH]; if (match == "") return NULL; strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+" VL_VALUE_STRING_MAX_WIDTH); @@ -1315,7 +1315,7 @@ void Verilated::commandArgs(int argc, const char** argv) { const char* Verilated::commandArgsPlusMatch(const char* prefixp) { const std::string& match = VerilatedImp::argPlusMatch(prefixp); - static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH]; + static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH]; if (match == "") return ""; strncpy(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH); outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0'; diff --git a/include/verilated.h b/include/verilated.h index 73b931c5d..cf9651c14 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -234,9 +234,9 @@ class Verilated { Serialized(); } s_s; - static VL_THREAD const VerilatedScope* t_dpiScopep; ///< DPI context scope - static VL_THREAD const char* t_dpiFilename; ///< DPI context filename - static VL_THREAD int t_dpiLineno; ///< DPI context line number + static VL_THREAD_LOCAL const VerilatedScope* t_dpiScopep; ///< DPI context scope + static VL_THREAD_LOCAL const char* t_dpiFilename; ///< DPI context filename + static VL_THREAD_LOCAL int t_dpiLineno; ///< DPI context line number // no need to be save-restored (serialized) the // assumption is that the restore is allowed to pass different arguments diff --git a/include/verilated.mk.in b/include/verilated.mk.in index 6c17ef03d..584427299 100644 --- a/include/verilated.mk.in +++ b/include/verilated.mk.in @@ -16,6 +16,10 @@ RANLIB = ranlib CFG_WITH_CCWARN = @CFG_WITH_CCWARN@ CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@ +# Select newest language +CFG_CXXFLAGS_STD_NEWEST = @CFG_CXXFLAGS_STD_NEWEST@ +# Select oldest language (for Verilator internal testing only) +CFG_CXXFLAGS_STD_OLDEST = @CFG_CXXFLAGS_STD_OLDEST@ # Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@ # Compiler flags that turn on extra warnings diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 5b22f40a7..61be1a02e 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -721,9 +721,9 @@ void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) { // value processing void vpi_get_value(vpiHandle object, p_vpi_value value_p) { - static VL_THREAD char outStr[1+VL_MULS_MAX_WORDS*32]; // 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]; // Maximum required size is for binary string, one byte per bit plus null termination // cppcheck-suppress variableScope - static VL_THREAD int outStrSz = sizeof(outStr)-1; + static VL_THREAD_LOCAL int outStrSz = sizeof(outStr)-1; VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object);); _VL_VPI_ERROR_RESET(); // reset vpi error status if (VL_UNLIKELY(!value_p)) return; @@ -733,7 +733,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { if (value_p->format == vpiVectorVal) { // Vector pointer must come from our memory pool // It only needs to persist until the next vpi_get_value - static VL_THREAD t_vpi_vecval out[VL_MULS_MAX_WORDS*2]; + static VL_THREAD_LOCAL t_vpi_vecval out[VL_MULS_MAX_WORDS*2]; value_p->value.vector = out; switch (vop->varp()->vltype()) { case VLVT_UINT8: @@ -884,7 +884,6 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { } for (i=0; i>1]>>((i&1)<<2))&15; - static char hex[] = "0123456789abcdef"; if (i==(chars-1)) { // most signifcant char, mask off non existant bits when vector // size is not a multiple of 4 @@ -894,7 +893,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) { val &= (1<(val)]; + outStr[chars-i-1] = "0123456789abcdef"[static_cast(val)]; } outStr[i]=0; // NULL terminate return; diff --git a/include/verilated_vpi.h b/include/verilated_vpi.h index a360c222b..1f6f76d38 100644 --- a/include/verilated_vpi.h +++ b/include/verilated_vpi.h @@ -215,7 +215,7 @@ public: virtual const VerilatedRange* rangep() const { return &get_range(); } virtual const char* name() { return m_varp->name(); } virtual const char* fullname() { - VL_STATIC_OR_THREAD std::string out; + static VL_THREAD_LOCAL std::string out; out = std::string(m_scopep->name())+"."+name(); return out.c_str(); } @@ -243,7 +243,7 @@ public: virtual vluint32_t size() const { return varp()->range().elements(); } virtual const VerilatedRange* rangep() const { return &(varp()->range()); } virtual const char* fullname() { - VL_STATIC_OR_THREAD std::string out; + static VL_THREAD_LOCAL std::string out; char num[20]; sprintf(num,"%d",m_index); out = std::string(scopep()->name())+"."+name()+"["+num+"]"; return out.c_str(); @@ -464,7 +464,7 @@ public: return this; } void setMessage(std::string file, PLI_INT32 line, std::string message, ...) { - static VL_THREAD std::string filehold; + static VL_THREAD_LOCAL std::string filehold; _VL_VPI_ERROR_SET; m_errorInfo.state = vpiPLI; filehold = file; diff --git a/include/verilatedos.h b/include/verilatedos.h index 48f46e1b4..462739752 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -77,17 +77,18 @@ #ifdef VL_THREADED # ifdef __GNUC__ -# define VL_THREAD __thread ///< Storage class for thread-local storage +# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING) +# error "VL_THREADED support plans to move to C++-11 and later only; use newer --std to be ready" +# endif # else # error "Unsupported compiler for VL_THREADED: No thread-local declarator" # endif -# define VL_STATIC_OR_THREAD ///< Static if unthreaded, as some strings can be faster -// ///< if non-dynamic and can't do "static VL_THREAD string" +# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread #else -# define VL_THREAD ///< Storage class for thread-local storage -# define VL_STATIC_OR_THREAD static ///< Static if unthreaded, as some strings can be faster -// ///< if non-dynamic and can't do "static VL_THREAD string" +# define VL_THREAD_LOCAL ///< Use new C++ static local thread #endif +#define VL_THREAD ///< Deprecated +#define VL_STATIC_OR_THREAD static ///< Deprecated #ifdef _MSC_VER # define VL_ULL(c) (c##ui64) ///< Add appropriate suffix to 64-bit constant @@ -109,9 +110,14 @@ #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) # define VL_HAS_UNIQUE_PTR -# define VL_UNIQUE_PTR unique_ptr +# define VL_HAS_UNORDERED_MAP +# define VL_UNIQUE_PTR std::unique_ptr +# define VL_UNORDERED_MAP std::unordered_map +# define VL_INCLUDE_UNORDERED_MAP #else -# define VL_UNIQUE_PTR auto_ptr +# define VL_UNIQUE_PTR std::auto_ptr +# define VL_UNORDERED_MAP std::map +# define VL_INCLUDE_UNORDERED_MAP #endif //========================================================================= diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index f73862c58..724d841a6 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include VL_INCLUDE_UNORDERED_MAP #include "V3Global.h" #include "V3Broken.h" @@ -47,7 +47,7 @@ class BrokenTable : public AstNVisitor { private: // MEMBERS // For each node, we keep if it exists or not. - typedef map NodeMap; + typedef VL_UNORDERED_MAP NodeMap; // Performance matters (when --debug) static NodeMap s_nodes; // Set of all nodes that exist // BITMASK enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed diff --git a/test_regress/Makefile_obj b/test_regress/Makefile_obj index 3d0d0c641..40cf8e7be 100644 --- a/test_regress/Makefile_obj +++ b/test_regress/Makefile_obj @@ -35,6 +35,15 @@ CPPFLAGS += $(CPPFLAGS_DRIVER) CPPFLAGS += $(CPPFLAGS_DRIVER2) CPPFLAGS += $(CPPFLAGS_ADD) +ifeq ($(CFG_WITH_LONGTESTS),yes) + ifeq ($(DRIVER_STD),newest) + CPPFLAGS += $(CFG_CXXFLAGS_STD_NEWEST) + endif + ifeq ($(DRIVER_STD),oldest) + CPPFLAGS += $(CFG_CXXFLAGS_STD_OLDEST) + endif +endif + ####################################################################### # Linking final exe diff --git a/test_regress/t/t_include_all_newest.pl b/test_regress/t/t_include_all_newest.pl new file mode 100755 index 000000000..b386a4e71 --- /dev/null +++ b/test_regress/t/t_include_all_newest.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. + +top_filename("t/t_include_all.v"); + +my $root = ".."; + +compile ( + # Can't use --coverage and --savable together, so cheat and compile inline + verilator_flags2 => ['--cc --coverage-toggle --coverage-line --coverage-user --trace --vpi $root/include/verilated_save.cpp'], + make_flags => 'DRIVER_STD=newest CPPFLAGS_ADD=-DVL_THREADED=1', + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_include_all_oldest.pl b/test_regress/t/t_include_all_oldest.pl new file mode 100755 index 000000000..a0077af6f --- /dev/null +++ b/test_regress/t/t_include_all_oldest.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. + +top_filename("t/t_include_all.v"); + +my $root = ".."; + +compile ( + # Can't use --coverage and --savable together, so cheat and compile inline + verilator_flags2 => ['--cc --coverage-toggle --coverage-line --coverage-user --trace --vpi $root/include/verilated_save.cpp'], + make_flags => 'DRIVER_STD=oldest', + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1;