From 79c2488a0c66486242e1920ffc9e985371b6b7a5 Mon Sep 17 00:00:00 2001 From: Muzaffer Kal Date: Tue, 28 Jul 2026 17:20:19 -0700 Subject: [PATCH] Preserve shortreal hierarchy width Keep 32-bit hierarchy metadata while using eight-byte real storage for promoted shortreal values. --- fstcpp/fstcpp_writer.cpp | 10 ++++++-- fstcpp/fstcpp_writer_easy_blocks.test.cpp | 29 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/fstcpp/fstcpp_writer.cpp b/fstcpp/fstcpp_writer.cpp index 386a761..129fe7a 100644 --- a/fstcpp/fstcpp_writer.cpp +++ b/fstcpp/fstcpp_writer.cpp @@ -126,16 +126,22 @@ Handle Writer::createVar( // determine real/string handling like original C implementation bool is_real{false}; + uint32_t stored_bitwidth{bitwidth}; switch (vartype) { case Hierarchy::VarType::VCD_REAL: case Hierarchy::VarType::VCD_REAL_PARAMETER: case Hierarchy::VarType::VCD_REALTIME: - case Hierarchy::VarType::SV_SHORTREAL: is_real = true; bitwidth = 8; // recast to double size + stored_bitwidth = bitwidth; + break; + case Hierarchy::VarType::SV_SHORTREAL: + is_real = true; + stored_bitwidth = 8; break; case Hierarchy::VarType::GEN_STRING: bitwidth = 0; + stored_bitwidth = bitwidth; break; default: break; @@ -166,7 +172,7 @@ Handle Writer::createVar( // I don't know why the original C implementation encode bitwidth again const uint32_t geom_len{(bitwidth == 0 ? uint32_t(-1) : is_real ? uint32_t(0) : bitwidth)}; g.writeLEB128(geom_len); - m_value_change_data_.m_variable_infos.emplace_back(bitwidth, is_real); + m_value_change_data_.m_variable_infos.emplace_back(stored_bitwidth, is_real); } return alias_handle; diff --git a/fstcpp/fstcpp_writer_easy_blocks.test.cpp b/fstcpp/fstcpp_writer_easy_blocks.test.cpp index ecae757..d95b116 100644 --- a/fstcpp/fstcpp_writer_easy_blocks.test.cpp +++ b/fstcpp/fstcpp_writer_easy_blocks.test.cpp @@ -44,6 +44,10 @@ class WriterTest : public ::testing::Test { ); } + static const VariableInfo &getVariableInfo(Writer &writer, Handle handle) { + return writer.m_value_change_data_.m_variable_infos.at(handle - 1); + } + static void writeHeader(const Header &h, ostream &os) { Writer::writeHeader_(h, os); } static void appendBlackout(Writer &Writer, std::ostream &os) { Writer.appendBlackout_(os); } @@ -278,6 +282,31 @@ TEST_F(WriterTest, createVarVcdReal) { EXPECT_EQ(buf, expected); } +TEST_F(WriterTest, createVarSvShortreal) { + Writer writer; + writer.setWriterPackType(WriterPackType::NO_COMPRESSION); + const Handle handle{writer.createVar( + fst::Hierarchy::VarType::SV_SHORTREAL, + fst::Hierarchy::VarDirection::INPUT, + /*bitwidth =*/32, + "shortreal_val", + /*alias handle =*/0 + )}; + EXPECT_EQ(handle, 1u); + + // Preserve the 32-bit shortreal width in the hierarchy. + const string hierarchy_buf{getHierarchyBuffer(writer)}; + const string hierarchy_expected{"\x1d\x01shortreal_val\x00\x20\x00"s}; + EXPECT_EQ(hierarchy_buf, hierarchy_expected); + + // FST stores real values as doubles, including shortreal values promoted to double. + const string geometry_buf{getGeometryBuffer(writer)}; + EXPECT_EQ(geometry_buf, "\x00"s); + const VariableInfo &variable_info{getVariableInfo(writer, handle)}; + EXPECT_TRUE(variable_info.is_real()); + EXPECT_EQ(variable_info.bitwidth(), 8u); +} + TEST_F(WriterTest, GeometryBufferNormalVar) { Writer writer; writer.setWriterPackType(WriterPackType::NO_COMPRESSION);