Fix vpi_put_value release on non-continuous signal (#7231) (#7241)

This commit is contained in:
Christian Hecken 2026-03-12 03:57:13 +01:00 committed by GitHub
parent cbf8d97a76
commit b3a1a15e2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 403 additions and 119 deletions

View File

@ -2713,6 +2713,26 @@ bool vl_check_format(const VerilatedVpioVarBase* vop, const p_vpi_value valuep,
return status;
}
// Get a VPI format that can be used to fully represent a signal of the given type
PLI_INT32 vl_get_vltype_format(VerilatedVarType vlType) {
switch (vlType) {
case VLVT_UINT8:
case VLVT_UINT16:
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: return vpiVectorVal;
case VLVT_STRING:
return vpiStringVal; // LCOV_EXCL_LINE - vl_get_vltype_format is only used in
// vpi_put_value for releasing a forceable signal, and string signals
// cannot be forced
case VLVT_REAL: return vpiRealVal;
default: // LCOV_EXCL_START - Cannot test, because vpi_put_value would already exit due to
// failed vl_check_format before calling this
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported vltype (%d)", __func__, vlType);
return vpiUndefined;
} // LCOV_EXCL_STOP
}
static void vl_strprintf(std::string& buffer, char const* fmt, ...) {
va_list args, args_copy;
va_start(args, fmt);
@ -3179,6 +3199,18 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
if (baseSignalVop->varp()->isContinuously())
VerilatedVpiImp::setAllBitsToValue(forceEnableSignalVop, 0);
// For writing back the forced value to a non-continuously assigned base signal in the
// release case, need to get the forced signal's raw data, since valuep could have
// a format that modifies the data (e.g. vpiStringVal which pads with spaces)
const s_vpi_value forcedValue
= baseSignalVop->varp()->isContinuously() ? s_vpi_value{} : [&baseSignalVop]() {
s_vpi_value val{.format
= vl_get_vltype_format(baseSignalVop->varp()->vltype()),
.value{}};
vl_vpi_get_value(baseSignalVop, &val);
return val;
}();
vl_vpi_get_value(baseSignalVop, valuep);
t_vpi_error_info baseValueGetError{};
@ -3202,9 +3234,15 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
VL_VPI_ERROR_RESET_();
} // LCOV_EXCL_STOP
if (!baseSignalVop->varp()->isContinuously())
if (!baseSignalVop->varp()->isContinuously()) {
VerilatedVpiImp::setAllBitsToValue(forceEnableSignalVop, 0);
// If the signal is not continuously assigned, it should keep the forced value
// until the next time it is assigned in the simulation, so the forced value is
// written to the base signal
vpi_put_value(object, const_cast<p_vpi_value>(&forcedValue), nullptr, vpiNoDelay);
}
return nullptr;
}

View File

@ -360,6 +360,32 @@ extern "C" int checkValuesForced(void) {
return 0;
}
extern "C" int checkNonContinuousValuesForced(void) {
// Non-continuously assigned (e.g. clocked) signals retain the forced value after releasing
// until the they are updated again, so check that they are still at the forced value
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
std::any_of(TestSignals.begin(), TestSignals.end(), [](const TestSignal& signal) {
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
checkValue(scopeName, signal.signalName, signal.valueType, signal.forceValue));
return 0;
}));
return 0;
}
extern "C" int checkContinuousValuesReleased(void) {
// Continuously assigned signals return to their original value immediately after releasing
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
std::any_of(TestSignals.begin(), TestSignals.end(), [](const TestSignal& signal) {
const std::string continouslyAssignedSignal
= std::string{signal.signalName} + "Continuously";
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
checkValue(scopeName, continouslyAssignedSignal, signal.valueType,
signal.releaseValue));
return 0;
}));
return 0;
}
extern "C" int checkValuesPartiallyForced(void) {
// Clocked signals
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
@ -383,6 +409,21 @@ extern "C" int checkValuesPartiallyForced(void) {
return 0;
}
extern "C" int checkNonContinuousValuesPartiallyForced(void) {
// Non-continuously assigned (e.g. clocked) signals retain the partially forced value after
// releasing until the they are updated again, so check that they are still at the partially
// forced value
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
std::any_of(TestSignals.begin(), TestSignals.end(), [](const TestSignal& signal) {
if (signal.partialForceValue.second)
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
checkValue(scopeName, signal.signalName, signal.valueType,
signal.partialForceValue.first));
return 0;
}));
return 0;
}
extern "C" int checkValuesReleased(void) {
// Clocked signals
CHECK_RESULT_Z( // NOLINT(concurrency-mt-unsafe)
@ -631,6 +672,28 @@ static int checkValuesForcedVpi() {
return 0;
}
static int checkNonContinuousValuesForcedVpi() {
TestVpiHandle href = vpi_handle(vpiSysTfCall, 0);
s_vpi_value vpi_value;
vpi_value.format = vpiIntVal;
vpi_value.value.integer = checkNonContinuousValuesForced();
vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
return 0;
}
static int checkContinuousValuesReleasedVpi() {
TestVpiHandle href = vpi_handle(vpiSysTfCall, 0);
s_vpi_value vpi_value;
vpi_value.format = vpiIntVal;
vpi_value.value.integer = checkContinuousValuesReleased();
vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
return 0;
}
static int checkValuesPartiallyForcedVpi() {
TestVpiHandle href = vpi_handle(vpiSysTfCall, 0);
s_vpi_value vpi_value;
@ -642,6 +705,17 @@ static int checkValuesPartiallyForcedVpi() {
return 0;
}
static int checkNonContinuousValuesPartiallyForcedVpi() {
TestVpiHandle href = vpi_handle(vpiSysTfCall, 0);
s_vpi_value vpi_value;
vpi_value.format = vpiIntVal;
vpi_value.value.integer = checkNonContinuousValuesPartiallyForced();
vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
return 0;
}
static int checkValuesReleasedVpi() {
TestVpiHandle href = vpi_handle(vpiSysTfCall, 0);
s_vpi_value vpi_value;
@ -686,7 +760,7 @@ static int releasePartiallyForcedValuesVpi() {
return 0;
}
std::array<s_vpi_systf_data, 6> vpi_systf_data
std::array<s_vpi_systf_data, 9> vpi_systf_data
= {s_vpi_systf_data{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$forceValues",
(PLI_INT32(*)(PLI_BYTE8*))forceValuesVpi, 0, 0, 0},
s_vpi_systf_data{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$releaseValues",
@ -695,8 +769,15 @@ std::array<s_vpi_systf_data, 6> vpi_systf_data
(PLI_INT32(*)(PLI_BYTE8*))releasePartiallyForcedValuesVpi, 0, 0, 0},
s_vpi_systf_data{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$checkValuesForced",
(PLI_INT32(*)(PLI_BYTE8*))checkValuesForcedVpi, 0, 0, 0},
s_vpi_systf_data{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$checkNonContinuousValuesForced",
(PLI_INT32(*)(PLI_BYTE8*))checkNonContinuousValuesForcedVpi, 0, 0, 0},
s_vpi_systf_data{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$checkContinuousValuesReleased",
(PLI_INT32(*)(PLI_BYTE8*))checkContinuousValuesReleasedVpi, 0, 0, 0},
s_vpi_systf_data{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$checkValuesPartiallyForced",
(PLI_INT32(*)(PLI_BYTE8*))checkValuesPartiallyForcedVpi, 0, 0, 0},
s_vpi_systf_data{
vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$checkNonContinuousValuesPartiallyForced",
(PLI_INT32(*)(PLI_BYTE8*))checkNonContinuousValuesPartiallyForcedVpi, 0, 0, 0},
s_vpi_systf_data{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$checkValuesReleased",
(PLI_INT32(*)(PLI_BYTE8*))checkValuesReleasedVpi, 0, 0, 0}};

View File

@ -4,6 +4,13 @@
// SPDX-License-Identifier: CC0-1.0
// ======================================================================
// verilog_format: off
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
`define STRINGIFY(x) `"x`"
`ifdef VERILATOR_COMMENTS
@ -18,7 +25,7 @@ module t;
initial begin
clk = 0;
forever #1 clk = ~clk;
forever #2 clk = ~clk;
end
Test test (.clk(clk));
@ -44,6 +51,9 @@ module Test (
extern "C" int checkValuesForced();
extern "C" int checkValuesPartiallyForced();
extern "C" int checkValuesReleased();
extern "C" int checkNonContinuousValuesForced();
extern "C" int checkContinuousValuesReleased();
extern "C" int checkNonContinuousValuesPartiallyForced();
`verilog
`endif
`else
@ -59,6 +69,9 @@ module Test (
import "DPI-C" context function int checkValuesPartiallyForced();
import "DPI-C" context function int checkValuesForced();
import "DPI-C" context function int checkValuesReleased();
import "DPI-C" context function int checkNonContinuousValuesForced();
import "DPI-C" context function int checkContinuousValuesReleased();
import "DPI-C" context function int checkNonContinuousValuesPartiallyForced();
`endif
// Verify that vpi_put_value still works for strings
@ -451,39 +464,39 @@ module Test (
endtask
task automatic svCheckValuesForced();
if(onebit != 0) $stop;
if(intval != 32'h55555555) $stop;
if(vectorC != 8'h55) $stop;
if(vectorQ != 62'h15555555_55555555) $stop;
if(vectorW != 128'h55555555_55555555_55555555_55555555) $stop;
if(real1 != 123456.789) $stop;
if(textHalf != "T2") $stop;
if(textLong != "44Four44") $stop;
if(text != "lorem ipsum") $stop;
if(binString != 8'b01010101) $stop;
if(octString != 15'o52525) $stop;
if(hexString != 64'h5555555555555555) $stop;
if(decStringC != 8'h55) $stop;
if(decStringS != 16'h5555) $stop;
if(decStringI != 32'h55555555) $stop;
if(decStringQ != 64'd6148914691236517205) $stop;
`checkh(onebit, 0);
`checkh(intval, 32'h55555555);
`checkh(vectorC, 8'h55);
`checkh(vectorQ, 62'h15555555_55555555);
`checkh(vectorW, 128'h55555555_55555555_55555555_55555555);
`checkr(real1, 123456.789);
`checks(textHalf, "T2");
`checks(textLong, "44Four44");
`checks(text, "lorem ipsum");
`checkh(binString, 8'b01010101);
`checkh(octString, 15'o52525);
`checkh(hexString, 64'h5555555555555555);
`checkh(decStringC, 8'h55);
`checkh(decStringS, 16'h5555);
`checkh(decStringI, 32'h55555555);
`checkh(decStringQ, 64'd6148914691236517205);
if(onebitContinuously != 0) $stop;
if(intvalContinuously != 32'h55555555) $stop;
if(vectorCContinuously != 8'h55) $stop;
if(vectorQContinuously != 62'h15555555_55555555) $stop;
if(vectorWContinuously != 128'h55555555_55555555_55555555_55555555) $stop;
if(real1Continuously != 123456.789) $stop;
if(textHalfContinuously != "T2") $stop;
if(textLongContinuously != "44Four44") $stop;
if(textContinuously != "lorem ipsum") $stop;
if(binStringContinuously != 8'b01010101) $stop;
if(octStringContinuously != 15'o52525) $stop;
if(hexStringContinuously != 64'h5555555555555555) $stop;
if(decStringCContinuously != 8'h55) $stop;
if(decStringSContinuously != 16'h5555) $stop;
if(decStringIContinuously != 32'h55555555) $stop;
if(decStringQContinuously != 64'd6148914691236517205) $stop;
`checkh(onebitContinuously, 0);
`checkh(intvalContinuously, 32'h55555555);
`checkh(vectorCContinuously, 8'h55);
`checkh(vectorQContinuously, 62'h15555555_55555555);
`checkh(vectorWContinuously, 128'h55555555_55555555_55555555_55555555);
`checkr(real1Continuously, 123456.789);
`checks(textHalfContinuously, "T2");
`checks(textLongContinuously, "44Four44");
`checks(textContinuously, "lorem ipsum");
`checkh(binStringContinuously, 8'b01010101);
`checkh(octStringContinuously, 15'o52525);
`checkh(hexStringContinuously, 64'h5555555555555555);
`checkh(decStringCContinuously, 8'h55);
`checkh(decStringSContinuously, 16'h5555);
`checkh(decStringIContinuously, 32'h55555555);
`checkh(decStringQContinuously, 64'd6148914691236517205);
endtask
task automatic vpiCheckValuesForced();
@ -509,36 +522,121 @@ module Test (
end
endtask
task automatic svCheckValuesPartiallyForced();
if (intval != 32'hAAAA_5555) $stop;
if (vectorC != 8'h A5) $stop;
if (vectorQ != 62'h2AAAAAAAD5555555) $stop;
if (vectorW != 128'hAAAAAAAA_AAAAAAAA_55555555_55555555) $stop;
if (textHalf != "H2") $stop;
if (textLong != "Lonur44") $stop;
if (text != "Verilog Tesem ipsum") $stop;
if (binString != 8'b1010_0101) $stop;
if (octString != 15'b01010101_1010101) $stop;
if (hexString != 64'hAAAAAAAA_55555555) $stop;
if (decStringC != 8'hA5) $stop;
if (decStringS != 16'hAA55) $stop;
if (decStringI != 32'hAAAA_5555) $stop;
if (decStringQ != 64'hAAAAAAAA_55555555) $stop;
task automatic svCheckNonContinuousValuesForced();
`checkh(onebit, 0);
`checkh(intval, 32'h55555555);
`checkh(vectorC, 8'h55);
`checkh(vectorQ, 62'h15555555_55555555);
`checkh(vectorW, 128'h55555555_55555555_55555555_55555555);
`checkr(real1, 123456.789);
`checks(textHalf, "T2");
`checks(textLong, "44Four44");
`checks(text, "lorem ipsum");
`checkh(binString, 8'b01010101);
`checkh(octString, 15'o52525);
`checkh(hexString, 64'h5555555555555555);
`checkh(decStringC, 8'h55);
`checkh(decStringS, 16'h5555);
`checkh(decStringI, 32'h55555555);
`checkh(decStringQ, 64'd6148914691236517205);
endtask
if (intvalContinuously != 32'hAAAA_5555) $stop;
if (vectorCContinuously != 8'h A5) $stop;
if (vectorQContinuously != 62'h2AAAAAAAD5555555) $stop;
if (vectorWContinuously != 128'hAAAAAAAA_AAAAAAAA_55555555_55555555) $stop;
if (textHalfContinuously != "H2") $stop;
if (textLongContinuously != "Lonur44") $stop;
if (textContinuously != "Verilog Tesem ipsum") $stop;
if (binStringContinuously != 8'b1010_0101) $stop;
if (octStringContinuously != 15'b01010101_1010101) $stop;
if (hexStringContinuously != 64'hAAAAAAAA_55555555) $stop;
if (decStringCContinuously != 8'hA5) $stop;
if (decStringSContinuously != 16'hAA55) $stop;
if (decStringIContinuously != 32'hAAAA_5555) $stop;
if (decStringQContinuously != 64'hAAAAAAAA_55555555) $stop;
// Check that the values *after releasing* still have the forced value
task automatic vpiCheckNonContinuousValuesForced();
integer vpiStatus = 1;
`ifdef VERILATOR
`ifdef USE_VPI_NOT_DPI
vpiStatus = $c32("checkNonContinuousValuesForced()");
`else
vpiStatus = checkNonContinuousValuesForced();
`endif
`elsif IVERILOG
vpiStatus = $checkNonContinuousValuesForced;
`elsif USE_VPI_NOT_DPI
vpiStatus = $checkNonContinuousValuesForced;
`else
vpiStatus = checkNonContinuousValuesForced();
`endif
if (vpiStatus != 0) begin
$write("%%Error: t_vpi_force.cpp:%0d:", vpiStatus);
$display("C Test failed (value of non-continuously assigned signal after releasing does not match expectation)");
$stop;
end
endtask
task automatic svCheckContinuousValuesReleased();
`checkh(onebitContinuously, 1);
`checkh(intvalContinuously, 32'hAAAAAAAA);
`checkh(vectorCContinuously, 8'hAA);
`checkh(vectorQContinuously, 62'h2AAAAAAA_AAAAAAAA);
`checkh(vectorWContinuously, 128'hAAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA);
`checkr(real1Continuously, 1.0);
`checks(textHalfContinuously, "Hf");
`checks(textLongContinuously, "Long64b");
`checks(textContinuously, "Verilog Test module");
`checkh(binStringContinuously, 8'b10101010);
`checkh(octStringContinuously, 15'o25252);
`checkh(hexStringContinuously, 64'hAAAAAAAAAAAAAAAA);
`checkh(decStringCContinuously, 8'hAA);
`checkh(decStringSContinuously, 16'hAAAA);
`checkh(decStringIContinuously, 32'hAAAAAAAA);
`checkh(decStringQContinuously, 64'd12297829382473034410);
endtask
task automatic vpiCheckContinuousValuesReleased();
integer vpiStatus = 1;
`ifdef VERILATOR
`ifdef USE_VPI_NOT_DPI
vpiStatus = $c32("checkContinuousValuesReleased()");
`else
vpiStatus = checkContinuousValuesReleased();
`endif
`elsif IVERILOG
vpiStatus = $checkContinuousValuesReleased;
`elsif USE_VPI_NOT_DPI
vpiStatus = $checkContinuousValuesReleased;
`else
vpiStatus = checkContinuousValuesReleased();
`endif
if (vpiStatus != 0) begin
$write("%%Error: t_vpi_force.cpp:%0d:", vpiStatus);
$display("C Test failed (value of continuously assigned signal after releasing does not match expectation)");
$stop;
end
endtask
task automatic svCheckValuesPartiallyForced();
`checkh(intval, 32'hAAAA_5555);
`checkh(vectorC, 8'h A5);
`checkh(vectorQ, 62'h2AAAAAAAD5555555);
`checkh(vectorW, 128'hAAAAAAAA_AAAAAAAA_55555555_55555555);
`checks(textHalf, "H2");
`checks(textLong, "Lonur44");
`checks(text, "Verilog Tesem ipsum");
`checkh(binString, 8'b1010_0101);
`checkh(octString, 15'b01010101_1010101);
`checkh(hexString, 64'hAAAAAAAA_55555555);
`checkh(decStringC, 8'hA5);
`checkh(decStringS, 16'hAA55);
`checkh(decStringI, 32'hAAAA_5555);
`checkh(decStringQ, 64'hAAAAAAAA_55555555);
`checkh(intvalContinuously, 32'hAAAA_5555);
`checkh(vectorCContinuously, 8'h A5);
`checkh(vectorQContinuously, 62'h2AAAAAAAD5555555);
`checkh(vectorWContinuously, 128'hAAAAAAAA_AAAAAAAA_55555555_55555555);
`checks(textHalfContinuously, "H2");
`checks(textLongContinuously, "Lonur44");
`checks(textContinuously, "Verilog Tesem ipsum");
`checkh(binStringContinuously, 8'b1010_0101);
`checkh(octStringContinuously, 15'b01010101_1010101);
`checkh(hexStringContinuously, 64'hAAAAAAAA_55555555);
`checkh(decStringCContinuously, 8'hA5);
`checkh(decStringSContinuously, 16'hAA55);
`checkh(decStringIContinuously, 32'hAAAA_5555);
`checkh(decStringQContinuously, 64'hAAAAAAAA_55555555);
endtask
task automatic vpiCheckValuesPartiallyForced();
@ -564,40 +662,81 @@ module Test (
end
endtask
task automatic svCheckValuesReleased();
if (onebit != 1) $stop;
if (intval != 32'hAAAAAAAA) $stop;
if (vectorC != 8'hAA) $stop;
if (vectorQ != 62'h2AAAAAAA_AAAAAAAA) $stop;
if (vectorW != 128'hAAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA) $stop;
if (real1 != 1.0) $stop;
if (textHalf != "Hf") $stop;
if (textLong != "Long64b") $stop;
if (text != "Verilog Test module") $stop;
if (binString != 8'b10101010) $stop;
if (octString != 15'o25252) $stop;
if (hexString != 64'hAAAAAAAAAAAAAAAA) $stop;
if (decStringC != 8'hAA) $stop;
if (decStringS != 16'hAAAA) $stop;
if (decStringI != 32'hAAAAAAAA) $stop;
if (decStringQ != 64'd12297829382473034410) $stop;
task automatic svCheckNonContinuousValuesPartiallyForced();
`checkh(intval, 32'hAAAA_5555);
`checkh(vectorC, 8'h A5);
`checkh(vectorQ, 62'h2AAAAAAAD5555555);
`checkh(vectorW, 128'hAAAAAAAA_AAAAAAAA_55555555_55555555);
`checks(textHalf, "H2");
`checks(textLong, "Lonur44");
`checks(text, "Verilog Tesem ipsum");
`checkh(binString, 8'b1010_0101);
`checkh(octString, 15'b01010101_1010101);
`checkh(hexString, 64'hAAAAAAAA_55555555);
`checkh(decStringC, 8'hA5);
`checkh(decStringS, 16'hAA55);
`checkh(decStringI, 32'hAAAA_5555);
`checkh(decStringQ, 64'hAAAAAAAA_55555555);
endtask
if (onebitContinuously != 1) $stop;
if (intvalContinuously != 32'hAAAAAAAA) $stop;
if (vectorCContinuously != 8'hAA) $stop;
if (vectorQContinuously != 62'h2AAAAAAA_AAAAAAAA) $stop;
if (vectorWContinuously != 128'hAAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA) $stop;
if (real1Continuously != 1.0) $stop;
if (textHalfContinuously != "Hf") $stop;
if (textLongContinuously != "Long64b") $stop;
if (textContinuously != "Verilog Test module") $stop;
if (binStringContinuously != 8'b10101010) $stop;
if (octStringContinuously != 15'o25252) $stop;
if (hexStringContinuously != 64'hAAAAAAAAAAAAAAAA) $stop;
if (decStringCContinuously != 8'hAA) $stop;
if (decStringSContinuously != 16'hAAAA) $stop;
if (decStringIContinuously != 32'hAAAAAAAA) $stop;
if (decStringQContinuously != 64'd12297829382473034410) $stop;
// Check that the values *after releasing* still have the partially forced value
task automatic vpiCheckNonContinuousValuesPartiallyForced();
integer vpiStatus = 1;
`ifdef VERILATOR
`ifdef USE_VPI_NOT_DPI
vpiStatus = $c32("checkNonContinuousValuesPartiallyForced()");
`else
vpiStatus = checkNonContinuousValuesPartiallyForced();
`endif
`elsif IVERILOG
vpiStatus = $checkNonContinuousValuesPartiallyForced;
`elsif USE_VPI_NOT_DPI
vpiStatus = $checkNonContinuousValuesPartiallyForced;
`else
vpiStatus = checkNonContinuousValuesPartiallyForced();
`endif
if (vpiStatus != 0) begin
$write("%%Error: t_vpi_force.cpp:%0d:", vpiStatus);
$display("C Test failed (value of non-continuously assigned signal after releasing from partial force does not match expectation)");
$stop;
end
endtask
task automatic svCheckValuesReleased();
`checkh(onebit, 1);
`checkh(intval, 32'hAAAAAAAA);
`checkh(vectorC, 8'hAA);
`checkh(vectorQ, 62'h2AAAAAAA_AAAAAAAA);
`checkh(vectorW, 128'hAAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA);
`checkr(real1, 1.0);
`checks(textHalf, "Hf");
`checks(textLong, "Long64b");
`checks(text, "Verilog Test module");
`checkh(binString, 8'b10101010);
`checkh(octString, 15'o25252);
`checkh(hexString, 64'hAAAAAAAAAAAAAAAA);
`checkh(decStringC, 8'hAA);
`checkh(decStringS, 16'hAAAA);
`checkh(decStringI, 32'hAAAAAAAA);
`checkh(decStringQ, 64'd12297829382473034410);
`checkh(onebitContinuously, 1);
`checkh(intvalContinuously, 32'hAAAAAAAA);
`checkh(vectorCContinuously, 8'hAA);
`checkh(vectorQContinuously, 62'h2AAAAAAA_AAAAAAAA);
`checkh(vectorWContinuously, 128'hAAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA);
`checkr(real1Continuously, 1.0);
`checks(textHalfContinuously, "Hf");
`checks(textLongContinuously, "Long64b");
`checks(textContinuously, "Verilog Test module");
`checkh(binStringContinuously, 8'b10101010);
`checkh(octStringContinuously, 15'o25252);
`checkh(hexStringContinuously, 64'hAAAAAAAAAAAAAAAA);
`checkh(decStringCContinuously, 8'hAA);
`checkh(decStringSContinuously, 16'hAAAA);
`checkh(decStringIContinuously, 32'hAAAAAAAA);
`checkh(decStringQContinuously, 64'd12297829382473034410);
endtask
task automatic vpiCheckValuesReleased();
@ -636,54 +775,80 @@ $dumpfile(`STRINGIFY(`TEST_DUMPFILE));
#1 vpiCheckInertialDelay();
// Force and check non-public, but forceable signal
force nonPublic = 0;
#4 if(nonPublic != 0) $stop;
#8 `checkh(nonPublic, 0);
release nonPublic;
#4 if (nonPublic != 1) $stop;
#8 `checkh(nonPublic, 1);
`endif
// Force through VPI, release through VPI
vpiForceValues();
// Time delay to ensure setting and checking values does not happen
// at the same time, so that the signals can have their values overwritten
// by other processes
#4 vpiCheckValuesForced();
#8 vpiCheckValuesForced();
svCheckValuesForced();
#4 vpiReleaseValues();
#4 vpiCheckValuesReleased();
// Wait until negedge, then release
@(negedge clk) vpiReleaseValues();
// After release, but before posedge: Non-continuously assigned signals
// should still have their forced value, because the posedge re-assigning
// the non-continuously assigned signals has not happened yet, but
// continuously assigned signals should have their non-forced value again
#1 vpiCheckNonContinuousValuesForced();
vpiCheckContinuousValuesReleased();
svCheckNonContinuousValuesForced();
svCheckContinuousValuesReleased();
#8; // All signals should be released by now
vpiCheckValuesReleased();
svCheckValuesReleased();
// Force through VPI, release through Verilog
#4 vpiForceValues();
#4 vpiCheckValuesForced();
#8 vpiForceValues();
#8 vpiCheckValuesForced();
svCheckValuesForced();
#4 svReleaseValues();
#4 vpiCheckValuesReleased();
@(negedge clk) svReleaseValues();
#1 vpiCheckNonContinuousValuesForced();
vpiCheckContinuousValuesReleased();
svCheckNonContinuousValuesForced();
svCheckContinuousValuesReleased();
#8 vpiCheckValuesReleased();
svCheckValuesReleased();
// Force through Verilog, release through VPI
#4 svForceValues();
#4 vpiCheckValuesForced();
#8 svForceValues();
#8 vpiCheckValuesForced();
svCheckValuesForced();
#4 vpiReleaseValues();
#4 vpiCheckValuesReleased();
@(negedge clk) vpiReleaseValues();
#1 vpiCheckNonContinuousValuesForced();
vpiCheckContinuousValuesReleased();
svCheckNonContinuousValuesForced();
svCheckContinuousValuesReleased();
#8 vpiCheckValuesReleased();
svCheckValuesReleased();
// Force only some bits, check if __VforceRd yields correct signal,
// release through VPI
#4 svPartiallyForceValues();
#4 vpiCheckValuesPartiallyForced();
#8 svPartiallyForceValues();
#8 vpiCheckValuesPartiallyForced();
svCheckValuesPartiallyForced();
#4 vpiReleasePartiallyForcedValues();
#4 vpiCheckValuesReleased();
@(negedge clk) vpiReleasePartiallyForcedValues();
#1 vpiCheckNonContinuousValuesPartiallyForced();
vpiCheckContinuousValuesReleased();
svCheckNonContinuousValuesPartiallyForced();
svCheckContinuousValuesReleased();
#8 vpiCheckValuesReleased();
svCheckValuesReleased();
// Force only some bits, check if __VforceRd yields correct signal,
// release through Verilog
#4 svPartiallyForceValues();
#4 vpiCheckValuesPartiallyForced();
#8 svPartiallyForceValues();
#8 vpiCheckValuesPartiallyForced();
svCheckValuesPartiallyForced();
#4 svReleaseValues();
#4 vpiCheckValuesReleased();
@(negedge clk) svReleaseValues();
#1 vpiCheckNonContinuousValuesPartiallyForced();
vpiCheckContinuousValuesReleased();
svCheckNonContinuousValuesPartiallyForced();
svCheckContinuousValuesReleased();
#8 vpiCheckValuesReleased();
svCheckValuesReleased();