From f7a349c5a794c10b4eec703bd4d0c271aed8ef46 Mon Sep 17 00:00:00 2001 From: Christian Hecken Date: Sun, 19 Apr 2026 14:24:07 +0200 Subject: [PATCH] Fix uvm_hdl_release_and_read not reading release value or checking for success (#7425) --- include/verilated_vpi.cpp | 2 +- test_regress/t/t_uvm_dpi.v | 262 +++++++++++++++++- test_regress/t/t_uvm_dpi_v2017_1_0.out | 106 ++++++- test_regress/t/t_uvm_dpi_v2020_3_1.out | 106 ++++++- .../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c | 240 +++++++--------- .../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c | 240 +++++++--------- 6 files changed, 664 insertions(+), 292 deletions(-) diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 56f291a38..8abbc5205 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -3402,7 +3402,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_ vpi_put_value(object, const_cast(&forcedValue), nullptr, vpiNoDelay); } - return nullptr; + return object; } if (valuep->format == vpiVectorVal) { diff --git a/test_regress/t/t_uvm_dpi.v b/test_regress/t/t_uvm_dpi.v index 8902752e3..bbd17b9b0 100644 --- a/test_regress/t/t_uvm_dpi.v +++ b/test_regress/t/t_uvm_dpi.v @@ -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"); diff --git a/test_regress/t/t_uvm_dpi_v2017_1_0.out b/test_regress/t/t_uvm_dpi_v2017_1_0.out index 0d94db473..c89a337ba 100644 --- a/test_regress/t/t_uvm_dpi_v2017_1_0.out +++ b/test_regress/t/t_uvm_dpi_v2017_1_0.out @@ -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= = 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= *-* All Finished *-* diff --git a/test_regress/t/t_uvm_dpi_v2020_3_1.out b/test_regress/t/t_uvm_dpi_v2020_3_1.out index a3b89cc42..0b4e6389e 100644 --- a/test_regress/t/t_uvm_dpi_v2020_3_1.out +++ b/test_regress/t/t_uvm_dpi_v2020_3_1.out @@ -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= = 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= *-* All Finished *-* diff --git a/test_regress/t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c b/test_regress/t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c index f4cb9ea7a..40841cbe3 100644 --- a/test_regress/t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c +++ b/test_regress/t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c @@ -32,25 +32,56 @@ #include "svdpi.h" #include "vpi_user.h" +#include #include #include #include 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); } diff --git a/test_regress/t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c b/test_regress/t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c index f4cb9ea7a..40841cbe3 100644 --- a/test_regress/t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c +++ b/test_regress/t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c @@ -32,25 +32,56 @@ #include "svdpi.h" #include "vpi_user.h" +#include #include #include #include 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); }