Fix uvm_hdl_release_and_read not reading release value or checking for success (#7425)

This commit is contained in:
Christian Hecken 2026-04-19 14:24:07 +02:00 committed by GitHub
parent 29a93fe5bc
commit f7a349c5a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 664 additions and 292 deletions

View File

@ -3402,7 +3402,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
vpi_put_value(object, const_cast<p_vpi_value>(&forcedValue), nullptr, vpiNoDelay);
}
return nullptr;
return object;
}
if (valuep->format == vpiVectorVal) {

View File

@ -40,9 +40,14 @@ module t;
chandle h;
// To cover testing cases, this has non-zero LSB/LO
logic [31+8:8] exposed /*verilator public*/;
logic [31+8:8] exposed /*verilator public*/ /*verilator forceable*/;
logic not_exposed;
logic exposed_not_forceable;
logic exposed_not_forceable /*verilator public*/;
logic [31+8:8] exposedContinuously /*verilator public*/ /*verilator forceable*/;
assign exposedContinuously = 32'h0;
real realSignal /*verilator public*/ /*verilator forceable*/;
string stringSignal /*verilator public*/;
logic [83:4] wide_dec /* verilator public*/;
// verilator lint_off ASCRANGE
@ -52,8 +57,15 @@ module t;
logic [31:0] mem1d[1:2] /* verilator public*/;
logic [31:0] mem2d[1:2][3:4] /* verilator public*/;
logic [2047:0] tooWide /* verilator public*/ /* verilator forceable*/ = 2048'h0;
uvm_hdl_data_t lval;
task releaseExposedContinuously(input logic [31:0] din, output int i);
// verilator no_inline_task
i = uvm_hdl_release("t.exposedContinuously");
endtask
initial begin
// TODO TEST:
// extern const char* uvm_dpi_get_next_arg_c(int init);
@ -221,6 +233,56 @@ module t;
`checkh(mem2d[2][3], 32'h2300);
end
begin : t_read_bad
$display("= uvm_hdl_read bad ranges");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("t.exposed[10:3]", lval);
`checkh(i, 0);
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("t.exposed[99:15]", lval);
`checkh(i, 0);
$display("= uvm_hdl_read empty name (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("", lval);
`checkh(i, 0);
$display("= uvm_hdl_read not found (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("t.__READ_NOT_FOUND", lval);
`checkh(i, 0);
$display("= uvm_hdl_read with indexed part-select (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("t.exposed[15+8:8]", lval);
`checkh(i, 0);
$display("= uvm_hdl_read from real (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("t.realSignal", lval);
`checkh(i, 0);
$display("= uvm_hdl_read from string (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("t.stringSignal", lval);
`checkh(i, 0);
$display("= uvm_hdl_read producing error message larger than print buffer (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read(
"t.lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_duis_autem_vel_eum_iriure_dolor_in_hendrerit_in_vulputate_velit_esse_molestie_consequat_vel_illum_dolore_eu_feugiat_nulla_facilisis_at_vero",
lval
);
`checkh(i, 0);
`ifdef VERILATOR
$display("= uvm_hdl_read from not exposed (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_read("t.not_exposed", lval);
`checkh(i, 0);
`endif
end
begin : t_deposit_bad
$display("= uvm_hdl_deposit bad ranges");
$display("===\nUVM Report expected on next line:");
@ -230,11 +292,40 @@ module t;
i = uvm_hdl_deposit("t.exposed[99:15]", lval);
`checkh(i, 0);
$display("= uvm_hdl_deposit empty name (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_deposit("", lval);
`checkh(i, 0);
$display("= uvm_hdl_deposit not found (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_deposit("t.__DEPOSIT_NOT_FOUND", 12);
`checkh(i, 0);
$display("= uvm_hdl_deposit with indexed part-select (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_deposit("t.exposed[15+8:8]", 0);
`checkh(i, 0);
$display("= uvm_hdl_deposit to real (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_deposit("t.realSignal", 0);
`checkh(i, 0);
$display("= uvm_hdl_deposit to string (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_deposit("t.stringSignal", 0);
`checkh(i, 0);
// lval is only 1024 bits, so if vpi_put_value is called on a 2048-bit
// signal, it would read out of bounds of lval if unchecked
$display("= Test uvm_hdl_deposit to signal wider than UVM_HDL_MAX_WIDTH (bad)");
$display("===\nUVM Report expected on next line:");
lval = 1024'hAAAA;
i = uvm_hdl_deposit("t.tooWide", lval);
`checkh(i, 0);
`checkh(tooWide, 2048'h0);
`ifdef VERILATOR
$display("= uvm_hdl_deposit to not exposed (bad)");
$display("===\nUVM Report expected on next line:");
@ -248,31 +339,192 @@ module t;
i = uvm_hdl_read("t.exposed", lval);
`checkh(i, 1);
`checkh(lval[31:0], exposed);
// UNSUPPORTED: force/release via VPI
// If support, validate or throw unsupported on force/release part-selects
$display("= uvm_hdl_force");
i = uvm_hdl_force("t.exposed", 62);
`checkh(i, 1);
exposed = 32'h0; // should have no effect, since signal is being forced
`checkh(exposed, 32'd62);
$display("= uvm_hdl_release");
i = uvm_hdl_release("t.exposed");
`checkh(i, 1);
// exposed is not assigned continuously, so return value is force value
`checkh(exposed, 32'd62);
exposed = 32'hFFFF_FFFF;
`checkh(exposed, 32'hFFFF_FFFF);
$display("= uvm_hdl_release_and_read");
exposed = 32'hFFFF_FFFF;
force exposed[31+8:8] = 32'h0;
lval = 1024'hFFFF_FFFF;
i = uvm_hdl_release_and_read("t.exposed", lval);
`checkh(i, 1);
// exposed is not assigned continuously, so return value is force value
`checkh(lval[31:0], 32'h0);
`checkh(exposed, 32'h0);
end
begin : t_force_expose_bad
begin : t_force_release_continuous
$display("= uvm_hdl_force continuously assigned signal");
i = uvm_hdl_force("t.exposedContinuously", 62);
`checkh(i, 1);
`checkh(exposedContinuously, 32'd62);
force exposedContinuously = 32'hFFFF_FFFF;
$display("= uvm_hdl_release continuously assigned signal");
releaseExposedContinuously(
exposedContinuously,
i); // Need to wrap VPI call in task for Verilation to actually check the release value
`checkh(i, 1);
`checkh(exposedContinuously, 32'h0);
$display("= uvm_hdl_release_and_read continuously assigned signal");
force exposedContinuously[31+8:8] = 32'hFFFF_FFFF;
lval = 1024'hFFFF_FFFF;
i = uvm_hdl_release_and_read("t.exposedContinuously", lval);
`checkh(i, 1);
`checkh(lval[31:0], 32'h0);
`checkh(t.exposedContinuously, 32'h0);
end
begin : t_force_partial
// Partial force from SystemVerilog
$display("= uvm_hdl_read partially forced signal");
force exposed[15+8:8] = 16'h0;
exposed = 32'hFFFF_FFFF; // Expect 16 LSBs to stay at 0
`checkh(exposed, 32'hFFFF_0000);
lval = 1024'hAAAA_AAAA;
i = uvm_hdl_read("t.exposed", lval);
`checkh(i, 1);
`checkh(lval[31:0], exposed);
$display("= uvm_hdl_release partially forced signal");
i = uvm_hdl_release("t.exposed");
`checkh(i, 1);
`checkh(exposed, 32'hFFFF_0000);
exposed = 32'hFFFF_FFFF;
`checkh(exposed, 32'hFFFF_FFFF);
// Partial force through UVM
$display("= uvm_hdl_force multi-bit");
i = uvm_hdl_force("t.exposed[23:8]", 0); // [15+8:8] is not valid syntax in Verilator
`checkh(i, 1);
exposed = 32'hFFFF_FFFF; // Expect 16 LSBs to stay at 0
`checkh(exposed, 32'hFFFF_0000);
$display("= uvm_hdl_release_and_read partially forced signal");
lval = 1024'h0;
i = uvm_hdl_release_and_read("t.exposed", lval);
`checkh(i, 1);
// exposed is not assigned continuously, so return value is force value
`checkh(lval[31:0], 32'hFFFF_0000);
`checkh(exposed, 32'hFFFF_0000);
exposed = 32'hFFFF_FFFF;
`checkh(exposed, 32'hFFFF_FFFF);
end
begin : t_force_partial_continuous
$display("= uvm_hdl_force multi-bit continuously assigned signal");
i = uvm_hdl_force("t.exposedContinuously[23:8]", 'hFFFF);
`checkh(i, 1);
`checkh(exposedContinuously, 32'h0000_FFFF);
$display("= uvm_hdl_release partially forced continuously assigned signal");
i = uvm_hdl_release("t.exposedContinuously");
`checkh(i, 1);
`checkh(exposedContinuously, 32'h0000_0000);
$display("= uvm_hdl_release_and_read partially forced continuously assigned signal");
force exposedContinuously[23:8] = 16'hFFFF;
lval = 1024'h0;
i = uvm_hdl_release_and_read("t.exposedContinuously", lval);
`checkh(i, 1);
`checkh(lval[31:0], 32'h0000_0000);
`checkh(exposedContinuously, 32'h0000_0000);
end
begin : t_force_single_bit
$display("= uvm_hdl_force single bit");
exposed = 32'hAAAA_AAAA;
i = uvm_hdl_force("t.exposed[16]", 1);
`checkh(i, 1);
exposed = 32'h0; // should have no effect on bit 16
`checkh(exposed, 32'h0000_0100);
$display("= uvm_hdl_release_and_read single bit");
lval = 1024'h0;
i = uvm_hdl_release_and_read("t.exposed[16]", lval);
`checkh(i, 1);
`checkh(lval[31:0], 32'h0000_0001);
exposed = 32'hFFFF_FFFF;
`checkh(exposed, 32'hFFFF_FFFF);
$display("= uvm_hdl_force single bit on continuously assigned signal");
i = uvm_hdl_force("t.exposedContinuously[16]", 1);
`checkh(i, 1);
`checkh(exposedContinuously, 32'h0000_0100);
$display("= uvm_hdl_release_and_read single bit on continuously assigned signal");
lval = 1024'h0;
i = uvm_hdl_release_and_read("t.exposedContinuously[16]", lval);
`checkh(i, 1);
`checkh(lval[31:0], 32'h0000_0000);
`checkh(exposedContinuously, 32'h0);
end
begin : t_partial_release
$display("= uvm_hdl_release_and_read lower 16 bits only");
force exposed = 32'h5555_5555;
lval = 1024'h0;
i = uvm_hdl_release_and_read("t.exposed[23:8]", lval);
`checkh(i, 1);
`checkh(lval[31:0], 32'h0000_5555);
exposed = 32'hFFFF_FFFF;
`checkh(exposed, 32'h5555_FFFF);
release exposed;
$display("= uvm_hdl_release upper 16 bits only of continuously assigned signal");
force exposedContinuously = 32'h5555_5555;
lval = 1024'h0;
i = uvm_hdl_release_and_read("t.exposedContinuously[39:24]", lval);
`checkh(i, 1);
`checkh(lval[31:0], 32'h0000_0000);
`checkh(exposedContinuously, 32'h0000_5555);
release exposedContinuously;
end
begin : t_force_bad
$display("= uvm_hdl_force to not exposed (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_force("t.not_exposed", 12);
`checkh(i, 0);
exposed = 32'hFFFF_FFFF;
$display("= uvm_hdl_force with indexed part-select (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_force("t.exposed[15+8:8]", 0);
`checkh(i, 0);
`checkh(exposed, 32'hFFFF_FFFF);
$display("= uvm_hdl_force to not forcable (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_force("t.exposed_not_forceable", 12);
`checkh(i, 0);
$display("= uvm_hdl_force to real (bad)");
$display("===\nUVM Report expected on next line:");
i = uvm_hdl_force("t.realSignal", 0);
`checkh(i, 0);
$display("= uvm_hdl_force to signal wider than UVM_HDL_MAX_WIDTH (bad)");
$display("===\nUVM Report expected on next line:");
lval = 1024'hAAAA;
i = uvm_hdl_force("t.tooWide", lval);
`checkh(i, 0);
`checkh(tooWide, 2048'h0);
end
$write("*-* All Finished *-*\n");

View File

@ -1,4 +1,4 @@
UVM Report t/t_uvm_dpi.v:62: id message
UVM Report t/t_uvm_dpi.v:74: id message
uvm_dpi_get_tool_name_c() = Verilator
= uvm_re
= uvm_hdl_check_path
@ -12,36 +12,126 @@ uvm_dpi_get_tool_name_c() = Verilator
= uvm_hdl_read/deposit wide ascending
= uvm_hdl_read/deposit 1D memory
= uvm_hdl_read/deposit 2D memory
= uvm_hdl_read bad ranges
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.exposed[10:3])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.exposed[99:15])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read empty name (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET NULL or empty HDL path passed to uvm_hdl_get_vlog
= uvm_hdl_read not found (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.__READ_NOT_FOUND)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read with indexed part-select (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.exposed[15+8:8])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read from real (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET failed to get value for hdl path 't.realSignal'. Common reasons include a signal having an unsupported type, such as a real or a string
= uvm_hdl_read from string (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET failed to get value for hdl path 't.stringSignal'. Common reasons include a signal having an unsupported type, such as a real or a string
= uvm_hdl_read producing error message larger than print buffer (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_duis_autem_vel_eum_iriure_dolor_in_hendrerit_in_vulputate_velit_esse_molestie_consequat_vel_illum_dolore_eu_feugiat_nulla_facilisis_at_vero)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read from not exposed (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.not_exposed)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit bad ranges
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.exposed[10:3])
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[10:3])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.exposed[99:15])
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[99:15])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit empty name (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT NULL or empty HDL path passed to uvm_hdl_set_vlog
= uvm_hdl_deposit not found (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.__DEPOSIT_NOT_FOUND)
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.__DEPOSIT_NOT_FOUND)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit with indexed part-select (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[15+8:8])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit to real (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.realSignal'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= uvm_hdl_deposit to string (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.stringSignal'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= Test uvm_hdl_deposit to signal wider than UVM_HDL_MAX_WIDTH (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT hdl path 't.tooWide' is 2048 bits, but the maximum size is 1024. You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>
= uvm_hdl_deposit to not exposed (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.not_exposed)
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.not_exposed)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_force
= uvm_hdl_release
= uvm_hdl_release_and_read
= uvm_hdl_force continuously assigned signal
= uvm_hdl_release continuously assigned signal
= uvm_hdl_release_and_read continuously assigned signal
= uvm_hdl_read partially forced signal
= uvm_hdl_release partially forced signal
= uvm_hdl_force multi-bit
= uvm_hdl_release_and_read partially forced signal
= uvm_hdl_force multi-bit continuously assigned signal
= uvm_hdl_release partially forced continuously assigned signal
= uvm_hdl_release_and_read partially forced continuously assigned signal
= uvm_hdl_force single bit
= uvm_hdl_release_and_read single bit
= uvm_hdl_force single bit on continuously assigned signal
= uvm_hdl_release_and_read single bit on continuously assigned signal
= uvm_hdl_release_and_read lower 16 bits only
= uvm_hdl_release upper 16 bits only of continuously assigned signal
= uvm_hdl_force to not exposed (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.not_exposed)
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.not_exposed)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_force with indexed part-select (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[15+8:8])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_force to not forcable (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.exposed_not_forceable)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.exposed_not_forceable'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= uvm_hdl_force to real (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.realSignal'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= uvm_hdl_force to signal wider than UVM_HDL_MAX_WIDTH (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT hdl path 't.tooWide' is 2048 bits, but the maximum size is 1024. You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>
*-* All Finished *-*

View File

@ -1,4 +1,4 @@
UVM Report t/t_uvm_dpi.v:62: id message
UVM Report t/t_uvm_dpi.v:74: id message
uvm_dpi_get_tool_name_c() = Verilator
= uvm_re
= uvm_hdl_check_path
@ -12,36 +12,126 @@ uvm_dpi_get_tool_name_c() = Verilator
= uvm_hdl_read/deposit wide ascending
= uvm_hdl_read/deposit 1D memory
= uvm_hdl_read/deposit 2D memory
= uvm_hdl_read bad ranges
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.exposed[10:3])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.exposed[99:15])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read empty name (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET NULL or empty HDL path passed to uvm_hdl_get_vlog
= uvm_hdl_read not found (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.__READ_NOT_FOUND)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read with indexed part-select (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.exposed[15+8:8])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read from real (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET failed to get value for hdl path 't.realSignal'. Common reasons include a signal having an unsupported type, such as a real or a string
= uvm_hdl_read from string (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET failed to get value for hdl path 't.stringSignal'. Common reasons include a signal having an unsupported type, such as a real or a string
= uvm_hdl_read producing error message larger than print buffer (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_lorem_ipsum_dolor_sit_amet_consetetur_sadipscing_elitr_sed_diam_nonumy_eirmod_tempor_invidunt_ut_labore_et_dolore_magna_aliquyam_erat_sed_diam_voluptua_at_vero_eos_et_accusam_et_justo_duo_dolores_et_ea_rebum_stet_clita_kasd_gubergren_no_sea_takimata_sanctus_est_lorem_ipsum_dolor_sit_amet_duis_autem_vel_eum_iriure_dolor_in_hendrerit_in_vulputate_velit_esse_molestie_consequat_vel_illum_dolore_eu_feugiat_nulla_facilisis_at_vero)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_read from not exposed (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_GET unable to locate hdl path (t.not_exposed)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit bad ranges
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.exposed[10:3])
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[10:3])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.exposed[99:15])
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[99:15])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit empty name (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT NULL or empty HDL path passed to uvm_hdl_set_vlog
= uvm_hdl_deposit not found (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.__DEPOSIT_NOT_FOUND)
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.__DEPOSIT_NOT_FOUND)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit with indexed part-select (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[15+8:8])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_deposit to real (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.realSignal'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= uvm_hdl_deposit to string (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.stringSignal'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= Test uvm_hdl_deposit to signal wider than UVM_HDL_MAX_WIDTH (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT hdl path 't.tooWide' is 2048 bits, but the maximum size is 1024. You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>
= uvm_hdl_deposit to not exposed (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.not_exposed)
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.not_exposed)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_force
= uvm_hdl_release
= uvm_hdl_release_and_read
= uvm_hdl_force continuously assigned signal
= uvm_hdl_release continuously assigned signal
= uvm_hdl_release_and_read continuously assigned signal
= uvm_hdl_read partially forced signal
= uvm_hdl_release partially forced signal
= uvm_hdl_force multi-bit
= uvm_hdl_release_and_read partially forced signal
= uvm_hdl_force multi-bit continuously assigned signal
= uvm_hdl_release partially forced continuously assigned signal
= uvm_hdl_release_and_read partially forced continuously assigned signal
= uvm_hdl_force single bit
= uvm_hdl_release_and_read single bit
= uvm_hdl_force single bit on continuously assigned signal
= uvm_hdl_release_and_read single bit on continuously assigned signal
= uvm_hdl_release_and_read lower 16 bits only
= uvm_hdl_release upper 16 bits only of continuously assigned signal
= uvm_hdl_force to not exposed (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.not_exposed)
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.not_exposed)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_force with indexed part-select (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT set: unable to locate hdl path (t.exposed[15+8:8])
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
= uvm_hdl_force to not forcable (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable to locate hdl path (t.exposed_not_forceable)
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.exposed_not_forceable'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= uvm_hdl_force to real (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT failed to set hdl path 't.realSignal'. Common reasons include a signal having an unsupported type, such as a real or a string, or attempting to force a signal that is not marked as /*verilator forceable*/
= uvm_hdl_force to signal wider than UVM_HDL_MAX_WIDTH (bad)
===
UVM Report expected on next line:
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:85: UVM/DPI/VLOG_PUT hdl path 't.tooWide' is 2048 bits, but the maximum size is 1024. You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>
*-* All Finished *-*

View File

@ -32,25 +32,56 @@
#include "svdpi.h"
#include "vpi_user.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void m_uvm_error(const char *ID, const char *msg, ...);
static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int partsel);
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value);
static int uvm_hdl_max_width();
// static print buffer
static char m_uvm_temp_print_buffer[1024];
static char *m_uvm_temp_print_buffer = NULL;
static size_t m_uvm_temp_print_buffer_size = 0;
// static print error
static void m_uvm_error(const char *id, const char *msg, ...) {
va_list argptr;
va_list size_argptr;
int msg_size;
size_t formatted_msg_size;
va_start(argptr, msg);
vsprintf(m_uvm_temp_print_buffer, msg, argptr);
va_copy(size_argptr, argptr);
msg_size = vsnprintf(NULL, 0, msg, size_argptr);
va_end(size_argptr);
if (msg_size < 0) {
va_end(argptr);
m_uvm_report_dpi(M_UVM_ERROR, (char *)id,
(char *)"Failed to format UVM DPI error message", M_UVM_NONE,
(char *)__FILE__, __LINE__);
return;
}
formatted_msg_size = (size_t)msg_size + 1;
if (formatted_msg_size > m_uvm_temp_print_buffer_size) {
char *const new_buffer = (char *)realloc(m_uvm_temp_print_buffer, formatted_msg_size);
if (new_buffer == NULL) {
va_end(argptr);
m_uvm_report_dpi(M_UVM_ERROR, (char *)id,
(char *)"Failed to allocate memory for UVM DPI error message",
M_UVM_NONE, (char *)__FILE__, __LINE__);
return;
}
m_uvm_temp_print_buffer = new_buffer;
m_uvm_temp_print_buffer_size = formatted_msg_size;
}
vsnprintf(m_uvm_temp_print_buffer, m_uvm_temp_print_buffer_size, msg, argptr);
va_end(argptr);
m_uvm_report_dpi(M_UVM_ERROR, (char *)id, &m_uvm_temp_print_buffer[0], M_UVM_NONE,
m_uvm_report_dpi(M_UVM_ERROR, (char *)id, m_uvm_temp_print_buffer, M_UVM_NONE,
(char *)__FILE__, __LINE__);
}
@ -66,9 +97,6 @@ static void m_uvm_error(const char *id, const char *msg, ...) {
* If no such variable is found, then the default
* width of 1024 is used.
*
* This function should only get called once or twice,
* its return value is cached in the caller.
*
*/
static int UVM_HDL_MAX_WIDTH = 0;
static int uvm_hdl_max_width() {
@ -81,99 +109,12 @@ static int uvm_hdl_max_width() {
} else {
vpi_get_value(ms, &value_s);
UVM_HDL_MAX_WIDTH = value_s.value.integer;
vpi_release_handle(ms);
}
}
return UVM_HDL_MAX_WIDTH;
}
/*
* Internals: Given a path, look at the path name and determine
* the handle and any partsel's needed to access it.
*/
static vpiHandle uvm_hdl_handle_by_name_partsel(char *path, int *is_partsel_ptr, int *hi_ptr,
int *lo_ptr) {
vpiHandle r;
char *path_ptr;
char *path_base_ptr;
int temp;
*is_partsel_ptr = 0;
if (!path || !path[0]) return 0;
// If direct lookup works, go with that
r = vpi_handle_by_name(path, 0);
if (r) return r;
// Find array subscript
path_ptr = (char *)(path + strlen(path) - 1);
if (*path_ptr != ']') return 0;
while (path_ptr != path && *path_ptr != ':' && *path_ptr != '[') --path_ptr;
if (path_ptr == path) return 0;
*lo_ptr = *hi_ptr = atoi(path_ptr + 1);
*is_partsel_ptr = 1;
if (*path_ptr == ':') {
--path_ptr; // back over :
while (path_ptr != path && *path_ptr != '[') --path_ptr;
*hi_ptr = atoi(path_ptr + 1);
if (path_ptr == path) return 0;
}
if (*lo_ptr > *hi_ptr) {
temp = *lo_ptr;
*lo_ptr = *hi_ptr;
*hi_ptr = temp;
}
path_base_ptr = strndup(path, (path_ptr - path));
r = vpi_handle_by_name(path_base_ptr, 0);
if (!r) return 0;
{
vpiHandle rh;
s_vpi_value value;
int req_width_m1;
int decl_ranged = 0;
int decl_lo;
int decl_hi;
int decl_left = -1;
int decl_right = -1;
rh = vpi_handle(vpiLeftRange, r);
if (rh) {
value.format = vpiIntVal;
vpi_get_value(rh, &value);
decl_left = value.value.integer;
vpi_release_handle(rh);
}
rh = vpi_handle(vpiRightRange, r);
if (rh) {
value.format = vpiIntVal;
vpi_get_value(rh, &value);
decl_ranged = 1;
decl_right = value.value.integer;
vpi_release_handle(rh);
}
if (!decl_ranged) {
// vpi_printf((PLI_BYTE8 *)"Outside declaration '%s' range %d:%d\n",
// path, decl_left, decl_right);
return 0;
}
// vpi_printf((PLI_BYTE8 *)"%s:%d: req %d:%d decl %d:%d for '%s'\n",
// __FILE__, __LINE__, *hi_ptr, *lo_ptr, decl_left, decl_right, path);
decl_lo = (decl_left > decl_right) ? decl_right : decl_left;
decl_hi = (decl_left > decl_right) ? decl_left : decl_right;
if (*lo_ptr < decl_lo) return 0;
if (*hi_ptr > decl_hi) return 0;
req_width_m1 = *hi_ptr - *lo_ptr;
*lo_ptr = (decl_left > decl_right) ? (*lo_ptr - decl_lo) : (decl_right - *hi_ptr);
*hi_ptr = *lo_ptr + req_width_m1;
}
return r;
}
/*
* Given a path, look the path name up using the PLI,
* and set it to 'value'.
@ -182,24 +123,31 @@ static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag) {
vpiHandle r;
s_vpi_value value_s = {vpiIntVal, {0}};
s_vpi_time time_s = {vpiSimTime, 0, 0, 0.0};
int is_partsel, hi, lo;
int size;
int i, size, chunks;
static int s_maxsize = -1;
r = uvm_hdl_handle_by_name_partsel(path, &is_partsel, &hi, &lo);
if (path == NULL || path[0] == '\0') {
m_uvm_error("UVM/DPI/VLOG_PUT", "NULL or empty HDL path passed to uvm_hdl_set_vlog");
return 0;
}
r = vpi_handle_by_name(path, 0);
if (r == 0) {
m_uvm_error("UVM/DPI/HDL_SET",
m_uvm_error("UVM/DPI/VLOG_PUT",
"set: unable to locate hdl path (%s)\n Either the name is incorrect, "
"or you may not have PLI/ACC visibility to that name",
path);
return 0;
}
if (!is_partsel) {
value_s.format = vpiVectorVal;
value_s.value.vector = value;
vpi_put_value(r, &value_s, &time_s, flag);
} else {
if (value == NULL && flag != vpiReleaseFlag) {
m_uvm_error("UVM/DPI/VLOG_PUT",
"NULL value pointer passed for hdl path '%s' in non-release operation", path);
vpi_release_handle(r);
return 0;
}
if (value) {
if (s_maxsize == -1) s_maxsize = uvm_hdl_max_width();
size = vpi_get(vpiSize, r);
if (size > s_maxsize) {
@ -211,16 +159,24 @@ static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag) {
vpi_release_handle(r);
return 0;
}
}
value_s.format = vpiVectorVal;
vpi_get_value(r, &value_s);
value_s.format = value ? vpiVectorVal : vpiSuppressVal;
value_s.value.vector = value;
vpiHandle returnHandle = vpi_put_value(r, &value_s, &time_s, flag);
if (returnHandle == 0) {
vpi_release_handle(r);
m_uvm_error("UVM/DPI/VLOG_PUT",
"failed to set hdl path '%s'. Common reasons include a signal having an "
"unsupported type, such as a real or a string, or attempting to force a signal "
"that is not marked as /*verilator forceable*/",
path);
return 0;
}
for (int i = 0; i < (((hi - lo + 1) / 32) + 1); ++i) {
int subsize = hi - (lo + (i << 5)) + 1;
if (subsize > 32) subsize = 32;
svPutPartselLogic(&value_s.value.vector[i], value[i], lo + (i << 5), subsize);
}
vpi_put_value(r, &value_s, &time_s, flag);
if (flag == vpiReleaseFlag && value) {
chunks = (size - 1) / 32 + 1;
for (i = 0; i < chunks; ++i) value[i] = value_s.value.vector[i];
}
vpi_release_handle(r);
@ -232,14 +188,18 @@ static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag) {
* Given a path, look the path name up using the PLI
* and return its 'value'.
*/
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int partsel) {
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value) {
static int s_maxsize = -1;
int i, size, chunks;
vpiHandle r;
s_vpi_value value_s;
int is_partsel, hi, lo;
s_vpi_value value_s = {vpiVectorVal, {0}};
r = uvm_hdl_handle_by_name_partsel(path, &is_partsel, &hi, &lo);
if (path == NULL || path[0] == '\0') {
m_uvm_error("UVM/DPI/VLOG_GET", "NULL or empty HDL path passed to uvm_hdl_get_vlog");
return 0;
}
r = vpi_handle_by_name(path, 0);
if (r == 0) {
m_uvm_error("UVM/DPI/VLOG_GET",
"unable to locate hdl path (%s)\n Either the name is incorrect, or you "
@ -248,6 +208,12 @@ static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int
return 0;
}
if (value == NULL) {
m_uvm_error("UVM/DPI/VLOG_GET", "NULL value pointer passed for hdl path '%s'", path);
vpi_release_handle(r);
return 0;
}
if (s_maxsize == -1) s_maxsize = uvm_hdl_max_width();
size = vpi_get(vpiSize, r);
if (size > s_maxsize) {
@ -262,18 +228,21 @@ static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int
chunks = (size - 1) / 32 + 1;
value_s.format = vpiVectorVal;
value_s.value.vector = NULL;
vpi_get_value(r, &value_s);
if (value_s.format != vpiVectorVal || value_s.value.vector == 0) {
m_uvm_error("UVM/DPI/VLOG_GET",
"failed to get value for hdl path '%s'. Common reasons include a signal having an "
"unsupported type, such as a real or a string",
path);
vpi_release_handle(r);
return 0;
}
// Note upper bits are not cleared, other simulators do likewise
if (!is_partsel) {
// Keep as separate branch as subroutine can potentially inline and highly optimize
for (i = 0; i < chunks; ++i) {
value[i].aval = value_s.value.vector[i].aval;
value[i].bval = value_s.value.vector[i].bval;
}
} else {
// Verilator supports > 32 bit widths, which is an extension to IEEE DPI
svGetPartselLogic(value, value_s.value.vector, lo, hi - lo + 1);
for (i = 0; i < chunks; ++i) {
value[i].aval = value_s.value.vector[i].aval;
value[i].bval = value_s.value.vector[i].bval;
}
// vpi_printf((PLI_BYTE8 *)"uvm_hdl_get_vlog(%s,%0x)\n", path, value[0].aval);
vpi_release_handle(r);
@ -291,7 +260,13 @@ static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int
int uvm_hdl_check_path(char *path) {
vpiHandle handle;
if (path == NULL || path[0] == '\0') {
m_uvm_error("UVM/DPI/VLOG_CHECK", "NULL or empty HDL path passed to uvm_hdl_check_path");
return 0;
}
handle = vpi_handle_by_name(path, 0);
if (handle) vpi_release_handle(handle);
return (handle != 0);
}
@ -299,9 +274,7 @@ int uvm_hdl_check_path(char *path) {
* Given a path, look the path name up using the PLI
* or the FLI, and return its 'value'.
*/
int uvm_hdl_read(char *path, p_vpi_vecval value) {
return uvm_hdl_get_vlog(path, value, vpiNoDelay, 0);
}
int uvm_hdl_read(char *path, p_vpi_vecval value) { return uvm_hdl_get_vlog(path, value); }
/*
* Given a path, look the path name up using the PLI
@ -331,7 +304,4 @@ int uvm_hdl_release_and_read(char *path, p_vpi_vecval value) {
* Given a path, look the path name up using the PLI
* or the FLI, and release it.
*/
int uvm_hdl_release(char *path) {
s_vpi_vecval value;
return uvm_hdl_set_vlog(path, &value, vpiReleaseFlag);
}
int uvm_hdl_release(char *path) { return uvm_hdl_set_vlog(path, NULL, vpiReleaseFlag); }

View File

@ -32,25 +32,56 @@
#include "svdpi.h"
#include "vpi_user.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void m_uvm_error(const char *ID, const char *msg, ...);
static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int partsel);
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value);
static int uvm_hdl_max_width();
// static print buffer
static char m_uvm_temp_print_buffer[1024];
static char *m_uvm_temp_print_buffer = NULL;
static size_t m_uvm_temp_print_buffer_size = 0;
// static print error
static void m_uvm_error(const char *id, const char *msg, ...) {
va_list argptr;
va_list size_argptr;
int msg_size;
size_t formatted_msg_size;
va_start(argptr, msg);
vsprintf(m_uvm_temp_print_buffer, msg, argptr);
va_copy(size_argptr, argptr);
msg_size = vsnprintf(NULL, 0, msg, size_argptr);
va_end(size_argptr);
if (msg_size < 0) {
va_end(argptr);
m_uvm_report_dpi(M_UVM_ERROR, (char *)id,
(char *)"Failed to format UVM DPI error message", M_UVM_NONE,
(char *)__FILE__, __LINE__);
return;
}
formatted_msg_size = (size_t)msg_size + 1;
if (formatted_msg_size > m_uvm_temp_print_buffer_size) {
char *const new_buffer = (char *)realloc(m_uvm_temp_print_buffer, formatted_msg_size);
if (new_buffer == NULL) {
va_end(argptr);
m_uvm_report_dpi(M_UVM_ERROR, (char *)id,
(char *)"Failed to allocate memory for UVM DPI error message",
M_UVM_NONE, (char *)__FILE__, __LINE__);
return;
}
m_uvm_temp_print_buffer = new_buffer;
m_uvm_temp_print_buffer_size = formatted_msg_size;
}
vsnprintf(m_uvm_temp_print_buffer, m_uvm_temp_print_buffer_size, msg, argptr);
va_end(argptr);
m_uvm_report_dpi(M_UVM_ERROR, (char *)id, &m_uvm_temp_print_buffer[0], M_UVM_NONE,
m_uvm_report_dpi(M_UVM_ERROR, (char *)id, m_uvm_temp_print_buffer, M_UVM_NONE,
(char *)__FILE__, __LINE__);
}
@ -66,9 +97,6 @@ static void m_uvm_error(const char *id, const char *msg, ...) {
* If no such variable is found, then the default
* width of 1024 is used.
*
* This function should only get called once or twice,
* its return value is cached in the caller.
*
*/
static int UVM_HDL_MAX_WIDTH = 0;
static int uvm_hdl_max_width() {
@ -81,99 +109,12 @@ static int uvm_hdl_max_width() {
} else {
vpi_get_value(ms, &value_s);
UVM_HDL_MAX_WIDTH = value_s.value.integer;
vpi_release_handle(ms);
}
}
return UVM_HDL_MAX_WIDTH;
}
/*
* Internals: Given a path, look at the path name and determine
* the handle and any partsel's needed to access it.
*/
static vpiHandle uvm_hdl_handle_by_name_partsel(char *path, int *is_partsel_ptr, int *hi_ptr,
int *lo_ptr) {
vpiHandle r;
char *path_ptr;
char *path_base_ptr;
int temp;
*is_partsel_ptr = 0;
if (!path || !path[0]) return 0;
// If direct lookup works, go with that
r = vpi_handle_by_name(path, 0);
if (r) return r;
// Find array subscript
path_ptr = (char *)(path + strlen(path) - 1);
if (*path_ptr != ']') return 0;
while (path_ptr != path && *path_ptr != ':' && *path_ptr != '[') --path_ptr;
if (path_ptr == path) return 0;
*lo_ptr = *hi_ptr = atoi(path_ptr + 1);
*is_partsel_ptr = 1;
if (*path_ptr == ':') {
--path_ptr; // back over :
while (path_ptr != path && *path_ptr != '[') --path_ptr;
*hi_ptr = atoi(path_ptr + 1);
if (path_ptr == path) return 0;
}
if (*lo_ptr > *hi_ptr) {
temp = *lo_ptr;
*lo_ptr = *hi_ptr;
*hi_ptr = temp;
}
path_base_ptr = strndup(path, (path_ptr - path));
r = vpi_handle_by_name(path_base_ptr, 0);
if (!r) return 0;
{
vpiHandle rh;
s_vpi_value value;
int req_width_m1;
int decl_ranged = 0;
int decl_lo;
int decl_hi;
int decl_left = -1;
int decl_right = -1;
rh = vpi_handle(vpiLeftRange, r);
if (rh) {
value.format = vpiIntVal;
vpi_get_value(rh, &value);
decl_left = value.value.integer;
vpi_release_handle(rh);
}
rh = vpi_handle(vpiRightRange, r);
if (rh) {
value.format = vpiIntVal;
vpi_get_value(rh, &value);
decl_ranged = 1;
decl_right = value.value.integer;
vpi_release_handle(rh);
}
if (!decl_ranged) {
// vpi_printf((PLI_BYTE8 *)"Outside declaration '%s' range %d:%d\n",
// path, decl_left, decl_right);
return 0;
}
// vpi_printf((PLI_BYTE8 *)"%s:%d: req %d:%d decl %d:%d for '%s'\n",
// __FILE__, __LINE__, *hi_ptr, *lo_ptr, decl_left, decl_right, path);
decl_lo = (decl_left > decl_right) ? decl_right : decl_left;
decl_hi = (decl_left > decl_right) ? decl_left : decl_right;
if (*lo_ptr < decl_lo) return 0;
if (*hi_ptr > decl_hi) return 0;
req_width_m1 = *hi_ptr - *lo_ptr;
*lo_ptr = (decl_left > decl_right) ? (*lo_ptr - decl_lo) : (decl_right - *hi_ptr);
*hi_ptr = *lo_ptr + req_width_m1;
}
return r;
}
/*
* Given a path, look the path name up using the PLI,
* and set it to 'value'.
@ -182,24 +123,31 @@ static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag) {
vpiHandle r;
s_vpi_value value_s = {vpiIntVal, {0}};
s_vpi_time time_s = {vpiSimTime, 0, 0, 0.0};
int is_partsel, hi, lo;
int size;
int i, size, chunks;
static int s_maxsize = -1;
r = uvm_hdl_handle_by_name_partsel(path, &is_partsel, &hi, &lo);
if (path == NULL || path[0] == '\0') {
m_uvm_error("UVM/DPI/VLOG_PUT", "NULL or empty HDL path passed to uvm_hdl_set_vlog");
return 0;
}
r = vpi_handle_by_name(path, 0);
if (r == 0) {
m_uvm_error("UVM/DPI/HDL_SET",
m_uvm_error("UVM/DPI/VLOG_PUT",
"set: unable to locate hdl path (%s)\n Either the name is incorrect, "
"or you may not have PLI/ACC visibility to that name",
path);
return 0;
}
if (!is_partsel) {
value_s.format = vpiVectorVal;
value_s.value.vector = value;
vpi_put_value(r, &value_s, &time_s, flag);
} else {
if (value == NULL && flag != vpiReleaseFlag) {
m_uvm_error("UVM/DPI/VLOG_PUT",
"NULL value pointer passed for hdl path '%s' in non-release operation", path);
vpi_release_handle(r);
return 0;
}
if (value) {
if (s_maxsize == -1) s_maxsize = uvm_hdl_max_width();
size = vpi_get(vpiSize, r);
if (size > s_maxsize) {
@ -211,16 +159,24 @@ static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag) {
vpi_release_handle(r);
return 0;
}
}
value_s.format = vpiVectorVal;
vpi_get_value(r, &value_s);
value_s.format = value ? vpiVectorVal : vpiSuppressVal;
value_s.value.vector = value;
vpiHandle returnHandle = vpi_put_value(r, &value_s, &time_s, flag);
if (returnHandle == 0) {
vpi_release_handle(r);
m_uvm_error("UVM/DPI/VLOG_PUT",
"failed to set hdl path '%s'. Common reasons include a signal having an "
"unsupported type, such as a real or a string, or attempting to force a signal "
"that is not marked as /*verilator forceable*/",
path);
return 0;
}
for (int i = 0; i < (((hi - lo + 1) / 32) + 1); ++i) {
int subsize = hi - (lo + (i << 5)) + 1;
if (subsize > 32) subsize = 32;
svPutPartselLogic(&value_s.value.vector[i], value[i], lo + (i << 5), subsize);
}
vpi_put_value(r, &value_s, &time_s, flag);
if (flag == vpiReleaseFlag && value) {
chunks = (size - 1) / 32 + 1;
for (i = 0; i < chunks; ++i) value[i] = value_s.value.vector[i];
}
vpi_release_handle(r);
@ -232,14 +188,18 @@ static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag) {
* Given a path, look the path name up using the PLI
* and return its 'value'.
*/
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int partsel) {
static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value) {
static int s_maxsize = -1;
int i, size, chunks;
vpiHandle r;
s_vpi_value value_s;
int is_partsel, hi, lo;
s_vpi_value value_s = {vpiVectorVal, {0}};
r = uvm_hdl_handle_by_name_partsel(path, &is_partsel, &hi, &lo);
if (path == NULL || path[0] == '\0') {
m_uvm_error("UVM/DPI/VLOG_GET", "NULL or empty HDL path passed to uvm_hdl_get_vlog");
return 0;
}
r = vpi_handle_by_name(path, 0);
if (r == 0) {
m_uvm_error("UVM/DPI/VLOG_GET",
"unable to locate hdl path (%s)\n Either the name is incorrect, or you "
@ -248,6 +208,12 @@ static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int
return 0;
}
if (value == NULL) {
m_uvm_error("UVM/DPI/VLOG_GET", "NULL value pointer passed for hdl path '%s'", path);
vpi_release_handle(r);
return 0;
}
if (s_maxsize == -1) s_maxsize = uvm_hdl_max_width();
size = vpi_get(vpiSize, r);
if (size > s_maxsize) {
@ -262,18 +228,21 @@ static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int
chunks = (size - 1) / 32 + 1;
value_s.format = vpiVectorVal;
value_s.value.vector = NULL;
vpi_get_value(r, &value_s);
if (value_s.format != vpiVectorVal || value_s.value.vector == 0) {
m_uvm_error("UVM/DPI/VLOG_GET",
"failed to get value for hdl path '%s'. Common reasons include a signal having an "
"unsupported type, such as a real or a string",
path);
vpi_release_handle(r);
return 0;
}
// Note upper bits are not cleared, other simulators do likewise
if (!is_partsel) {
// Keep as separate branch as subroutine can potentially inline and highly optimize
for (i = 0; i < chunks; ++i) {
value[i].aval = value_s.value.vector[i].aval;
value[i].bval = value_s.value.vector[i].bval;
}
} else {
// Verilator supports > 32 bit widths, which is an extension to IEEE DPI
svGetPartselLogic(value, value_s.value.vector, lo, hi - lo + 1);
for (i = 0; i < chunks; ++i) {
value[i].aval = value_s.value.vector[i].aval;
value[i].bval = value_s.value.vector[i].bval;
}
// vpi_printf((PLI_BYTE8 *)"uvm_hdl_get_vlog(%s,%0x)\n", path, value[0].aval);
vpi_release_handle(r);
@ -291,7 +260,13 @@ static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int
int uvm_hdl_check_path(char *path) {
vpiHandle handle;
if (path == NULL || path[0] == '\0') {
m_uvm_error("UVM/DPI/VLOG_CHECK", "NULL or empty HDL path passed to uvm_hdl_check_path");
return 0;
}
handle = vpi_handle_by_name(path, 0);
if (handle) vpi_release_handle(handle);
return (handle != 0);
}
@ -299,9 +274,7 @@ int uvm_hdl_check_path(char *path) {
* Given a path, look the path name up using the PLI
* or the FLI, and return its 'value'.
*/
int uvm_hdl_read(char *path, p_vpi_vecval value) {
return uvm_hdl_get_vlog(path, value, vpiNoDelay, 0);
}
int uvm_hdl_read(char *path, p_vpi_vecval value) { return uvm_hdl_get_vlog(path, value); }
/*
* Given a path, look the path name up using the PLI
@ -331,7 +304,4 @@ int uvm_hdl_release_and_read(char *path, p_vpi_vecval value) {
* Given a path, look the path name up using the PLI
* or the FLI, and release it.
*/
int uvm_hdl_release(char *path) {
s_vpi_vecval value;
return uvm_hdl_set_vlog(path, &value, vpiReleaseFlag);
}
int uvm_hdl_release(char *path) { return uvm_hdl_set_vlog(path, NULL, vpiReleaseFlag); }