diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 194631664bf9..5752c9cdb6ac 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -14,7 +14,7 @@ jobs: name: Sanity Check runs-on: ubuntu-latest container: - image: ghcr.io/circt/images/circt-ci-build:20240213211952 + image: ghcr.io/circt/images/circt-ci-build:20241113160334 steps: # Clone the CIRCT repo and its submodules. Do shallow clone to save clone # time. @@ -134,7 +134,7 @@ jobs: # John and re-run the job. runs-on: ["self-hosted", "1ES.Pool=1ES-CIRCT-builds", "linux"] container: - image: ghcr.io/circt/images/circt-ci-build:20240213211952 + image: ghcr.io/circt/images/circt-ci-build:20241113160334 volumes: - /mnt:/__w/circt strategy: @@ -143,13 +143,13 @@ jobs: # Our PR builds are trying to test the two corners of the build matrix: # clang + release + noassert + static # gcc + debug + assert + shared - - cc: clang - cxx: clang++ + - cc: clang-17 + cxx: clang++-17 mode: Debug assert: ON shared: ON - - cc: gcc - cxx: g++ + - cc: gcc-11 + cxx: g++-11 mode: Release assert: OFF shared: OFF diff --git a/.github/workflows/nightlyIntegrationTests.yml b/.github/workflows/nightlyIntegrationTests.yml index aad654bab9b4..c33d0d01635d 100644 --- a/.github/workflows/nightlyIntegrationTests.yml +++ b/.github/workflows/nightlyIntegrationTests.yml @@ -32,10 +32,10 @@ jobs: build-shared: [ON, OFF] build-type: [Debug, Release] compiler: - - cc: clang - cxx: clang++ - - cc: gcc - cxx: g++ + - cc: clang-17 + cxx: clang++-17 + - cc: gcc-11 + cxx: g++-11 lit-flags: ['', '--vg'] exclude: - build-type: Debug @@ -48,7 +48,7 @@ jobs: build-shared: ON # TODO: This corner is failing and has been for some time. #5253. - build-type: Release - compiler: {cc: gcc, cxx: g++} + compiler: {cc: gcc-11, cxx: g++-11} lit-flags: --vg steps: diff --git a/.github/workflows/shortIntegrationTests.yml b/.github/workflows/shortIntegrationTests.yml index e85f98d8bcfb..dcc68d234901 100644 --- a/.github/workflows/shortIntegrationTests.yml +++ b/.github/workflows/shortIntegrationTests.yml @@ -40,8 +40,8 @@ jobs: build-shared: [ON] build-type: [Release] compiler: - - cc: clang - cxx: clang++ + - cc: clang-17 + cxx: clang++-17 steps: # Clone the CIRCT repo and its submodules. Do shallow clone to save clone diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e9e31f019cb..895bfb6b581f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -554,14 +554,17 @@ llvm_canonicalize_cmake_booleans(CIRCT_SLANG_BUILD_FROM_SOURCE) if(CIRCT_SLANG_FRONTEND_ENABLED) message(STATUS "slang Verilog frontend is enabled") if(CIRCT_SLANG_BUILD_FROM_SOURCE) + # slang requires C++20 + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + # Build slang as part of CIRCT (see https://sv-lang.com/building.html) message(STATUS "Building slang from source") include(FetchContent) FetchContent_Declare( slang GIT_REPOSITORY https://github.com/MikePopoloski/slang.git - GIT_TAG v3.0 - GIT_SHALLOW ON) + GIT_TAG bad0d6ba3dec20355b0156c535bbddf2f926ab37) set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE "NEVER") # Force Slang to be built as a static library to avoid messing around with @@ -576,6 +579,7 @@ if(CIRCT_SLANG_FRONTEND_ENABLED) set(CMAKE_CXX_FLAGS "") endif () set(BUILD_SHARED_LIBS OFF) + set(SLANG_USE_MIMALLOC OFF) FetchContent_MakeAvailable(slang) set(CMAKE_CXX_FLAGS ${ORIGINAL_CMAKE_CXX_FLAGS}) @@ -584,7 +588,6 @@ if(CIRCT_SLANG_FRONTEND_ENABLED) if(BUILD_SHARED_LIBS) set_target_properties(slang_slang PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON) - set_target_properties(unordered_dense PROPERTIES POSITION_INDEPENDENT_CODE ON) endif() # The following feels *very* hacky, but CMake complains about the @@ -593,17 +596,24 @@ if(CIRCT_SLANG_FRONTEND_ENABLED) # statically link slang into the CIRCTImportVerilog library, but seems to be # harder than it ought to be. set_property( - GLOBAL APPEND PROPERTY CIRCT_EXPORTS slang_slang unordered_dense fmt) + GLOBAL APPEND PROPERTY CIRCT_EXPORTS slang_slang fmt) # Disable the installation of headers coming from third-party libraries. We # won't use those APIs directly. Just make them static libraries for the sake # of running slang normally. set_target_properties(fmt PROPERTIES PUBLIC_HEADER "") - set_target_properties(unordered_dense PROPERTIES PUBLIC_HEADER "") - install(TARGETS slang_slang unordered_dense fmt EXPORT CIRCTTargets) + install(TARGETS slang_slang fmt EXPORT CIRCTTargets) + + # Match the behavior of slang_slang, which installs its own vendored + # boost_unordered if it does not a system-wide boost installation. + find_package(Boost 1.82.0 QUIET) + if(NOT Boost_FOUND) + set_property(GLOBAL APPEND PROPERTY CIRCT_EXPORTS boost_unordered) + install(TARGETS boost_unordered EXPORT CIRCTTargets) + endif() else() - find_package(slang 3.0 REQUIRED) + find_package(slang 7.0 REQUIRED) endif() endif() diff --git a/include/circt/Support/FVInt.h b/include/circt/Support/FVInt.h index dfafb5b96481..43d0153fa86b 100644 --- a/include/circt/Support/FVInt.h +++ b/include/circt/Support/FVInt.h @@ -646,8 +646,8 @@ inline FVInt operator-(uint64_t a, const FVInt &b) { inline FVInt operator-(const APInt &a, const FVInt &b) { return FVInt(a) - b; } -inline bool operator==(uint64_t a, const FVInt &b) { return b == a; } -inline bool operator!=(uint64_t a, const FVInt &b) { return b != a; } +inline bool operator==(uint64_t a, const FVInt &b) { return b.operator==(a); } +inline bool operator!=(uint64_t a, const FVInt &b) { return b.operator!=(a); } inline raw_ostream &operator<<(raw_ostream &os, const FVInt &value) { value.print(os); diff --git a/lib/Conversion/ImportVerilog/CMakeLists.txt b/lib/Conversion/ImportVerilog/CMakeLists.txt index d813fa908ce7..1673d05258aa 100644 --- a/lib/Conversion/ImportVerilog/CMakeLists.txt +++ b/lib/Conversion/ImportVerilog/CMakeLists.txt @@ -1,7 +1,3 @@ -# slang uses exceptions -set(LLVM_REQUIRES_EH ON) -set(LLVM_REQUIRES_RTTI ON) - # For ABI compatibility, define the DEBUG macro in debug builds. Slang sets this # internally. If we don't set this here as well, header-defined things like the # destructor of `Driver`, which is generated in ImportVerilog's compilation @@ -15,15 +11,10 @@ add_compile_definitions($<$:DEBUG>) if (MSVC) # No idea what to put here else () - # slang uses exceptions; we intercept these in ImportVerilog - add_compile_options(-fexceptions) - add_compile_options(-frtti) # slang has some classes with virtual funcs but non-virtual destructor. add_compile_options(-Wno-non-virtual-dtor) # some other warnings we've seen - add_compile_options(-Wno-c++98-compat-extra-semi) add_compile_options(-Wno-ctad-maybe-unsupported) - add_compile_options(-Wno-cast-qual) # visitor switch statements cover all cases but have default add_compile_options(-Wno-covered-switch-default) endif () @@ -50,3 +41,11 @@ add_circt_translation_library(CIRCTImportVerilog PRIVATE slang_slang ) + +# HACK: When `OBJECT` argument is passed to `llvm_add_library()`, +# `COMPILE_DEFINITIONS` are not correctly inherited. For that reason, +# we manually set it here. +if(TARGET obj.CIRCTImportVerilog) + get_target_property(compile_defs Boost::headers INTERFACE_COMPILE_DEFINITIONS) + target_compile_definitions(obj.CIRCTImportVerilog PRIVATE ${compile_defs}) +endif() diff --git a/lib/Conversion/ImportVerilog/Expressions.cpp b/lib/Conversion/ImportVerilog/Expressions.cpp index 6f0706ef155a..4bd4f4b14c32 100644 --- a/lib/Conversion/ImportVerilog/Expressions.cpp +++ b/lib/Conversion/ImportVerilog/Expressions.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ImportVerilogInternals.h" +#include "slang/ast/EvalContext.h" #include "slang/ast/SystemSubroutine.h" #include "slang/syntax/AllSyntax.h" @@ -526,7 +527,7 @@ struct RvalueExprVisitor { // The open range list on the right-hand side of the inside operator is a // comma-separated list of expressions or ranges. if (const auto *openRange = - listExpr->as_if()) { + listExpr->as_if()) { // Handle ranges. auto lowBound = context.convertToSimpleBitVector( context.convertRvalueExpression(openRange->left())); @@ -1022,7 +1023,9 @@ slang::ConstantValue Context::evaluateConstant(const slang::ast::Expression &expr) { using slang::ast::EvalFlags; slang::ast::EvalContext evalContext( - compilation, EvalFlags::CacheResults | EvalFlags::SpecparamsAllowed); + slang::ast::ASTContext(compilation.getRoot(), + slang::ast::LookupLocation::max), + EvalFlags::CacheResults | EvalFlags::SpecparamsAllowed); return expr.eval(evalContext); } diff --git a/lib/Conversion/ImportVerilog/FormatStrings.cpp b/lib/Conversion/ImportVerilog/FormatStrings.cpp index 7698ad142b71..b3b15daac18d 100644 --- a/lib/Conversion/ImportVerilog/FormatStrings.cpp +++ b/lib/Conversion/ImportVerilog/FormatStrings.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "ImportVerilogInternals.h" -#include "slang/text/SFormat.h" +#include "slang/ast/SFormat.h" using namespace mlir; using namespace circt; @@ -15,7 +15,7 @@ using namespace ImportVerilog; using moore::IntAlign; using moore::IntFormat; using moore::IntPadding; -using slang::SFormat::FormatOptions; +using slang::ast::SFormat::FormatOptions; namespace { struct FormatStringParser { @@ -87,7 +87,7 @@ struct FormatStringParser { auto onError = [&](auto, auto, auto, auto) { assert(false && "Slang should have already reported all errors"); }; - slang::SFormat::parse(format, onText, onArg, onError); + slang::ast::SFormat::parse(format, onText, onArg, onError); return failure(anyFailure); } @@ -191,7 +191,7 @@ struct FormatStringParser { } // namespace FailureOr Context::convertFormatString( - slang::span arguments, Location loc, + std::span arguments, Location loc, IntFormat defaultFormat, bool appendNewline) { FormatStringParser parser(*this, ArrayRef(arguments.data(), arguments.size()), loc, defaultFormat); diff --git a/lib/Conversion/ImportVerilog/ImportVerilog.cpp b/lib/Conversion/ImportVerilog/ImportVerilog.cpp index 773893fa3c84..8d4029f97445 100644 --- a/lib/Conversion/ImportVerilog/ImportVerilog.cpp +++ b/lib/Conversion/ImportVerilog/ImportVerilog.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "ImportVerilogInternals.h" -#include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/Verifier.h" #include "mlir/Support/Timing.h" @@ -23,7 +22,7 @@ #include "slang/driver/Driver.h" #include "slang/parsing/Preprocessor.h" #include "slang/syntax/SyntaxPrinter.h" -#include "slang/util/Version.h" +#include "slang/util/VersionInfo.h" using namespace mlir; using namespace circt; @@ -92,11 +91,10 @@ class MlirDiagnosticClient : public slang::DiagnosticClient { mlirDiag << " [-W" << optionName << "]"; // Write out macro expansions, if we have any, in reverse order. - for (auto it = diag.expansionLocs.rbegin(); it != diag.expansionLocs.rend(); - it++) { + for (auto loc : std::views::reverse(diag.expansionLocs)) { auto ¬e = mlirDiag.attachNote( - convertLocation(sourceManager->getFullyOriginalLoc(*it))); - auto macroName = sourceManager->getMacroName(*it); + convertLocation(sourceManager->getFullyOriginalLoc(loc))); + auto macroName = sourceManager->getMacroName(loc); if (macroName.empty()) note << "expanded from here"; else @@ -202,15 +200,29 @@ LogicalResult ImportDriver::prepareDriver(SourceMgr &sourceMgr) { const llvm::MemoryBuffer *mlirBuffer = sourceMgr.getMemoryBuffer(i + 1); auto slangBuffer = driver.sourceManager.assignText( mlirBuffer->getBufferIdentifier(), mlirBuffer->getBuffer()); - driver.buffers.push_back(slangBuffer); + driver.sourceLoader.addBuffer(slangBuffer); bufferFilePaths.insert({slangBuffer.id, mlirBuffer->getBufferIdentifier()}); } + for (const auto &libDir : options.libDirs) + driver.sourceLoader.addSearchDirectories(libDir); + + for (const auto &libExt : options.libExts) + driver.sourceLoader.addSearchExtension(libExt); + + for (const auto &includeDir : options.includeDirs) { + if (driver.sourceManager.addUserDirectories(includeDir)) { + return failure(); + } + } + + for (const auto &includeDir : options.includeSystemDirs) { + if (driver.sourceManager.addSystemDirectories(includeDir)) { + return failure(); + } + } + // Populate the driver options. - driver.options.includeDirs = options.includeDirs; - driver.options.includeSystemDirs = options.includeSystemDirs; - driver.options.libDirs = options.libDirs; - driver.options.libExts = options.libExts; driver.options.excludeExts.insert(options.excludeExts.begin(), options.excludeExts.end()); driver.options.ignoreDirectives = options.ignoreDirectives; @@ -221,22 +233,22 @@ LogicalResult ImportDriver::prepareDriver(SourceMgr &sourceMgr) { driver.options.librariesInheritMacros = options.librariesInheritMacros; driver.options.timeScale = options.timeScale; - driver.options.allowUseBeforeDeclare = options.allowUseBeforeDeclare; - driver.options.ignoreUnknownModules = options.ignoreUnknownModules; - driver.options.onlyLint = - options.mode == ImportVerilogOptions::Mode::OnlyLint; + driver.options.compilationFlags.emplace( + slang::ast::CompilationFlags::AllowUseBeforeDeclare, + options.allowUseBeforeDeclare); + driver.options.compilationFlags.emplace( + slang::ast::CompilationFlags::IgnoreUnknownModules, + options.ignoreUnknownModules); + driver.options.compilationFlags.emplace( + slang::ast::CompilationFlags::LintMode, + options.mode == ImportVerilogOptions::Mode::OnlyLint); driver.options.topModules = options.topModules; driver.options.paramOverrides = options.paramOverrides; driver.options.errorLimit = options.errorLimit; driver.options.warningOptions = options.warningOptions; - driver.options.suppressWarningsPaths = options.suppressWarningsPaths; driver.options.singleUnit = options.singleUnit; - driver.options.libraryFiles = options.libraryFiles; - - for (auto &dir : sourceMgr.getIncludeDirs()) - driver.options.includeDirs.push_back(dir); return success(driver.processOptions()); } @@ -318,12 +330,13 @@ LogicalResult ImportDriver::preprocessVerilog(llvm::raw_ostream &os) { diagnostics, optionBag); // Sources have to be pushed in reverse, as they form a stack in the // preprocessor. Last pushed source is processed first. - for (auto &buffer : slang::make_reverse_range(driver.buffers)) + auto sources = driver.sourceLoader.loadSources(); + for (auto &buffer : std::views::reverse(sources)) preprocessor.pushSource(buffer); if (failed(preprocessAndPrint(preprocessor))) return failure(); } else { - for (auto &buffer : driver.buffers) { + for (auto &buffer : driver.sourceLoader.loadSources()) { slang::BumpAllocator alloc; slang::Diagnostics diagnostics; slang::parsing::Preprocessor preprocessor(driver.sourceManager, alloc, @@ -341,28 +354,15 @@ LogicalResult ImportDriver::preprocessVerilog(llvm::raw_ostream &os) { // Entry Points //===----------------------------------------------------------------------===// -/// Execute a callback and report any thrown exceptions as "internal slang -/// error" MLIR diagnostics. -static LogicalResult -catchExceptions(llvm::function_ref callback) { - try { - return callback(); - } catch (const std::exception &e) { - return emitError(UnknownLoc(), "internal slang error: ") << e.what(); - } -} - /// Parse the specified Verilog inputs into the specified MLIR context. LogicalResult circt::importVerilog(SourceMgr &sourceMgr, MLIRContext *mlirContext, TimingScope &ts, ModuleOp module, const ImportVerilogOptions *options) { - return catchExceptions([&] { - ImportDriver importDriver(mlirContext, ts, options); - if (failed(importDriver.prepareDriver(sourceMgr))) - return failure(); - return importDriver.importVerilog(module); - }); + ImportDriver importDriver(mlirContext, ts, options); + if (failed(importDriver.prepareDriver(sourceMgr))) + return failure(); + return importDriver.importVerilog(module); } /// Run the files in a source manager through Slang's Verilog preprocessor and @@ -371,12 +371,10 @@ LogicalResult circt::preprocessVerilog(SourceMgr &sourceMgr, MLIRContext *mlirContext, TimingScope &ts, llvm::raw_ostream &os, const ImportVerilogOptions *options) { - return catchExceptions([&] { - ImportDriver importDriver(mlirContext, ts, options); - if (failed(importDriver.prepareDriver(sourceMgr))) - return failure(); - return importDriver.preprocessVerilog(os); - }); + ImportDriver importDriver(mlirContext, ts, options); + if (failed(importDriver.prepareDriver(sourceMgr))) + return failure(); + return importDriver.preprocessVerilog(os); } /// Entry point as an MLIR translation. diff --git a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h index b045ffe00713..463b73d3857b 100644 --- a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h +++ b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h @@ -140,7 +140,7 @@ struct Context { /// failure if an error occurs. Returns a null value if the formatted string /// is trivially empty. Otherwise returns the formatted string. FailureOr convertFormatString( - slang::span arguments, Location loc, + std::span arguments, Location loc, moore::IntFormat defaultFormat = moore::IntFormat::Decimal, bool appendNewline = false); diff --git a/lib/Conversion/ImportVerilog/Structure.cpp b/lib/Conversion/ImportVerilog/Structure.cpp index c7b5548c92d1..70b5361f4768 100644 --- a/lib/Conversion/ImportVerilog/Structure.cpp +++ b/lib/Conversion/ImportVerilog/Structure.cpp @@ -602,7 +602,7 @@ Context::convertModuleHeader(const slang::ast::InstanceBodySymbol *module) { using slang::ast::PortSymbol; using slang::ast::TypeParameterSymbol; - auto parameters = module->parameters; + auto parameters = module->getParameters(); bool hasModuleSame = false; // If there is already exist a module that has the same name with this // module ,has the same parent scope and has the same parameters we can @@ -610,7 +610,7 @@ Context::convertModuleHeader(const slang::ast::InstanceBodySymbol *module) { for (auto const &existingModule : modules) { if (module->getDeclaringDefinition() == existingModule.getFirst()->getDeclaringDefinition()) { - auto moduleParameters = existingModule.getFirst()->parameters; + auto moduleParameters = existingModule.getFirst()->getParameters(); hasModuleSame = true; for (auto it1 = parameters.begin(), it2 = moduleParameters.begin(); it1 != parameters.end() && it2 != moduleParameters.end(); diff --git a/lib/Dialect/FIRRTL/FIRRTLOps.cpp b/lib/Dialect/FIRRTL/FIRRTLOps.cpp index 0b4ca6f76e66..9ca12e4ccad9 100644 --- a/lib/Dialect/FIRRTL/FIRRTLOps.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLOps.cpp @@ -1579,7 +1579,7 @@ LogicalResult FModuleOp::verify() { for (auto [arg, type, loc] : zip(body->getArguments(), portTypes, portLocs)) { if (arg.getType() != cast(type).getValue()) return emitOpError("block argument types should match signature types"); - if (arg.getLoc() != cast(loc)) + if (arg.getLoc() != cast(loc)) return emitOpError( "block argument locations should match signature locations"); } diff --git a/lib/Transforms/StripDebugInfoWithPred.cpp b/lib/Transforms/StripDebugInfoWithPred.cpp index 26e388e0e88b..54cf440edc93 100644 --- a/lib/Transforms/StripDebugInfoWithPred.cpp +++ b/lib/Transforms/StripDebugInfoWithPred.cpp @@ -57,7 +57,7 @@ struct StripDebugInfoWithPred SmallVector newLocs; if (auto resLocs = op->getAttrOfType(attributeName)) { bool changed = false; - for (auto loc : resLocs.getAsRange()) { + for (auto loc : resLocs.getAsRange()) { auto newLoc = getStrippedLoc(loc); changed |= newLoc != loc; newLocs.push_back(newLoc); diff --git a/test/circt-verilog/commandline.sv b/test/circt-verilog/commandline.sv index 32b94be04aaf..4ed83bd83b03 100644 --- a/test/circt-verilog/commandline.sv +++ b/test/circt-verilog/commandline.sv @@ -3,4 +3,4 @@ // REQUIRES: slang // CHECK-HELP: OVERVIEW: Verilog and SystemVerilog frontend -// CHECK-VERSION: slang version 3. +// CHECK-VERSION: slang version 7. diff --git a/test/circt-verilog/preprocess-errors.sv b/test/circt-verilog/preprocess-errors.sv index 814345e30ffa..325e22092fa6 100644 --- a/test/circt-verilog/preprocess-errors.sv +++ b/test/circt-verilog/preprocess-errors.sv @@ -1,5 +1,5 @@ // RUN: circt-verilog %s -E --verify-diagnostics // REQUIRES: slang -// expected-error @below {{could not find or open include file}} +// expected-error @below {{'unknown.sv': No such file or directory}} `include "unknown.sv"