From bb893def08fdf18f56f78173bde8f4c473de0be5 Mon Sep 17 00:00:00 2001 From: Josep Sans i Prats Date: Wed, 14 Feb 2024 20:49:46 +0100 Subject: [PATCH 1/3] Fixes #825 With this commit slang-reflect is able to reflect more complex local parameters. Also, it will throw an error if it doesn't know how to reflect the parameter instead of crashing. --- tools/reflect/CMakeLists.txt | 3 +- tools/reflect/include/SvLocalParam.h | 12 ++--- tools/reflect/src/SvLocalParam.cpp | 77 ++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 tools/reflect/src/SvLocalParam.cpp diff --git a/tools/reflect/CMakeLists.txt b/tools/reflect/CMakeLists.txt index ad27122d0..47601e07e 100644 --- a/tools/reflect/CMakeLists.txt +++ b/tools/reflect/CMakeLists.txt @@ -4,7 +4,8 @@ # ~~~ add_library(slang_reflect_obj_lib OBJECT src/SvStruct.cpp src/SvType.cpp - src/SvEnum.cpp src/SvTypeReflector.cpp) + src/SvEnum.cpp src/SvTypeReflector.cpp + src/SvLocalParam.cpp) target_include_directories(slang_reflect_obj_lib PUBLIC include ../../include) target_link_libraries(slang_reflect_obj_lib PUBLIC slang::slang) diff --git a/tools/reflect/include/SvLocalParam.h b/tools/reflect/include/SvLocalParam.h index db5dab278..6289b2434 100644 --- a/tools/reflect/include/SvLocalParam.h +++ b/tools/reflect/include/SvLocalParam.h @@ -12,20 +12,14 @@ #include "SvType.h" #include +#include "slang/ast/symbols/ParameterSymbols.h" + class SvLocalParam : public SvGeneric { public: explicit SvLocalParam(const slang::ast::ParameterSymbol& parameter) : SvGeneric(SvGeneric::Kind::LocalParam), parameter(parameter) {} - void toCpp(HppFile& hppFile, std::string_view, const SvAliases&, bool) const override { - std::string parameterName = isCppReserved(parameter.name) - ? fmt::format("_{}", parameter.name) - : std::string(parameter.name); - hppFile.addWithIndent( - fmt::format("static constexpr {} {} = {};\n", - toString(CppType::fromSize(parameter.getType().getBitstreamWidth())), - parameterName, *parameter.getValue().integer().getRawPtr())); - } + void toCpp(HppFile& hppFile, std::string_view, const SvAliases&, bool) const override; private: const slang::ast::ParameterSymbol& parameter; diff --git a/tools/reflect/src/SvLocalParam.cpp b/tools/reflect/src/SvLocalParam.cpp new file mode 100644 index 000000000..a55f34633 --- /dev/null +++ b/tools/reflect/src/SvLocalParam.cpp @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: Michael Popoloski +// SPDX-License-Identifier: MIT + +#include "SvLocalParam.h" + +void unwrapUnpackedArray(const std::span constantValues, + std::vector>& values, uint64_t& biggestElementSize) { + if (constantValues.front().isUnpacked()) + for (const auto& unpackedArray : constantValues) + unwrapUnpackedArray(unpackedArray.elements(), values, biggestElementSize); + else if (constantValues.front().isInteger()) { + std::vector collectedValues; + for (const auto& value : constantValues) { + if (!value.isInteger()) + SLANG_THROW(std::runtime_error( + "Found a non integer member while reflecting this parameter")); + if (value.getBitstreamWidth() > 64) + SLANG_THROW(std::runtime_error( + "Found a value bigger than 64 bits while reflecting this parameter")); + biggestElementSize = std::max(biggestElementSize, value.getBitstreamWidth()); + collectedValues.emplace_back(*value.integer().getRawPtr()); + } + values.emplace_back(collectedValues); + } +} + +void SvLocalParam::toCpp(HppFile& hppFile, std::string_view, const SvAliases&, bool) const { + std::string parameterName = isCppReserved(parameter.name) ? fmt::format("_{}", parameter.name) + : std::string(parameter.name); + if (parameter.getValue().isUnpacked()) { + std::vector> unpackedArrays; + uint64_t biggestSize = 0; + SLANG_TRY { + unwrapUnpackedArray(parameter.getValue().elements(), unpackedArrays, biggestSize); + } + SLANG_CATCH(const std::runtime_error& error) { + SLANG_THROW(std::runtime_error(fmt::format( + "There has been an error while reflecting {}: {}", parameterName, error.what()))); + } + if (unpackedArrays.empty()) + SLANG_THROW(std::runtime_error( + fmt::format("{} has no values, can not reflect.", parameterName))); + hppFile.addInclude("array"); + auto arraySize = unpackedArrays.front().size(); + auto arrayElementType = toString(CppType::fromSize(biggestSize)); + std::string arrayType = fmt::format("std::array<{}, {}>", arrayElementType, arraySize); + for (auto i = 1; i < unpackedArrays.size(); i++) + arrayType = fmt::format("std::array<{}, {}", arrayType, arraySize); + for (auto i = 1; i < unpackedArrays.size(); i++) + arrayType += ">"; + hppFile.addWithIndent( + fmt::format("static constexpr {} {} = {{{{\n", arrayType, parameterName)); + hppFile.increaseIndent(); + for (const auto& unpacked : unpackedArrays) { + hppFile.addWithIndent("{{"); + for (auto i = 0; i < unpacked.size(); i++) { + if (i == 0) + hppFile.add(fmt::format(" {:#x}", unpacked[i])); + else + hppFile.add(fmt::format(", {:#x}", unpacked[i])); + } + hppFile.add(" }},\n"); + } + hppFile.decreaseIndent(); + hppFile.addWithIndent("}};\n"); + } + else if (parameter.getValue().isInteger()) { + hppFile.addWithIndent( + fmt::format("static constexpr {} {} = {};\n", + toString(CppType::fromSize(parameter.getType().getBitstreamWidth())), + parameterName, *parameter.getValue().integer().getRawPtr())); + } + else { + SLANG_THROW( + std::runtime_error(fmt::format("Can't reflect this localparam {}", parameterName))); + } +} From d4f589980c4d8251b111c6dea7d165f227712c59 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 19:52:49 +0000 Subject: [PATCH 2/3] style: pre-commit fixes --- tools/reflect/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/reflect/CMakeLists.txt b/tools/reflect/CMakeLists.txt index 47601e07e..3c743dab8 100644 --- a/tools/reflect/CMakeLists.txt +++ b/tools/reflect/CMakeLists.txt @@ -3,9 +3,9 @@ # SPDX-License-Identifier: MIT # ~~~ -add_library(slang_reflect_obj_lib OBJECT src/SvStruct.cpp src/SvType.cpp - src/SvEnum.cpp src/SvTypeReflector.cpp - src/SvLocalParam.cpp) +add_library( + slang_reflect_obj_lib OBJECT src/SvStruct.cpp src/SvType.cpp src/SvEnum.cpp + src/SvTypeReflector.cpp src/SvLocalParam.cpp) target_include_directories(slang_reflect_obj_lib PUBLIC include ../../include) target_link_libraries(slang_reflect_obj_lib PUBLIC slang::slang) From 59f0207175832ed3ec2ccb31af1229ebbe9543d4 Mon Sep 17 00:00:00 2001 From: Josep Sans i Prats Date: Fri, 16 Feb 2024 09:40:33 +0100 Subject: [PATCH 3/3] [slang-reflect] Fix exception throw when exceptions are disabled --- tools/reflect/src/SvLocalParam.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/reflect/src/SvLocalParam.cpp b/tools/reflect/src/SvLocalParam.cpp index a55f34633..f3306ae98 100644 --- a/tools/reflect/src/SvLocalParam.cpp +++ b/tools/reflect/src/SvLocalParam.cpp @@ -34,8 +34,10 @@ void SvLocalParam::toCpp(HppFile& hppFile, std::string_view, const SvAliases&, b unwrapUnpackedArray(parameter.getValue().elements(), unpackedArrays, biggestSize); } SLANG_CATCH(const std::runtime_error& error) { +#if __cpp_exceptions SLANG_THROW(std::runtime_error(fmt::format( "There has been an error while reflecting {}: {}", parameterName, error.what()))); +#endif } if (unpackedArrays.empty()) SLANG_THROW(std::runtime_error(