Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 22 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON)

set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to")
set(CMAKE_CXX_STANDARD_REQUIRED YES)
# NOTE: If the Slang Verilog frontend is enabled, the libraries interfacing with
# Slang will be built using the C++20 standard. (See SlangCompilerOptions.cmake)

# If we are not building as a part of LLVM, build Circt as an
# standalone project, using LLVM as an external library:
Expand Down Expand Up @@ -562,22 +564,18 @@ if(CIRCT_SLANG_FRONTEND_ENABLED)
FetchContent_Declare(
slang
GIT_REPOSITORY https://github.com/MikePopoloski/slang.git
GIT_TAG v3.0
GIT_TAG v8.0
GIT_SHALLOW ON)
set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE "NEVER")

# Force Slang to be built as a static library to avoid messing around with
# RPATHs and installing a slang dylib alongside CIRCT. The static library
# will embed Slang into ImportVerilog.
# will embed Slang into ImportVerilog and circt-verilog-lsp-server.
set(ORIGINAL_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
set(ORIGINAL_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})

if (MSVC)
set(CMAKE_CXX_FLAGS "/EHsc")
else ()
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})
Expand All @@ -586,26 +584,31 @@ 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
# CIRCTImportVerilog target linking against slang_slang (even with PRIVATE
# linking) without the latter being in an export set. I think we'd want to
# 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)

# 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)
get_target_property(slang_deps slang_slang INTERFACE_LINK_LIBRARIES)
foreach(dep_alias ${slang_deps})
if (TARGET ${dep_alias})
get_target_property(dep_target ${dep_alias} ALIASED_TARGET)
message(STATUS "Installing slang dependency ${dep_target}")
set_property(GLOBAL APPEND PROPERTY CIRCT_EXPORTS ${dep_target})
install(TARGETS ${dep_target} EXPORT CIRCTTargets)

# 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(${dep_target} PROPERTIES PUBLIC_HEADER "")
endif()
endforeach()
set_property(GLOBAL APPEND PROPERTY CIRCT_EXPORTS slang_slang)
install(TARGETS slang_slang EXPORT CIRCTTargets)
else()
find_package(slang 3.0 REQUIRED)
find_package(slang 8.0 REQUIRED)
endif()
endif()

Expand Down
23 changes: 12 additions & 11 deletions cmake/modules/SlangCompilerOptions.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# slang uses exceptions
set(LLVM_REQUIRES_EH ON)
set(LLVM_REQUIRES_RTTI ON)
# The Slang headers contain C++20 code. So anything that interfaces directly
# with Slang must be built accordingly.
set(CMAKE_CXX_STANDARD 20)

# 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
Expand All @@ -9,22 +9,23 @@ set(LLVM_REQUIRES_RTTI ON)
# or modified by code compiled in the Slang compilation unit.
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)

# HACK: When the `OBJECT` argument is passed to `llvm_add_library()`,
# `COMPILE_DEFINITIONS` are not correctly inherited. For that reason, we
# manually set it here.
if(TARGET Boost::headers)
add_compile_definitions(
$<TARGET_PROPERTY:Boost::headers,INTERFACE_COMPILE_DEFINITIONS>)
endif()

# Disable some compiler warnings caused by slang headers such that the
# `ImportVerilog` build doesn't spew out a ton of warnings that are not related
# to CIRCT.
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)
if (NOT MSVC)
# slang has some classes with virtual funcs but non-virtual destructor.
add_compile_options(-Wno-non-virtual-dtor)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW these should all be fixed now.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And by that I mean all of the various warnings being suppressed here should no longer be needed.

Copy link
Contributor

@fabianschuiki fabianschuiki Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was only able to remove -Wno-cast-qual. The others still seem to be needed. Could this be something that only got fixed or Slang 9 (while this PR only bumps to 8 for now)?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, that is possible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I'm going to give v9 a try again once this has landed.

# 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 ()

4 changes: 2 additions & 2 deletions include/circt/Support/FVInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -647,8 +647,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); }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this related to the slang version? Is it picking up some overzealous global operator in slang somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a consequence of building circt code with C++ 20 for the first time, where https://timsong-cpp.github.io/cppwp/n4868/over.match#oper-3.4.4 has come into play. If my analysis is correct, operator resolution of == in { return b == a; } where a: uint64_t and b: const FVInt &b resolved to inline bool operator==(uint64_t a, const FVInt &b) { return b == a; } , i.e. itself, leading to infinite recursion.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, just an artifact of C++20 and not anything slang is doing. Maybe you can just ifdef out these overloads when compiling in C++20 mode.

inline bool operator!=(uint64_t a, const FVInt &b) { return b.operator!=(a); }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any tips on how to best deal with https://timsong-cpp.github.io/cppwp/n4868/over.match#oper-3.4.4 in a codebase that still needs to support older standards?


inline raw_ostream &operator<<(raw_ostream &os, const FVInt &value) {
value.print(os);
Expand Down
39 changes: 22 additions & 17 deletions lib/Conversion/ImportVerilog/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "ImportVerilogInternals.h"
#include "slang/ast/EvalContext.h"
#include "slang/ast/SystemSubroutine.h"
#include "slang/syntax/AllSyntax.h"

Expand Down Expand Up @@ -770,7 +771,7 @@ struct RvalueExprVisitor : public ExprVisitor {
// 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<slang::ast::OpenRangeExpression>()) {
listExpr->as_if<slang::ast::ValueRangeExpression>()) {
// Handle ranges.
auto lowBound = context.convertToSimpleBitVector(
context.convertRvalueExpression(openRange->left()));
Expand Down Expand Up @@ -1076,30 +1077,31 @@ struct RvalueExprVisitor : public ExprVisitor {
value = moore::ConcatOp::create(builder, loc, operands).getResult();
}

if (expr.sliceSize == 0) {
if (expr.getSliceSize() == 0) {
return value;
}

auto type = cast<moore::IntType>(value.getType());
SmallVector<Value> slicedOperands;
auto iterMax = type.getWidth() / expr.sliceSize;
auto remainSize = type.getWidth() % expr.sliceSize;
auto iterMax = type.getWidth() / expr.getSliceSize();
auto remainSize = type.getWidth() % expr.getSliceSize();

for (size_t i = 0; i < iterMax; i++) {
auto extractResultType = moore::IntType::get(
context.getContext(), expr.sliceSize, type.getDomain());
context.getContext(), expr.getSliceSize(), type.getDomain());

auto extracted = moore::ExtractOp::create(builder, loc, extractResultType,
value, i * expr.sliceSize);
value, i * expr.getSliceSize());
slicedOperands.push_back(extracted);
}
// Handle other wire
if (remainSize) {
auto extractResultType = moore::IntType::get(
context.getContext(), remainSize, type.getDomain());

auto extracted = moore::ExtractOp::create(
builder, loc, extractResultType, value, iterMax * expr.sliceSize);
auto extracted =
moore::ExtractOp::create(builder, loc, extractResultType, value,
iterMax * expr.getSliceSize());
slicedOperands.push_back(extracted);
}

Expand Down Expand Up @@ -1195,7 +1197,7 @@ struct LvalueExprVisitor : public ExprVisitor {
value = moore::ConcatRefOp::create(builder, loc, operands).getResult();
}

if (expr.sliceSize == 0) {
if (expr.getSliceSize() == 0) {
return value;
}

Expand All @@ -1204,24 +1206,25 @@ struct LvalueExprVisitor : public ExprVisitor {
SmallVector<Value> slicedOperands;
auto widthSum = type.getWidth();
auto domain = type.getDomain();
auto iterMax = widthSum / expr.sliceSize;
auto remainSize = widthSum % expr.sliceSize;
auto iterMax = widthSum / expr.getSliceSize();
auto remainSize = widthSum % expr.getSliceSize();

for (size_t i = 0; i < iterMax; i++) {
auto extractResultType = moore::RefType::get(
moore::IntType::get(context.getContext(), expr.sliceSize, domain));
auto extractResultType = moore::RefType::get(moore::IntType::get(
context.getContext(), expr.getSliceSize(), domain));

auto extracted = moore::ExtractRefOp::create(
builder, loc, extractResultType, value, i * expr.sliceSize);
builder, loc, extractResultType, value, i * expr.getSliceSize());
slicedOperands.push_back(extracted);
}
// Handle other wire
if (remainSize) {
auto extractResultType = moore::RefType::get(
moore::IntType::get(context.getContext(), remainSize, domain));

auto extracted = moore::ExtractRefOp::create(
builder, loc, extractResultType, value, iterMax * expr.sliceSize);
auto extracted =
moore::ExtractRefOp::create(builder, loc, extractResultType, value,
iterMax * expr.getSliceSize());
slicedOperands.push_back(extracted);
}

Expand Down Expand Up @@ -1308,7 +1311,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);
}

Expand Down
8 changes: 4 additions & 4 deletions lib/Conversion/ImportVerilog/FormatStrings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
//===----------------------------------------------------------------------===//

#include "ImportVerilogInternals.h"
#include "slang/text/SFormat.h"
#include "slang/ast/SFormat.h"

using namespace mlir;
using namespace circt;
using namespace ImportVerilog;
using moore::IntAlign;
using moore::IntFormat;
using moore::IntPadding;
using slang::SFormat::FormatOptions;
using slang::ast::SFormat::FormatOptions;

namespace {
struct FormatStringParser {
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -191,7 +191,7 @@ struct FormatStringParser {
} // namespace

FailureOr<Value> Context::convertFormatString(
slang::span<const slang::ast::Expression *const> arguments, Location loc,
std::span<const slang::ast::Expression *const> arguments, Location loc,
IntFormat defaultFormat, bool appendNewline) {
FormatStringParser parser(*this, ArrayRef(arguments.data(), arguments.size()),
loc, defaultFormat);
Expand Down
Loading