Skip to content

Commit

Permalink
Reflect more complex local parameters (#894)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
Sustrak committed Feb 16, 2024
1 parent e13feb8 commit f904c15
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 11 deletions.
5 changes: 3 additions & 2 deletions tools/reflect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +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)
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)
Expand Down
12 changes: 3 additions & 9 deletions tools/reflect/include/SvLocalParam.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,14 @@
#include "SvType.h"
#include <fmt/format.h>

#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;
Expand Down
79 changes: 79 additions & 0 deletions tools/reflect/src/SvLocalParam.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: Michael Popoloski
// SPDX-License-Identifier: MIT

#include "SvLocalParam.h"

void unwrapUnpackedArray(const std::span<const slang::ConstantValue> constantValues,
std::vector<std::vector<uint64_t>>& 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<uint64_t> 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<std::vector<uint64_t>> unpackedArrays;
uint64_t biggestSize = 0;
SLANG_TRY {
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(
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)));
}
}

0 comments on commit f904c15

Please sign in to comment.