diff --git a/include/verilated.h b/include/verilated.h index 02c022176..2e34adbe9 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -154,7 +154,8 @@ enum VerilatedVarFlags { // Flags VLVF_PUB_RD = (1 << 8), // Public readable VLVF_PUB_RW = (1 << 9), // Public writable - VLVF_DPI_CLAY = (1 << 10) // DPI compatible C standard layout + VLVF_DPI_CLAY = (1 << 10), // DPI compatible C standard layout + VLVF_SIGNED = (1 << 11) // Signed integer }; // IEEE 1800-2023 Table 20-6 diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h index 53600e7a1..bcd0f9d73 100644 --- a/include/verilated_sym_props.h +++ b/include/verilated_sym_props.h @@ -158,6 +158,7 @@ public: bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); } // DPI compatible C standard layout bool isDpiCLayout() const { return ((m_vlflags & VLVF_DPI_CLAY) != 0); } + bool isSigned() const { return ((m_vlflags & VLVF_SIGNED) != 0); } int udims() const VL_MT_SAFE { return m_unpacked.size(); } int pdims() const VL_MT_SAFE { return m_packed.size(); } int dims() const VL_MT_SAFE { return pdims() + udims(); } diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index c8ee28401..3b25180a3 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -2339,6 +2339,11 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) { if (VL_UNLIKELY(!vop)) return vpiUndefined; return vop->size(); } + case vpiSigned: { + const VerilatedVpioVarBase* const vop = VerilatedVpioVarBase::castp(object); + if (VL_UNLIKELY(!vop)) return vpiUndefined; + return vop->varp()->isSigned(); + } default: VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported property %s, nothing will be returned", __func__, VerilatedVpiError::strFromVpiProp(property)); diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 2d67b19d8..6cd4b20d7 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -827,6 +827,7 @@ std::vector EmitCSyms::getSymCtorStmts() { stmt += varp->vlEnumType(); // VLVT_UINT32 etc stmt += ", "; stmt += varp->vlEnumDir(); // VLVD_IN etc + if (varp->dtypep()->skipRefp()->isSigned()) stmt += "|VLVF_SIGNED"; stmt += ", "; stmt += std::to_string(udim); stmt += ", "; diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp index 514551df7..b5a8bccb4 100644 --- a/test_regress/t/t_vpi_var.cpp +++ b/test_regress/t/t_vpi_var.cpp @@ -407,6 +407,41 @@ int _mon_check_var() { CHECK_RESULT_CSTR(p, "vpiParameter"); } + // test properties on bad handle + { + TestVpiHandle vh999 = VPI_HANDLE("nonexistent"); + CHECK_RESULT_Z(vh999); + d = vpi_get(vpiType, vh999); + CHECK_RESULT(d, vpiUndefined); + d = vpi_get(vpiSigned, vh999); + CHECK_RESULT(d, vpiUndefined); + d = vpi_get(vpiSize, vh999); + CHECK_RESULT(d, vpiUndefined); + } + + // other integer types + tmpValue.format = vpiIntVal; + constexpr struct { + const char* name; + PLI_INT32 exp_sz; + } int_vars[] = { + {"integer1", 32}, {"byte1", 8}, {"short1", 16}, {"int1", 32}, {"long1", 64}, + }; + for (const auto& s : int_vars) { + TestVpiHandle vh101 = VPI_HANDLE(s.name); + CHECK_RESULT_NZ(vh101); + d = vpi_get(vpiType, vh101); + CHECK_RESULT(d, vpiReg); + auto sz = vpi_get(vpiSize, vh101); + CHECK_RESULT(sz, s.exp_sz); + auto sn = vpi_get(vpiSigned, vh101); + CHECK_RESULT(sn, 1); + vpi_get_value(vh101, &tmpValue); + TEST_CHECK_EQ(tmpValue.value.integer, 123); + p = vpi_get_str(vpiType, vh101); + CHECK_RESULT_CSTR(p, "vpiReg"); + } + // non-integer variables tmpValue.format = vpiRealVal; { @@ -414,6 +449,8 @@ int _mon_check_var() { CHECK_RESULT_NZ(vh101); d = vpi_get(vpiType, vh101); CHECK_RESULT(d, vpiRealVar); + auto sn = vpi_get(vpiSigned, vh101); + CHECK_RESULT(sn, 1); vpi_get_value(vh101, &tmpValue); TEST_CHECK_REAL_EQ(tmpValue.value.real, 1.0, 0.0005); p = vpi_get_str(vpiType, vh101); @@ -427,6 +464,8 @@ int _mon_check_var() { CHECK_RESULT_NZ(vh101); d = vpi_get(vpiType, vh101); CHECK_RESULT(d, vpiStringVar); + auto sn = vpi_get(vpiSigned, vh101); + CHECK_RESULT(sn, 0); vpi_get_value(vh101, &tmpValue); CHECK_RESULT_CSTR(tmpValue.value.str, "hello"); p = vpi_get_str(vpiType, vh101); diff --git a/test_regress/t/t_vpi_var.v b/test_regress/t/t_vpi_var.v index a651fb413..a94fab60d 100644 --- a/test_regress/t/t_vpi_var.v +++ b/test_regress/t/t_vpi_var.v @@ -53,6 +53,11 @@ extern "C" int mon_check(); integer status; + integer integer1 /*verilator public_flat_rw */; + byte byte1 /*verilator public_flat_rw */; + shortint short1 /*verilator public_flat_rw */; + int int1 /*verilator public_flat_rw */; + longint long1 /*verilator public_flat_rw */; real real1 /*verilator public_flat_rw */; string str1 /*verilator public_flat_rw */; // specifically public and not public_flat_rw here so as to induce the C++ @@ -76,6 +81,11 @@ extern "C" int mon_check(); text = "Verilog Test module"; too_big = "some text"; + integer1 = 123; + byte1 = 123; + short1 = 123; + int1 = 123; + long1 = 123; real1 = 1.0; str1 = "hello"; diff --git a/test_regress/t/t_vpi_var2.v b/test_regress/t/t_vpi_var2.v index d5602e0c2..53329b4cb 100644 --- a/test_regress/t/t_vpi_var2.v +++ b/test_regress/t/t_vpi_var2.v @@ -72,6 +72,11 @@ extern "C" int mon_check(); integer status; /*verilator public_flat_rw_on*/ + integer integer1; + byte byte1; + shortint short1; + int int1; + longint long1; real real1; string str1; localparam int nullptr = 123; @@ -93,6 +98,11 @@ extern "C" int mon_check(); text = "Verilog Test module"; too_big = "some text"; + integer1 = 123; + byte1 = 123; + short1 = 123; + int1 = 123; + long1 = 123; real1 = 1.0; str1 = "hello"; diff --git a/test_regress/t/t_vpi_var3.v b/test_regress/t/t_vpi_var3.v index a2f75b88b..f5565dd48 100644 --- a/test_regress/t/t_vpi_var3.v +++ b/test_regress/t/t_vpi_var3.v @@ -53,6 +53,11 @@ extern "C" int mon_check(); integer status; + integer integer1; + byte byte1; + shortint short1; + int int1; + longint long1; real real1; string str1; localparam int nullptr = 123; @@ -73,6 +78,11 @@ extern "C" int mon_check(); text = "Verilog Test module"; too_big = "some text"; + integer1 = 123; + byte1 = 123; + short1 = 123; + int1 = 123; + long1 = 123; real1 = 1.0; str1 = "hello";