Add `-Wno-vla-cxx-extension` CLang flag, and UVM DPI tests (#6782)
This commit is contained in:
parent
e6a3d61d25
commit
db2099a4dc
|
|
@ -534,7 +534,8 @@ m4_foreach([cflag],[
|
||||||
[-Wno-unused-but-set-parameter],
|
[-Wno-unused-but-set-parameter],
|
||||||
[-Wno-unused-but-set-variable],
|
[-Wno-unused-but-set-variable],
|
||||||
[-Wno-unused-parameter],
|
[-Wno-unused-parameter],
|
||||||
[-Wno-unused-variable]],[
|
[-Wno-unused-variable],
|
||||||
|
[-Wno-vla-cxx-extension]],[
|
||||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,cflag)
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,cflag)
|
||||||
# CMake will test what flags work itself, so pass all flags through to it
|
# CMake will test what flags work itself, so pass all flags through to it
|
||||||
CFG_CXX_FLAGS_CMAKE="$CFG_CXX_FLAGS_CMAKE cflag"
|
CFG_CXX_FLAGS_CMAKE="$CFG_CXX_FLAGS_CMAKE cflag"
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ for filename in files.split():
|
||||||
continue
|
continue
|
||||||
if "include/gtkwave/" in filename: # Standard file - can't change it
|
if "include/gtkwave/" in filename: # Standard file - can't change it
|
||||||
continue
|
continue
|
||||||
if "test_regress/t/uvm/dpi/" in filename: # Standard file - can't change it
|
if "test_regress/t/uvm/" in filename: # Standard file - can't change it
|
||||||
continue
|
continue
|
||||||
filename = os.path.join(test.root, filename)
|
filename = os.path.join(test.root, filename)
|
||||||
if not os.path.exists(filename):
|
if not os.path.exists(filename):
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,16 @@
|
||||||
// any use, without warranty, 2025 by Wilson Snyder.
|
// any use, without warranty, 2025 by Wilson Snyder.
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`ifdef T_V2020_3_1
|
||||||
|
function void uvm_report_error(string a, string b);
|
||||||
|
$display("uvm_report_error(\"%s\", \"%s\")", a, b);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
export "DPI-C" function uvm_polling_value_change_notify;
|
||||||
|
function void uvm_polling_value_change_notify(int sv_key);
|
||||||
|
endfunction
|
||||||
|
`endif
|
||||||
|
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
`include "dpi/uvm_dpi.svh"
|
`include "dpi/uvm_dpi.svh"
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
UVM Report t/t_uvm_dpi.v:42: id message
|
UVM Report t/t_uvm_dpi.v:52: id message
|
||||||
uvm_dpi_get_tool_name_c() = Verilator
|
uvm_dpi_get_tool_name_c() = Verilator
|
||||||
= uvm_re
|
= uvm_re
|
||||||
= uvm_hdl_check_path
|
= uvm_hdl_check_path
|
||||||
|
|
@ -6,7 +6,7 @@ uvm_dpi_get_tool_name_c() = Verilator
|
||||||
= uvm_hdl_read not found (bad)
|
= uvm_hdl_read not found (bad)
|
||||||
===
|
===
|
||||||
UVM Report expected on next line:
|
UVM Report expected on next line:
|
||||||
UVM Report ../../t/uvm/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:54: UVM/DPI/HDL_SET 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
|
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
|
||||||
= uvm_hdl_deposit simple variable
|
= uvm_hdl_deposit simple variable
|
||||||
= uvm_hdl_read single bit
|
= uvm_hdl_read single bit
|
||||||
|
|
@ -16,22 +16,22 @@ UVM Report ../../t/uvm/dpi/uvm_hdl_verilator.c:54: UVM/DPI/HDL_SET set: unable t
|
||||||
= uvm_hdl_deposit bad ranges
|
= uvm_hdl_deposit bad ranges
|
||||||
===
|
===
|
||||||
UVM Report expected on next line:
|
UVM Report expected on next line:
|
||||||
UVM Report ../../t/uvm/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:54: UVM/DPI/HDL_SET 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
|
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
|
||||||
===
|
===
|
||||||
UVM Report expected on next line:
|
UVM Report expected on next line:
|
||||||
UVM Report ../../t/uvm/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:54: UVM/DPI/HDL_SET 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
|
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
|
||||||
= uvm_hdl_force
|
= uvm_hdl_force
|
||||||
===
|
===
|
||||||
UVM Report expected on next line:
|
UVM Report expected on next line:
|
||||||
UVM Report ../../t/uvm/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
||||||
= uvm_hdl_release
|
= uvm_hdl_release
|
||||||
===
|
===
|
||||||
UVM Report expected on next line:
|
UVM Report expected on next line:
|
||||||
UVM Report ../../t/uvm/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
||||||
= uvm_hdl_release_and_read
|
= uvm_hdl_release_and_read
|
||||||
===
|
===
|
||||||
UVM Report expected on next line:
|
UVM Report expected on next line:
|
||||||
UVM Report ../../t/uvm/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
UVM Report ../../t/uvm/v2017_1_0/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
||||||
*-* All Finished *-*
|
*-* All Finished *-*
|
||||||
|
|
@ -10,13 +10,16 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt')
|
test.scenarios('vlt')
|
||||||
test.pli_filename = "t/uvm/dpi/uvm_dpi.cc"
|
test.top_filename = "t/t_uvm_dpi.v"
|
||||||
|
test.pli_filename = "t/uvm/v2017_1_0/dpi/uvm_dpi.cc"
|
||||||
|
|
||||||
if re.search(r'clang', test.cxx_version):
|
if re.search(r'clang', test.cxx_version):
|
||||||
test.skip("uvm_regex.cc from upstream has clang warnings")
|
test.skip("uvm_regex.cc from upstream has clang warnings")
|
||||||
|
|
||||||
test.compile(
|
test.compile(verilator_flags2=[
|
||||||
verilator_flags2=["--binary", "--build-jobs 4", "--vpi", "+incdir+t/uvm", test.pli_filename])
|
"--binary", "--build-jobs 4", "--vpi", "+define+T_V2017_1_0", "+incdir+t/uvm/v2017_1_0",
|
||||||
|
test.pli_filename
|
||||||
|
])
|
||||||
|
|
||||||
test.execute(expect_filename=test.golden_filename)
|
test.execute(expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
UVM Report t/t_uvm_dpi.v:52: id message
|
||||||
|
uvm_dpi_get_tool_name_c() = Verilator
|
||||||
|
= uvm_re
|
||||||
|
= uvm_hdl_check_path
|
||||||
|
= uvm_hdl_read simple variable
|
||||||
|
= uvm_hdl_read 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)
|
||||||
|
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
|
||||||
|
= uvm_hdl_deposit simple variable
|
||||||
|
= uvm_hdl_read single bit
|
||||||
|
= uvm_hdl_deposit single bit
|
||||||
|
= uvm_hdl_read multi-bit
|
||||||
|
= uvm_hdl_deposit multi-bit
|
||||||
|
= 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])
|
||||||
|
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])
|
||||||
|
Either the name is incorrect, or you may not have PLI/ACC visibility to that name
|
||||||
|
= uvm_hdl_force
|
||||||
|
===
|
||||||
|
UVM Report expected on next line:
|
||||||
|
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
||||||
|
= uvm_hdl_release
|
||||||
|
===
|
||||||
|
UVM Report expected on next line:
|
||||||
|
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
||||||
|
= uvm_hdl_release_and_read
|
||||||
|
===
|
||||||
|
UVM Report expected on next line:
|
||||||
|
UVM Report ../../t/uvm/v2020_3_1/dpi/uvm_hdl_verilator.c:54: UVM/DPI/VLOG_GET Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path 't.exposed'
|
||||||
|
*-* All Finished *-*
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
test.top_filename = "t/t_uvm_dpi.v"
|
||||||
|
test.pli_filename = "t/uvm/v2020_3_1/dpi/uvm_dpi.cc"
|
||||||
|
|
||||||
|
if re.search(r'clang', test.cxx_version):
|
||||||
|
test.skip("uvm_regex.cc from upstream has clang warnings")
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=[
|
||||||
|
"--binary", "--build-jobs 4", "--vpi", "+define+T_V2020_3_1", "+incdir+t/uvm/v2020_3_1",
|
||||||
|
test.pli_filename
|
||||||
|
])
|
||||||
|
|
||||||
|
test.execute(expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -13,6 +13,6 @@ module t;
|
||||||
import uvm_pkg::*;
|
import uvm_pkg::*;
|
||||||
initial begin
|
initial begin
|
||||||
// verilator lint_off WIDTHTRUNC
|
// verilator lint_off WIDTHTRUNC
|
||||||
`uvm_info("TOP", "Hello World!", UVM_MEDIUM);
|
`uvm_info("TOP", "UVM TEST PASSED", UVM_MEDIUM);
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.priority(50)
|
||||||
|
test.scenarios('vlt')
|
||||||
|
test.top_filename = 't/t_uvm_hello.v'
|
||||||
|
test.pli_filename = "t/uvm/v2017_1_0/dpi/uvm_dpi.cc"
|
||||||
|
|
||||||
|
if test.have_dev_gcov:
|
||||||
|
test.skip("Test suite intended for full dev coverage without needing this test")
|
||||||
|
|
||||||
|
test.compile(v_flags2=[
|
||||||
|
"--binary",
|
||||||
|
"--vpi",
|
||||||
|
"-j 0",
|
||||||
|
"--CFLAGS -O0",
|
||||||
|
"-Wall",
|
||||||
|
"+incdir+t/uvm", #
|
||||||
|
"t/uvm/uvm_pkg_all_v2017_1_0_dpi.svh",
|
||||||
|
test.pli_filename
|
||||||
|
])
|
||||||
|
|
||||||
|
test.execute(all_run_flags=['' if test.verbose else '+UVM_NO_RELNOTES'])
|
||||||
|
|
||||||
|
test.file_grep(test.run_log_filename, r'UVM TEST PASSED')
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -19,9 +19,14 @@ if test.have_dev_gcov:
|
||||||
test.compile(v_flags2=[
|
test.compile(v_flags2=[
|
||||||
"--binary",
|
"--binary",
|
||||||
"-j 0",
|
"-j 0",
|
||||||
|
"--CFLAGS -O0",
|
||||||
"-Wall",
|
"-Wall",
|
||||||
"+incdir+t/uvm", #
|
"+incdir+t/uvm", #
|
||||||
"t/uvm/uvm_pkg_all_v2017_1_0_nodpi.svh",
|
"t/uvm/uvm_pkg_all_v2017_1_0_nodpi.svh",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
test.execute(all_run_flags=['' if test.verbose else '+UVM_NO_RELNOTES'])
|
||||||
|
|
||||||
|
test.file_grep(test.run_log_filename, r'UVM TEST PASSED')
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.priority(50)
|
||||||
|
test.scenarios('vlt')
|
||||||
|
test.top_filename = 't/t_uvm_hello.v'
|
||||||
|
test.pli_filename = "t/uvm/v2020_3_1/dpi/uvm_dpi.cc"
|
||||||
|
|
||||||
|
if test.have_dev_gcov:
|
||||||
|
test.skip("Test suite intended for full dev coverage without needing this test")
|
||||||
|
|
||||||
|
test.compile(v_flags2=[
|
||||||
|
"--binary",
|
||||||
|
"--vpi",
|
||||||
|
"-j 0",
|
||||||
|
"--CFLAGS -O0",
|
||||||
|
"-Wall",
|
||||||
|
"+incdir+t/uvm", #
|
||||||
|
"t/uvm/uvm_pkg_all_v2020_3_1_dpi.svh",
|
||||||
|
test.pli_filename
|
||||||
|
])
|
||||||
|
|
||||||
|
test.execute(all_run_flags=['' if test.verbose else '+UVM_NO_RELNOTES'])
|
||||||
|
|
||||||
|
test.file_grep(test.run_log_filename, r'UVM TEST PASSED')
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -19,9 +19,14 @@ if test.have_dev_gcov:
|
||||||
test.compile(v_flags2=[
|
test.compile(v_flags2=[
|
||||||
"--binary",
|
"--binary",
|
||||||
"-j 0",
|
"-j 0",
|
||||||
|
"--CFLAGS -O0",
|
||||||
"-Wall",
|
"-Wall",
|
||||||
"+incdir+t/uvm", #
|
"+incdir+t/uvm", #
|
||||||
"t/uvm/uvm_pkg_all_v2020_3_1_nodpi.svh",
|
"t/uvm/uvm_pkg_all_v2020_3_1_nodpi.svh",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
test.execute(all_run_flags=['' if test.verbose else '+UVM_NO_RELNOTES'])
|
||||||
|
|
||||||
|
test.file_grep(test.run_log_filename, r'UVM TEST PASSED')
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
|
|
||||||
`ifndef UVM_HDL_MAX_WIDTH
|
`ifndef UVM_HDL_MAX_WIDTH
|
||||||
|
// @uvm-ieee 1800.2-2017 auto 19.6.1
|
||||||
`define UVM_HDL_MAX_WIDTH 1024
|
`define UVM_HDL_MAX_WIDTH 1024
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
@ -50,8 +51,6 @@
|
||||||
* vpi_handle_by_name(
|
* vpi_handle_by_name(
|
||||||
* "uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
|
* "uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @uvm-ieee 1800.2-2020 manual 19.6.1
|
|
||||||
parameter int UVM_HDL_MAX_WIDTH = `UVM_HDL_MAX_WIDTH;
|
parameter int UVM_HDL_MAX_WIDTH = `UVM_HDL_MAX_WIDTH;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -153,7 +152,7 @@ typedef logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t;
|
||||||
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
function int uvm_hdl_release(string path);
|
function int uvm_hdl_release(string path, output uvm_hdl_data_t value);
|
||||||
uvm_report_fatal("UVM_HDL_RELEASE",
|
uvm_report_fatal("UVM_HDL_RELEASE",
|
||||||
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -167,4 +166,5 @@ typedef logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t;
|
||||||
|
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
||||||
`endif
|
`endif
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: DontAlign
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: All
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 99
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 2
|
||||||
|
ContinuationIndentWidth: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
|
||||||
|
# Include grouping/sorting
|
||||||
|
SortIncludes: true
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '"V3Pch.*\.h"'
|
||||||
|
Priority: -2 # Precompiled headers
|
||||||
|
- Regex: '"(config_build|verilated_config|verilatedos)\.h"'
|
||||||
|
Priority: -1 # Sepecials before main header
|
||||||
|
- Regex: '(<|")verilated.*'
|
||||||
|
Priority: 1 # Runtime headers
|
||||||
|
- Regex: '"V3.*__gen.*\.h"'
|
||||||
|
Priority: 3 # Generated internal headers separately
|
||||||
|
- Regex: '"V3.*"'
|
||||||
|
Priority: 2 # Internal header
|
||||||
|
- Regex: '".*"'
|
||||||
|
Priority: 4 # Other non-system headers
|
||||||
|
- Regex: '<[[:alnum:]_.]+>'
|
||||||
|
Priority: 5 # Simple system headers next
|
||||||
|
- Regex: '<.*>'
|
||||||
|
Priority: 6 # Other system headers next
|
||||||
|
IncludeIsMainRegex: '$'
|
||||||
|
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInLineCommentPrefix:
|
||||||
|
Minimum: 0
|
||||||
|
Maximum: -1
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2010 AMD
|
||||||
|
// Copyright 2010-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2010-2011 Mentor Graphics Corporation
|
||||||
|
// Copyright 2013-2024 NVIDIA Corporation
|
||||||
|
// Copyright 2010-2013 Synopsys, Inc.
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_common.c $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// Implementation of common methods for DPI
|
||||||
|
|
||||||
|
extern void m__uvm_report_dpi(int,const char*,const char*,int,const char*, int);
|
||||||
|
|
||||||
|
#if defined(XCELIUM) || defined(NCSC)
|
||||||
|
const static char* uvm_package_scope_name = "uvm_pkg::";
|
||||||
|
#else
|
||||||
|
const static char* uvm_package_scope_name = "uvm_pkg";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void m_uvm_report_dpi( int severity,
|
||||||
|
char* id,
|
||||||
|
char* message,
|
||||||
|
int verbosity,
|
||||||
|
char* file,
|
||||||
|
int linenum) {
|
||||||
|
svScope old_scope = svSetScope(svGetScopeFromName(uvm_package_scope_name));
|
||||||
|
m__uvm_report_dpi(severity, id, message, verbosity, file, linenum);
|
||||||
|
svSetScope(old_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int int_str_max ( int radix_bits ) {
|
||||||
|
int val = INT_MAX;
|
||||||
|
int ret = 1;
|
||||||
|
while ((val = (val /radix_bits)))
|
||||||
|
ret++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2010-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2023 Intel Corporation
|
||||||
|
// Copyright 2010-2017 Mentor Graphics Corporation
|
||||||
|
// Copyright 2013-2024 NVIDIA Corporation
|
||||||
|
// Copyright 2010-2013 Synopsys, Inc.
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_dpi.cc $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Top-level file that includes all of the C/C++ files required
|
||||||
|
// by UVM
|
||||||
|
//
|
||||||
|
// The C code may be compiled by compiling this top file only,
|
||||||
|
// or by compiling individual files then linking them together.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "uvm_dpi.h"
|
||||||
|
|
||||||
|
// Avoid -Wmissing-definitions
|
||||||
|
int uvm_hdl_check_path(char *path);
|
||||||
|
int uvm_hdl_read(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_deposit(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_force(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_release_and_read(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_release(char *path);
|
||||||
|
void push_data(int lvl,char *entry, int cmd);
|
||||||
|
void walk_level(int lvl, int argc, char**argv,int cmd);
|
||||||
|
const char *uvm_dpi_get_next_arg_c (int init);
|
||||||
|
extern char* uvm_dpi_get_tool_name_c ();
|
||||||
|
extern char* uvm_dpi_get_tool_version_c ();
|
||||||
|
|
||||||
|
extern char* uvm_re_buffer();
|
||||||
|
extern const char* uvm_re_deglobbed(const char *glob, unsigned char with_brackets);
|
||||||
|
extern void uvm_re_free(regex_t* handle);
|
||||||
|
extern regex_t* uvm_re_comp(const char* re, unsigned char deglob);
|
||||||
|
extern int uvm_re_exec(regex_t* rexp, const char *str);
|
||||||
|
extern regex_t* uvm_re_compexec(const char* re, const char* str, unsigned char deglob, int* exec_ret);
|
||||||
|
|
||||||
|
#include "uvm_common.c"
|
||||||
|
#include "uvm_regex.cc"
|
||||||
|
#include "uvm_hdl.c"
|
||||||
|
#include "uvm_svcmd_dpi.c"
|
||||||
|
//#ifdef UVM_PLI_POLLING_ENABLE
|
||||||
|
#include "uvm_hdl_polling.c"
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2010-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2010-2017 Mentor Graphics Corporation
|
||||||
|
// Copyright 2013-2024 NVIDIA Corporation
|
||||||
|
// Copyright 2010 Synopsys, Inc.
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_dpi.h $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Top level header filke that wraps all requirements which
|
||||||
|
// are common to the various C/C++ files in UVM.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef UVM_DPI__H
|
||||||
|
#define UVM_DPI__H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "vpi_user.h"
|
||||||
|
#include "veriuser.h"
|
||||||
|
#include "svdpi.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
// The following consts and method call are for
|
||||||
|
// internal usage by the UVM DPI implementation,
|
||||||
|
// and are not intended for public use.
|
||||||
|
static const int M_UVM_INFO = 0;
|
||||||
|
static const int M_UVM_WARNING = 1;
|
||||||
|
static const int M_UVM_ERROR = 2;
|
||||||
|
static const int M_UVM_FATAL = 3;
|
||||||
|
|
||||||
|
static const int M_UVM_NONE = 0;
|
||||||
|
static const int M_UVM_LOW = 100;
|
||||||
|
static const int M_UVM_MEDIUM = 200;
|
||||||
|
static const int M_UVM_HIGH = 300;
|
||||||
|
static const int M_UVM_FULL = 400;
|
||||||
|
static const int M_UVM_DEBUG = 500;
|
||||||
|
|
||||||
|
void m_uvm_report_dpi(int severity,
|
||||||
|
char* id,
|
||||||
|
char* message,
|
||||||
|
int verbosity,
|
||||||
|
char* file,
|
||||||
|
int linenum);
|
||||||
|
|
||||||
|
int int_str_max( int );
|
||||||
|
|
||||||
|
char * uvm_re_buffer();
|
||||||
|
const char * uvm_re_deglobbed(const char *glob, unsigned char with_brackets);
|
||||||
|
void uvm_re_free(regex_t* handle);
|
||||||
|
regex_t* uvm_re_comp(const char *re, unsigned char deglob);
|
||||||
|
int uvm_re_exec(regex_t* rexp, const char *str);
|
||||||
|
regex_t* uvm_re_compexec(const char *re, const char *str, unsigned char deglob, int* exec_ret);
|
||||||
|
|
||||||
|
|
||||||
|
int uvm_hdl_check_path(char *path);
|
||||||
|
int uvm_hdl_read(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_deposit(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_force(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_release_and_read(char *path, p_vpi_vecval value);
|
||||||
|
int uvm_hdl_release(char *path);
|
||||||
|
|
||||||
|
void push_data(int lvl,char *entry, int cmd);
|
||||||
|
void walk_level(int lvl, int argc, char**argv,int cmd);
|
||||||
|
const char *uvm_dpi_get_next_arg_c (int init);
|
||||||
|
extern char* uvm_dpi_get_tool_name_c ();
|
||||||
|
extern char* uvm_dpi_get_tool_version_c ();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2010 AMD
|
||||||
|
// Copyright 2010-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2023 Intel Corporation
|
||||||
|
// Copyright 2010-2011 Mentor Graphics Corporation
|
||||||
|
// Copyright 2020-2024 NVIDIA Corporation
|
||||||
|
// Copyright 2010 Synopsys, Inc.
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_dpi.svh $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef UVM_DPI_SVH
|
||||||
|
`define UVM_DPI_SVH
|
||||||
|
|
||||||
|
//
|
||||||
|
// Top-level file for DPI subroutines used by UVM.
|
||||||
|
//
|
||||||
|
// Tool-specific distribution overlays may be required.
|
||||||
|
//
|
||||||
|
// To use UVM without any tool-specific overlay, use +defin+UVM_NO_DPI
|
||||||
|
//
|
||||||
|
|
||||||
|
`ifdef UVM_NO_DPI
|
||||||
|
`define UVM_HDL_NO_DPI
|
||||||
|
`define UVM_REGEX_NO_DPI
|
||||||
|
`define UVM_CMDLINE_NO_DPI
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`include "dpi/uvm_hdl.svh"
|
||||||
|
`include "dpi/uvm_svcmd_dpi.svh"
|
||||||
|
`include "dpi/uvm_regex.svh"
|
||||||
|
|
||||||
|
`ifdef UVM_PLI_POLLING_ENABLE
|
||||||
|
`include "dpi/uvm_polling_dpi.svh"
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`endif // UVM_DPI_SVH
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2007-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2009-2011 Mentor Graphics Corporation
|
||||||
|
// Copyright 2013-2024 NVIDIA Corporation
|
||||||
|
// Copyright 2010-2011 Synopsys, Inc.
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_hdl.c $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// hdl vendor backends are defined for VCS,QUESTA,VERILATOR,XCELIUM
|
||||||
|
#if defined(VCS) || defined(VCSMX)
|
||||||
|
#include "uvm_hdl_vcs.c"
|
||||||
|
#else
|
||||||
|
#ifdef QUESTA
|
||||||
|
#include "uvm_hdl_questa.c"
|
||||||
|
#else
|
||||||
|
#ifdef VERILATOR
|
||||||
|
#include "uvm_hdl_verilator.c"
|
||||||
|
#else
|
||||||
|
#if defined(XCELIUM) || defined(NCSC)
|
||||||
|
#include "uvm_hdl_xcelium.c"
|
||||||
|
#else
|
||||||
|
#error "hdl vendor backend is missing"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2012 Accellera Systems Initiative
|
||||||
|
// Copyright 2015 Analog Devices, Inc.
|
||||||
|
// Copyright 2010-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2014 Cisco Systems, Inc.
|
||||||
|
// Copyright 2022-2023 Intel Corporation
|
||||||
|
// Copyright 2007-2011 Mentor Graphics Corporation
|
||||||
|
// Copyright 2014-2024 NVIDIA Corporation
|
||||||
|
// Copyright 2010 Synopsys, Inc.
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_hdl.svh $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TITLE -- NODOCS -- UVM HDL Backdoor Access support routines.
|
||||||
|
//
|
||||||
|
// These routines provide an interface to the DPI/PLI
|
||||||
|
// implementation of backdoor access used by registers.
|
||||||
|
//
|
||||||
|
// If you DON'T want to use the DPI HDL API, then compile your
|
||||||
|
// SystemVerilog code with the vlog switch
|
||||||
|
//: vlog ... +define+UVM_HDL_NO_DPI ...
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef UVM_HDL__SVH
|
||||||
|
`define UVM_HDL__SVH
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef UVM_HDL_MAX_WIDTH
|
||||||
|
`define UVM_HDL_MAX_WIDTH 1024
|
||||||
|
`endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VARIABLE -- NODOCS -- UVM_HDL_MAX_WIDTH
|
||||||
|
* Sets the maximum size bit vector for backdoor access.
|
||||||
|
* This parameter will be looked up by the
|
||||||
|
* DPI-C code using:
|
||||||
|
* vpi_handle_by_name(
|
||||||
|
* "uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @uvm-ieee 1800.2-2020 manual 19.6.1
|
||||||
|
parameter int UVM_HDL_MAX_WIDTH = `UVM_HDL_MAX_WIDTH;
|
||||||
|
|
||||||
|
|
||||||
|
typedef logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef UVM_HDL_NO_DPI
|
||||||
|
|
||||||
|
// Function -- NODOCS -- uvm_hdl_check_path
|
||||||
|
//
|
||||||
|
// Checks that the given HDL ~path~ exists. Returns 0 if NOT found, 1 otherwise.
|
||||||
|
//
|
||||||
|
import "DPI-C" context function int uvm_hdl_check_path(string path);
|
||||||
|
|
||||||
|
|
||||||
|
// Function -- NODOCS -- uvm_hdl_deposit
|
||||||
|
//
|
||||||
|
// Sets the given HDL ~path~ to the specified ~value~.
|
||||||
|
// Returns 1 if the call succeeded, 0 otherwise.
|
||||||
|
//
|
||||||
|
import "DPI-C" context function int uvm_hdl_deposit(string path, uvm_hdl_data_t value);
|
||||||
|
|
||||||
|
|
||||||
|
// Function -- NODOCS -- uvm_hdl_force
|
||||||
|
//
|
||||||
|
// Forces the ~value~ on the given ~path~. Returns 1 if the call succeeded, 0 otherwise.
|
||||||
|
//
|
||||||
|
import "DPI-C" context function int uvm_hdl_force(string path, uvm_hdl_data_t value);
|
||||||
|
|
||||||
|
|
||||||
|
// Function -- NODOCS -- uvm_hdl_force_time
|
||||||
|
//
|
||||||
|
// Forces the ~value~ on the given ~path~ for the specified amount of ~force_time~.
|
||||||
|
// If ~force_time~ is 0, <uvm_hdl_deposit> is called.
|
||||||
|
// Returns 1 if the call succeeded, 0 otherwise.
|
||||||
|
//
|
||||||
|
task uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time = 0);
|
||||||
|
if (force_time == 0) begin
|
||||||
|
void'(uvm_hdl_deposit(path, value));
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
if (!uvm_hdl_force(path, value)) begin
|
||||||
|
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
#force_time;
|
||||||
|
void'(uvm_hdl_release_and_read(path, value));
|
||||||
|
endtask
|
||||||
|
|
||||||
|
|
||||||
|
// Function -- NODOCS -- uvm_hdl_release_and_read
|
||||||
|
//
|
||||||
|
// Releases a value previously set with <uvm_hdl_force>.
|
||||||
|
// Returns 1 if the call succeeded, 0 otherwise. ~value~ is set to
|
||||||
|
// the HDL value after the release. For 'reg', the value will still be
|
||||||
|
// the forced value until it has been procedurally reassigned. For 'wire',
|
||||||
|
// the value will change immediately to the resolved value of its
|
||||||
|
// continuous drivers, if any. If none, its value remains as forced until
|
||||||
|
// the next direct assignment.
|
||||||
|
//
|
||||||
|
import "DPI-C" context function int uvm_hdl_release_and_read(string path, inout uvm_hdl_data_t value);
|
||||||
|
|
||||||
|
|
||||||
|
// Function -- NODOCS -- uvm_hdl_release
|
||||||
|
//
|
||||||
|
// Releases a value previously set with <uvm_hdl_force>.
|
||||||
|
// Returns 1 if the call succeeded, 0 otherwise.
|
||||||
|
//
|
||||||
|
import "DPI-C" context function int uvm_hdl_release(string path);
|
||||||
|
|
||||||
|
|
||||||
|
// Function -- NODOCS -- uvm_hdl_read()
|
||||||
|
//
|
||||||
|
// Gets the value at the given ~path~.
|
||||||
|
// Returns 1 if the call succeeded, 0 otherwise.
|
||||||
|
//
|
||||||
|
import "DPI-C" context function int uvm_hdl_read(string path, output uvm_hdl_data_t value);
|
||||||
|
|
||||||
|
`else
|
||||||
|
|
||||||
|
function int uvm_hdl_check_path(string path);
|
||||||
|
uvm_report_fatal("UVM_HDL_CHECK_PATH",
|
||||||
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
return 0;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int uvm_hdl_deposit(string path, uvm_hdl_data_t value);
|
||||||
|
uvm_report_fatal("UVM_HDL_DEPOSIT",
|
||||||
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
return 0;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int uvm_hdl_force(string path, uvm_hdl_data_t value);
|
||||||
|
uvm_report_fatal("UVM_HDL_FORCE",
|
||||||
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
return 0;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
task uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time=0);
|
||||||
|
uvm_report_fatal("UVM_HDL_FORCE_TIME",
|
||||||
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
endtask
|
||||||
|
|
||||||
|
function int uvm_hdl_release(string path);
|
||||||
|
uvm_report_fatal("UVM_HDL_RELEASE",
|
||||||
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
return 0;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int uvm_hdl_read(string path, output uvm_hdl_data_t value);
|
||||||
|
uvm_report_fatal("UVM_HDL_READ",
|
||||||
|
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
return 0;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
@ -0,0 +1,678 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2023-2024 Intel Corporation
|
||||||
|
// Copyright 2023-2024 NVIDIA Corporation
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_hdl_polling.c $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sv_vpi_user.h"
|
||||||
|
#include "svdpi.h"
|
||||||
|
#include "uvm_dpi.h"
|
||||||
|
|
||||||
|
// Everyone still supports deprecated function vpi_free_object,
|
||||||
|
// but VCS doesn't yet support vpi_release_handle, which supersedes it
|
||||||
|
#define vpi_release_handle vpi_free_object
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// DPI import and export prototypes
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// DPI import ____ uvm_polling_create
|
||||||
|
//
|
||||||
|
// Create an access hook on the signal whose absolute pathname is ~name~.
|
||||||
|
// Use ~sv_key~ as the key shared between SV and C that will be used as
|
||||||
|
// the unique identifier for the created probe object.
|
||||||
|
// This function returns a pointer to a hook_record structure (see
|
||||||
|
// below), which is returned from C as void* and passed to SV as
|
||||||
|
// a "chandle". It should be saved for use in future operations
|
||||||
|
// on this signal. In practice the SV code will do this by maintaining
|
||||||
|
// an array of chandle indexed by their unique sv_key.
|
||||||
|
// An access hook freshly created by this function has no properties,
|
||||||
|
// i.e. it does nothing. To make the access hook useful, it must be
|
||||||
|
// enabled by a suitable call to uvm_polling_set_enable_callback (see below).
|
||||||
|
//
|
||||||
|
extern void * uvm_polling_create(char * name, int sv_key);
|
||||||
|
|
||||||
|
|
||||||
|
// DPI import ____ uvm_polling_set_enable_callback
|
||||||
|
//
|
||||||
|
// Enable or disable value-changed callback on the signal referenced
|
||||||
|
// by p_hook_record ~hnd~. If ~enable~ is true (non-zero), value-change
|
||||||
|
// monitoring is enabled for the signal. If ~enable~ is false (zero),
|
||||||
|
// it is disabled. If monitoring is already enabled and this function
|
||||||
|
// is called with ~enable~ true, the function has no effect. Similarly,
|
||||||
|
// if monitoring is disabled and the function is called with ~enable~
|
||||||
|
// false, it has no effect.
|
||||||
|
//
|
||||||
|
extern void uvm_polling_set_enable_callback(void * hnd, int enable);
|
||||||
|
|
||||||
|
|
||||||
|
// DPI import ____ uvm_polling_get_callback_enable
|
||||||
|
//
|
||||||
|
// Find the current enabled/disabled state of value-change callback
|
||||||
|
// on the signal accessed by the hook record referenced by ~hnd~.
|
||||||
|
// Returns 0 (disabled) or 1 (enabled).
|
||||||
|
//
|
||||||
|
extern int uvm_polling_get_callback_enable(void * hnd);
|
||||||
|
|
||||||
|
|
||||||
|
// DPI import ____ uvm_polling_getValue32
|
||||||
|
//
|
||||||
|
// Get the current value of the signal referenced by ~hnd~.
|
||||||
|
// The result is placed into the vector ~result~,
|
||||||
|
// which must be a 32-bit logic or equivalent type.
|
||||||
|
// ~chunk~ indicates which 32-bit slice of the signal
|
||||||
|
// is to be read: chunk=0 gets the least significant 32 bits,
|
||||||
|
// chunk=1 gets bits [63:32], and in general the function
|
||||||
|
// reads bits [32*chunk+:32]. If the specified chunk is completely
|
||||||
|
// beyond the end of the vector (i.e. the signal's size is less than
|
||||||
|
// 32*chunk bits) then the function yields an error. If the signal
|
||||||
|
// does not completely fill the chunk (for example, a 48-bit signal
|
||||||
|
// and chunk=1) then the result is zero-extended if the signal is
|
||||||
|
// unsigned, and sign-extended in the standard Verilog 4-state way
|
||||||
|
// if the signal is signed.
|
||||||
|
// Returns 1 if success, 0 if failure (bad handle, chunk out-of-bounds).
|
||||||
|
//
|
||||||
|
extern int uvm_polling_getValue32(void * hnd, svLogicVecVal *result, int chunk);
|
||||||
|
|
||||||
|
|
||||||
|
// DPI import _______________________________________ uvm_polling_getSize
|
||||||
|
//
|
||||||
|
// Get the number of bits in the signal referenced by ~hnd~.
|
||||||
|
// Returns zero if the handle is bad.
|
||||||
|
//
|
||||||
|
extern int uvm_polling_getSize(void * hnd);
|
||||||
|
|
||||||
|
|
||||||
|
// DPI import _____________________________________ uvm_polling_getSigned
|
||||||
|
//
|
||||||
|
// Get a flag indicating whether the signal referenced by ~hnd~
|
||||||
|
// is signed (0=unsigned, 1=signed).
|
||||||
|
//
|
||||||
|
extern int uvm_polling_getSigned(void * hnd); // 1=signed, 0=unsigned
|
||||||
|
|
||||||
|
|
||||||
|
// DPI import _______________________________ uvm_polling_setup_notifier
|
||||||
|
//
|
||||||
|
// Here's how we get the value change information back in to SV.
|
||||||
|
// First we pass the name of a single-bit signal to this function.
|
||||||
|
// That signal will be toggled by the VPI whenever it requires
|
||||||
|
// attention from SV because one of the probed signals has changed.
|
||||||
|
//
|
||||||
|
extern int uvm_polling_setup_notifier(char * fullname);
|
||||||
|
|
||||||
|
|
||||||
|
// DPI import ____ uvm_polling_process_changelist
|
||||||
|
//
|
||||||
|
// When the SV notifier signal is toggled, the SV code must immediately
|
||||||
|
// call this function. It will service all pending value-change events,
|
||||||
|
// notifying each affected probe object in turn by calling exported
|
||||||
|
// function uvm_polling_value_change_notify for that signal.
|
||||||
|
//
|
||||||
|
extern void uvm_polling_process_changelist();
|
||||||
|
|
||||||
|
|
||||||
|
// DPI export ____ uvm_polling_value_change_notify
|
||||||
|
//
|
||||||
|
// uvm_polling_process_changelist() calls this DPI export function
|
||||||
|
// once for each probed signal that has a pending value-change event.
|
||||||
|
// It uses a unique int key, rather than the signal's vpi_handle
|
||||||
|
// reference, to work around a tool limitation (no associative array
|
||||||
|
// indexed by chandle).
|
||||||
|
//
|
||||||
|
extern void uvm_polling_value_change_notify(int sv_key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Typedefs and private data used by the C functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// The following struct is used to hold information about a
|
||||||
|
// probed signal. Various features of the signal are cached
|
||||||
|
// here, to avoid making repeated VPI accesses to discover this
|
||||||
|
// information. The structure sometimes appears on a linked list
|
||||||
|
// of signals that need to be serviced (the changeList), and
|
||||||
|
// struct members to support that linked list are also included.
|
||||||
|
//
|
||||||
|
typedef struct t_hook_record {
|
||||||
|
struct t_hook_record *allHooks_link; // linked list pointer - all records
|
||||||
|
struct t_hook_record *changeList_link; // linked list pointer - records awaiting processing
|
||||||
|
int on_changeList; // 1 if we're on the list, 0 if not
|
||||||
|
struct t_hook_record *check; // copy of self-pointer, for safety
|
||||||
|
vpiHandle obj; // reference to the monitored signal
|
||||||
|
int sv_key; // unique key to help SV find this
|
||||||
|
vpiHandle cb; // VPI value-change callback object
|
||||||
|
int size; // number of bits in the signal
|
||||||
|
int isSigned; // is the signal signed?
|
||||||
|
PLI_UINT32 top_mask; // word-mask for most significant 32 bits
|
||||||
|
PLI_UINT32 top_msb; // MSB position within that word
|
||||||
|
} s_hook_record, *p_hook_record;
|
||||||
|
|
||||||
|
// A single list of hook_records that have value changes yet to be handled
|
||||||
|
static p_hook_record changeList = NULL;
|
||||||
|
|
||||||
|
// A single list of all hook_records, for use when deallocating memory
|
||||||
|
static p_hook_record allHooks = NULL;
|
||||||
|
|
||||||
|
// VPI handle to the single bit that is toggled to notify SV of pending
|
||||||
|
// value-changes that require service
|
||||||
|
static vpiHandle notifier = NULL;
|
||||||
|
|
||||||
|
// VPI handle to the simulation reset callback
|
||||||
|
static vpiHandle reset_callback = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Static (file-local) helper functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Report an error in a consistent way. This function should be used when
|
||||||
|
// control will be returned to SV with an error indication; the SV code will
|
||||||
|
// then display a more comprehensive error diagnostic.
|
||||||
|
//
|
||||||
|
static void uvm_polling_report_error(const char *message) {
|
||||||
|
m_uvm_report_dpi(M_UVM_ERROR,
|
||||||
|
(char*) "UVM/DPI/HDL_POLLING",
|
||||||
|
(char*) message,
|
||||||
|
M_UVM_NONE,
|
||||||
|
(char*)__FILE__,
|
||||||
|
__LINE__);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uvm_polling_report_fatal(const char *message) {
|
||||||
|
m_uvm_report_dpi(M_UVM_FATAL,
|
||||||
|
(char*) "UVM/DPI/HDL_POLLING",
|
||||||
|
(char*) message,
|
||||||
|
M_UVM_NONE,
|
||||||
|
(char*)__FILE__,
|
||||||
|
__LINE__);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uvm_polling_report_info(const char *message) {
|
||||||
|
m_uvm_report_dpi(M_UVM_INFO,
|
||||||
|
(char*) "UVM/DPI/HDL_POLLING",
|
||||||
|
(char*) message,
|
||||||
|
M_UVM_MEDIUM,
|
||||||
|
(char*)__FILE__,
|
||||||
|
__LINE__);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Interrupt the simulation because of an error.
|
||||||
|
// After an error, a user can continue from the stop using
|
||||||
|
// simulator command-line functionality. This may help with
|
||||||
|
// debugging by providing additional trace information, but
|
||||||
|
// behaviour of the signal probe package is not guaranteed
|
||||||
|
// after any error.
|
||||||
|
//
|
||||||
|
static void uvm_polling_stop_on_error(const char *message) {
|
||||||
|
if (message != NULL) {
|
||||||
|
uvm_polling_report_fatal(message);
|
||||||
|
}
|
||||||
|
// vpi_control(vpiStop, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get and initialize a new s_hook_record from the heap.
|
||||||
|
// Add it to the allHooks structure to support memory
|
||||||
|
// deallocation on simulator restart.
|
||||||
|
//
|
||||||
|
static p_hook_record allocate_hook_record() {
|
||||||
|
p_hook_record rec = (p_hook_record)malloc(sizeof(s_hook_record));
|
||||||
|
if (rec == NULL) {
|
||||||
|
uvm_polling_stop_on_error("allocate_hook_record: no memory");
|
||||||
|
} else {
|
||||||
|
rec->on_changeList = 0;
|
||||||
|
rec->check = rec;
|
||||||
|
rec->obj = NULL;
|
||||||
|
rec->allHooks_link = allHooks;
|
||||||
|
allHooks = rec;
|
||||||
|
}
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deallocate a single hook_record structure.
|
||||||
|
// Destroy its internal referenced VPI objects before deallocation.
|
||||||
|
//
|
||||||
|
static void free_hook_record(p_hook_record rec) {
|
||||||
|
if (rec == NULL) return;
|
||||||
|
if (rec->cb != NULL) {
|
||||||
|
(void)vpi_remove_cb(rec->cb);
|
||||||
|
}
|
||||||
|
if (rec->obj != NULL) {
|
||||||
|
(void)vpi_release_handle(rec->obj);
|
||||||
|
}
|
||||||
|
free(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Deallocate all memory structures owned by this VPI application.
|
||||||
|
// This will typically be done by the VPI simulation restart callback.
|
||||||
|
// NOTE that the restart callback itself is NOT deallocated here,
|
||||||
|
// because this function is probably called from within that callback.
|
||||||
|
//
|
||||||
|
static void uvm_polling_free_mem_structures() {
|
||||||
|
if (notifier != NULL) {
|
||||||
|
(void)vpi_release_handle(notifier);
|
||||||
|
}
|
||||||
|
while (allHooks != NULL) {
|
||||||
|
p_hook_record rec = allHooks;
|
||||||
|
allHooks = rec->allHooks_link;
|
||||||
|
free_hook_record(rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get and remove the first (newest) entry from the
|
||||||
|
// list of signals with unserviced value changes.
|
||||||
|
// Return a reference to that entry.
|
||||||
|
//
|
||||||
|
static p_hook_record uvm_polling_get_newest_entry() {
|
||||||
|
p_hook_record rec;
|
||||||
|
rec = changeList;
|
||||||
|
if (rec != NULL) {
|
||||||
|
changeList = rec->changeList_link;
|
||||||
|
rec->on_changeList = 0;
|
||||||
|
}
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add a signal to the list of unserviced value changes.
|
||||||
|
// But if the signal is already on that list, don't
|
||||||
|
// try to add it again.
|
||||||
|
//
|
||||||
|
static void changeList_pushIfNeeded(p_hook_record rec) {
|
||||||
|
|
||||||
|
|
||||||
|
if (!rec->on_changeList) {
|
||||||
|
rec->on_changeList = 1;
|
||||||
|
|
||||||
|
rec->changeList_link = changeList;
|
||||||
|
changeList = rec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check to see whether a vpiType value represents
|
||||||
|
// an appropriate Verilog type (vector, reg etc) for probing.
|
||||||
|
// Basically we are checking for an integral type, but
|
||||||
|
// there does not seem to be any VPI property for that,
|
||||||
|
// so instead we must exhaustively list all known
|
||||||
|
// integral types.
|
||||||
|
//
|
||||||
|
static int isVerilogType(PLI_INT32 vpi_type) {
|
||||||
|
switch (vpi_type) {
|
||||||
|
case vpiNet:
|
||||||
|
case vpiNetBit:
|
||||||
|
case vpiReg:
|
||||||
|
case vpiRegBit:
|
||||||
|
case vpiPartSelect:
|
||||||
|
case vpiBitSelect:
|
||||||
|
case vpiBitVar:
|
||||||
|
case vpiEnumVar:
|
||||||
|
case vpiIntVar:
|
||||||
|
case vpiLongIntVar:
|
||||||
|
case vpiShortIntVar:
|
||||||
|
case vpiIntegerVar:
|
||||||
|
case vpiByteVar:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a handle value obtained from an untrusted source,
|
||||||
|
// cast it to a p_hook_record and do some sanity checks.
|
||||||
|
//
|
||||||
|
static p_hook_record chandle_to_hook(void * hnd) {
|
||||||
|
p_hook_record hook = (p_hook_record) hnd;
|
||||||
|
if ((hook != NULL) && (hook->check == hook)) {
|
||||||
|
return hook;
|
||||||
|
} else {
|
||||||
|
uvm_polling_stop_on_error("Bad chandle argument is not a valid created hook");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Static (file-local) helper functions related to simulator action callbacks
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// The callback function used to deal with simulator actions.
|
||||||
|
// Currently it handles only cbStartOfReset, which is caused by
|
||||||
|
// an interactive restart of the simulation back to time zero.
|
||||||
|
static PLI_INT32 uvm_polling_simulator_callback(p_cb_data cb_data_p) {
|
||||||
|
|
||||||
|
const char* str = "uvm_polling_simulator_callback: cbStartOfReset, deallocate all internal data\n\n";
|
||||||
|
char buffer[strlen(str) + 1];
|
||||||
|
|
||||||
|
switch (cb_data_p->reason) {
|
||||||
|
|
||||||
|
case cbStartOfReset :
|
||||||
|
uvm_polling_report_info(&buffer[0]);
|
||||||
|
uvm_polling_free_mem_structures();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up reset/restart callbacks, removing any old callback if necessary
|
||||||
|
static void uvm_polling_reset_callback() {
|
||||||
|
s_cb_data cb_data;
|
||||||
|
// Time and value structs should not be needed, but IUS requires them
|
||||||
|
s_vpi_time time_s;
|
||||||
|
s_vpi_value value_s;
|
||||||
|
|
||||||
|
// Remove any existing callback
|
||||||
|
if (reset_callback != NULL) {
|
||||||
|
(void)vpi_remove_cb(reset_callback);
|
||||||
|
}
|
||||||
|
// Set up the new callback
|
||||||
|
cb_data.cb_rtn = &uvm_polling_simulator_callback;
|
||||||
|
cb_data.obj = NULL;
|
||||||
|
cb_data.user_data = NULL;
|
||||||
|
cb_data.time = &time_s;
|
||||||
|
time_s.type = vpiSuppressTime;
|
||||||
|
cb_data.value = &value_s;
|
||||||
|
value_s.format = vpiSuppressVal;
|
||||||
|
cb_data.reason = cbStartOfReset;
|
||||||
|
reset_callback = vpi_register_cb(&cb_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Static (file-local) helper functions related to value-change callbacks
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Toggle the notifier signal
|
||||||
|
static PLI_INT32 uvm_polling_toggle_notifier() {
|
||||||
|
if (notifier == NULL) {
|
||||||
|
// Throw an error and return FALSE if there's no notifier set up.
|
||||||
|
uvm_polling_stop_on_error("Value-change callback but no active notifier bit");
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
s_vpi_value value_s;
|
||||||
|
value_s.format = vpiScalarVal;
|
||||||
|
vpi_get_value(notifier, &value_s);
|
||||||
|
value_s.value.scalar = (value_s.value.scalar == vpi1)? vpi0: vpi1;
|
||||||
|
vpi_put_value(notifier, &value_s, NULL, vpiNoDelay);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the function that is provided to the VPI as a value-change callback
|
||||||
|
// handler. There is only one entry point. Each callback's user_data field
|
||||||
|
// holds a pointer to the corrresponding signal's hook_record structure.
|
||||||
|
//
|
||||||
|
static PLI_INT32 uvm_polling_value_change_callback(p_cb_data cb_data) {
|
||||||
|
p_hook_record hook = chandle_to_hook(cb_data->user_data);
|
||||||
|
if (hook == NULL) return 0;
|
||||||
|
// At any given time, the first signal that suffers a
|
||||||
|
// value-change callback will cause the notifier signal
|
||||||
|
// to be toggled. Subsequent callbacks don't toggle the
|
||||||
|
// notifier again, as that might prevent it from being
|
||||||
|
// detected by SV "@notifier". Instead, they are just
|
||||||
|
// added to the changeList. When SV eventually responds
|
||||||
|
// to the notifier change, it causes the changeList to be
|
||||||
|
// scanned, servicing each signal in turn and emptying
|
||||||
|
// the changeList. The next value change will then
|
||||||
|
// give rise to another notification. This mechanism
|
||||||
|
// avoids any risk of races whereby a notification might
|
||||||
|
// be missed.
|
||||||
|
// We detect "first signal" by noting whether
|
||||||
|
// the changeList is currently empty.
|
||||||
|
int require_notification = (changeList == NULL);
|
||||||
|
// Put this object on the changeList, if it isn't already.
|
||||||
|
changeList_pushIfNeeded(hook);
|
||||||
|
if (require_notification) {
|
||||||
|
// Toggle the notifier bit.
|
||||||
|
int ok = uvm_polling_toggle_notifier();
|
||||||
|
return ok;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sensitise to a signal by placing a value-change callback on it.
|
||||||
|
// Set up the callback so that it does not collect the signal's
|
||||||
|
// value or the callback time (reduces overhead). Keep a copy
|
||||||
|
// of the callback handle in the signal's hook record, to simplify
|
||||||
|
// later removal of the callback.
|
||||||
|
//
|
||||||
|
static void enable_cb(p_hook_record hook) {
|
||||||
|
if (hook->cb == NULL) {
|
||||||
|
s_cb_data cb_data;
|
||||||
|
s_vpi_time time_s;
|
||||||
|
s_vpi_value value_s;
|
||||||
|
|
||||||
|
cb_data.reason = cbValueChange;
|
||||||
|
cb_data.cb_rtn = &uvm_polling_value_change_callback;
|
||||||
|
cb_data.obj = hook->obj;
|
||||||
|
cb_data.time = &time_s;
|
||||||
|
time_s.type = vpiSuppressTime;
|
||||||
|
cb_data.value = &value_s;
|
||||||
|
value_s.format = vpiSuppressVal;
|
||||||
|
cb_data.user_data = (PLI_BYTE8*)hook;
|
||||||
|
|
||||||
|
hook->cb = vpi_register_cb(&cb_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable value-change callbacks on a signal by removing
|
||||||
|
// its value-change callback completely.
|
||||||
|
//
|
||||||
|
static void disable_cb(p_hook_record hook) {
|
||||||
|
if (hook->cb != NULL) {
|
||||||
|
(void) vpi_remove_cb(hook->cb);
|
||||||
|
hook->cb = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// SV DPI import implementations
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
void * uvm_polling_create(char *name, int sv_key) {
|
||||||
|
vpiHandle obj;
|
||||||
|
p_hook_record rec;
|
||||||
|
int objType;
|
||||||
|
|
||||||
|
const char* str1 = "Unable to create probe on '%s' with key %d, type=%d\n" ;
|
||||||
|
const char* str2 = "uvm_hdl_polling_create(\"%s\"): object is not a variable or net of integral type\n";
|
||||||
|
char buffer0[strlen(str1) + strlen(name) + 32];
|
||||||
|
char buffer1[strlen(str2) + strlen(name) + 32];
|
||||||
|
// Locate the chosen object
|
||||||
|
obj = vpi_handle_by_name(name, NULL);
|
||||||
|
// If there was a problem, return NULL to report it.
|
||||||
|
if (obj == NULL) {
|
||||||
|
const char* str = "uvm_polling_create: create(\"%s\") could not locate requested signal\n";
|
||||||
|
char buffer[strlen(str) + strlen(name)];
|
||||||
|
sprintf(buffer,str,name);
|
||||||
|
uvm_polling_report_info(&buffer[0]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Check the object is indeed a vector variable or net; error if not.
|
||||||
|
objType = vpi_get(vpiType, obj);
|
||||||
|
if (!isVerilogType(objType)) {
|
||||||
|
sprintf(buffer0, str2, name, sv_key, objType);
|
||||||
|
sprintf(buffer1, str1, name);
|
||||||
|
uvm_polling_report_info(&buffer0[0]);
|
||||||
|
uvm_polling_report_info(&buffer1[0]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Obtain a clean object record from free memory
|
||||||
|
rec = allocate_hook_record();
|
||||||
|
// Populate it
|
||||||
|
rec->obj = obj;
|
||||||
|
rec->isSigned = vpi_get(vpiSigned, obj);
|
||||||
|
rec->size = vpi_get(vpiSize, obj);
|
||||||
|
rec->sv_key = sv_key;
|
||||||
|
rec->cb = NULL;
|
||||||
|
rec->top_msb = 1U << ((rec->size-1) % 32);
|
||||||
|
rec->top_mask = 2U * rec->top_msb - 1U;
|
||||||
|
|
||||||
|
return (void *)rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Enable or disable value-change callback on the chosen signal.
|
||||||
|
//
|
||||||
|
void uvm_polling_set_enable_callback(void * hnd, int enable) {
|
||||||
|
p_hook_record hook = chandle_to_hook(hnd);
|
||||||
|
if (hook == NULL) return;
|
||||||
|
if (enable) {
|
||||||
|
enable_cb(hook);
|
||||||
|
} else {
|
||||||
|
disable_cb(hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enquiry: is value-change callback enabled on the chosen signal?
|
||||||
|
//
|
||||||
|
int uvm_polling_get_callback_enable(void * hnd) {
|
||||||
|
p_hook_record hook = chandle_to_hook(hnd);
|
||||||
|
if (hook == NULL) return 0;
|
||||||
|
return (hook->cb != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get up to 32 bits of the signal's value.
|
||||||
|
//
|
||||||
|
int uvm_polling_getValue32(void * hnd, svLogicVecVal *result, int chunk) {
|
||||||
|
p_hook_record hook;
|
||||||
|
s_vpi_value value_s;
|
||||||
|
p_vpi_vecval vec_p;
|
||||||
|
int chunk_lsb = chunk*32;
|
||||||
|
|
||||||
|
hook = chandle_to_hook(hnd);
|
||||||
|
|
||||||
|
if (hook == NULL) {
|
||||||
|
uvm_polling_stop_on_error("uvm_polling_getValue32: bad handle");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (chunk<0) {
|
||||||
|
uvm_polling_report_error("uvm_polling_getValue32: negative chunk index");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (chunk_lsb >= hook->size) {
|
||||||
|
chunk = (hook->size-1)/32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the whole vector value from VPI
|
||||||
|
value_s.format = vpiVectorVal;
|
||||||
|
vpi_get_value(hook->obj, &value_s);
|
||||||
|
|
||||||
|
// Copy the relevant aval/bval bits into the output argument.
|
||||||
|
vec_p = value_s.value.vector;
|
||||||
|
*result = vec_p[chunk];
|
||||||
|
// Perform sign extension if appropriate.
|
||||||
|
if ((chunk_lsb + 32) > hook->size) {
|
||||||
|
// We're working on the most significant word, and it is not full.
|
||||||
|
result->aval &= hook->top_mask;
|
||||||
|
result->bval &= hook->top_mask;
|
||||||
|
if (hook->isSigned) {
|
||||||
|
if (result->bval & hook->top_msb) {
|
||||||
|
result->bval |= ~(hook->top_mask);
|
||||||
|
}
|
||||||
|
if (result->aval & hook->top_msb) {
|
||||||
|
result->aval |= ~(hook->top_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uvm_polling_getSize(void * hnd) {
|
||||||
|
p_hook_record hook = chandle_to_hook(hnd);
|
||||||
|
if (hook == NULL) return 0;
|
||||||
|
return hook->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uvm_polling_getSigned(void * hnd) {
|
||||||
|
p_hook_record hook = chandle_to_hook(hnd);
|
||||||
|
if (hook == NULL) return 0;
|
||||||
|
return hook->isSigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function must be called exactly once when the very first probe is created.
|
||||||
|
int uvm_polling_setup_notifier(char * fullname) {
|
||||||
|
vpiHandle obj;
|
||||||
|
|
||||||
|
// Locate the chosen notifier signal
|
||||||
|
obj = vpi_handle_by_name(fullname, NULL);
|
||||||
|
// If there was a problem, return NULL to report it.
|
||||||
|
if (obj == NULL) {
|
||||||
|
uvm_polling_report_error("uvm_polling_setup_notifier() could not locate requested signal");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Check the object is indeed a variable of type bit; error if not.
|
||||||
|
if (vpi_get(vpiType, obj) != vpiBitVar) {
|
||||||
|
uvm_polling_report_error("uvm_polling_setup_notifier: object is not a bit variable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
notifier = obj;
|
||||||
|
uvm_polling_reset_callback();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the changeList, calling back to SV to handle each item in turn
|
||||||
|
// as they are popped off the list. When done, the list will be empty.
|
||||||
|
void uvm_polling_process_changelist() {
|
||||||
|
while (changeList != NULL) {
|
||||||
|
p_hook_record rec = uvm_polling_get_newest_entry();
|
||||||
|
uvm_polling_value_change_notify(rec->sv_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsigned int uvm_hdl_signal_size(char* name)
|
||||||
|
{
|
||||||
|
const char* str = "uvm_hdl_signal_size : Cannot find name '%s'" ;
|
||||||
|
char buffer[strlen(str) + strlen(name)];
|
||||||
|
vpiHandle handle = vpi_handle_by_name(name, NULL);
|
||||||
|
if (handle != NULL) {
|
||||||
|
return vpi_get(vpiSize, handle);
|
||||||
|
} else {
|
||||||
|
uvm_polling_report_error(&buffer[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,342 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2007-2023 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2009-2011 Mentor Graphics Corporation
|
||||||
|
// Copyright 2013-2024 NVIDIA Corporation
|
||||||
|
// Copyright 2010-2011 Synopsys, Inc.
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File$
|
||||||
|
// $Rev$
|
||||||
|
// $Hash$
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "svdpi.h"
|
||||||
|
#include "vpi_user.h"
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.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_max_width();
|
||||||
|
|
||||||
|
// static print buffer
|
||||||
|
static char m_uvm_temp_print_buffer[1024];
|
||||||
|
|
||||||
|
// static print error
|
||||||
|
static void m_uvm_error(const char *id, const char *msg, ...) {
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, msg);
|
||||||
|
vsprintf(m_uvm_temp_print_buffer, msg, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
m_uvm_report_dpi(M_UVM_ERROR, (char *)id, &m_uvm_temp_print_buffer[0], M_UVM_NONE,
|
||||||
|
(char *)__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UVM HDL access C code.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This C code checks to see if there is PLI handle
|
||||||
|
* with a value set to define the maximum bit width.
|
||||||
|
*
|
||||||
|
* 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() {
|
||||||
|
if (!UVM_HDL_MAX_WIDTH) {
|
||||||
|
vpiHandle ms;
|
||||||
|
s_vpi_value value_s = {vpiIntVal, {0}};
|
||||||
|
ms = vpi_handle_by_name((PLI_BYTE8 *)"uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
|
||||||
|
if (ms == 0) {
|
||||||
|
UVM_HDL_MAX_WIDTH = 1024; /* If nothing else is defined, this is the DEFAULT */
|
||||||
|
} else {
|
||||||
|
vpi_get_value(ms, &value_s);
|
||||||
|
UVM_HDL_MAX_WIDTH = value_s.value.integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 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_left : decl_right;
|
||||||
|
decl_hi = (decl_left > decl_right) ? decl_left : decl_right;
|
||||||
|
if (*lo_ptr < decl_lo) return 0;
|
||||||
|
if (*hi_ptr > decl_hi) return 0;
|
||||||
|
*lo_ptr -= decl_lo;
|
||||||
|
*hi_ptr -= decl_lo;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a path, look the path name up using the PLI,
|
||||||
|
* and set it to 'value'.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
static int s_maxsize = -1;
|
||||||
|
|
||||||
|
if (flag == vpiForceFlag || flag == vpiReleaseFlag) {
|
||||||
|
// It appears other simulator interfaces likewise don't support this
|
||||||
|
m_uvm_error("UVM/DPI/VLOG_GET", "Unsupported: uvh_hdl_force/uvm_hdl_release on hdl path '%s'",
|
||||||
|
path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = uvm_hdl_handle_by_name_partsel(path, &is_partsel, &hi, &lo);
|
||||||
|
if (r == 0) {
|
||||||
|
m_uvm_error("UVM/DPI/HDL_SET",
|
||||||
|
"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 (s_maxsize == -1) s_maxsize = uvm_hdl_max_width();
|
||||||
|
size = vpi_get(vpiSize, r);
|
||||||
|
if (size > s_maxsize) {
|
||||||
|
m_uvm_error("UVM/DPI/VLOG_PUT",
|
||||||
|
"hdl path '%s' is %0d bits, but the maximum size is %0d. "
|
||||||
|
"You can increase the maximum via a compile-time flag: "
|
||||||
|
"+define+UVM_HDL_MAX_WIDTH=<value>",
|
||||||
|
path, size, s_maxsize);
|
||||||
|
vpi_release_handle(r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_s.format = vpiVectorVal;
|
||||||
|
vpi_get_value(r, &value_s);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
vpi_release_handle(r);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 s_maxsize = -1;
|
||||||
|
int i, size, chunks;
|
||||||
|
vpiHandle r;
|
||||||
|
s_vpi_value value_s;
|
||||||
|
int is_partsel, hi, lo;
|
||||||
|
|
||||||
|
r = uvm_hdl_handle_by_name_partsel(path, &is_partsel, &hi, &lo);
|
||||||
|
if (r == 0) {
|
||||||
|
m_uvm_error("UVM/DPI/VLOG_GET",
|
||||||
|
"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 (s_maxsize == -1) s_maxsize = uvm_hdl_max_width();
|
||||||
|
size = vpi_get(vpiSize, r);
|
||||||
|
if (size > s_maxsize) {
|
||||||
|
m_uvm_error("UVM/DPI/VLOG_GET",
|
||||||
|
"hdl path '%s' is %0d bits, but the maximum size is %0d. "
|
||||||
|
"You can increase the maximum via a compile-time flag: "
|
||||||
|
"+define+UVM_HDL_MAX_WIDTH=<value>",
|
||||||
|
path, size, s_maxsize);
|
||||||
|
vpi_release_handle(r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks = (size - 1) / 32 + 1;
|
||||||
|
|
||||||
|
value_s.format = vpiVectorVal;
|
||||||
|
vpi_get_value(r, &value_s);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
// vpi_printf((PLI_BYTE8 *)"uvm_hdl_get_vlog(%s,%0x)\n", path, value[0].aval);
|
||||||
|
vpi_release_handle(r);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a path, look the path name up using the PLI,
|
||||||
|
* but don't set or get. Just check.
|
||||||
|
*
|
||||||
|
* Return 0 if NOT found.
|
||||||
|
* Return 1 if found.
|
||||||
|
*/
|
||||||
|
int uvm_hdl_check_path(char *path) {
|
||||||
|
vpiHandle handle;
|
||||||
|
|
||||||
|
handle = vpi_handle_by_name(path, 0);
|
||||||
|
return (handle != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a path, look the path name up using the PLI
|
||||||
|
* or the FLI, and set it to 'value'.
|
||||||
|
*/
|
||||||
|
int uvm_hdl_deposit(char *path, p_vpi_vecval value) {
|
||||||
|
return uvm_hdl_set_vlog(path, value, vpiNoDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a path, look the path name up using the PLI
|
||||||
|
* or the FLI, and set it to 'value'.
|
||||||
|
*/
|
||||||
|
int uvm_hdl_force(char *path, p_vpi_vecval value) {
|
||||||
|
return uvm_hdl_set_vlog(path, value, vpiForceFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a path, look the path name up using the PLI
|
||||||
|
* or the FLI, and release it.
|
||||||
|
*/
|
||||||
|
int uvm_hdl_release_and_read(char *path, p_vpi_vecval value) {
|
||||||
|
return uvm_hdl_set_vlog(path, value, vpiReleaseFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2023 Intel Corporation
|
||||||
|
// Copyright 2023 NVIDIA Corporation
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_polling_dpi.svh $
|
||||||
|
// $Rev: 2024-01-16 12:31:36 -0800 $
|
||||||
|
// $Hash: 03eb4be614dec8e91a7f62d41cacff41c5f72ac5 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifndef UVM_DPI_POLLING_SVH
|
||||||
|
`define UVM_DPI_POLLING_SVH
|
||||||
|
`ifndef UVM_NO_DPI
|
||||||
|
import "DPI-C" context function chandle uvm_polling_create(input string name, input int sv_key);
|
||||||
|
|
||||||
|
// Set/get value-change callback enable on the chosen signal.
|
||||||
|
import "DPI-C" context function void uvm_polling_set_enable_callback(chandle hnd, int enable);
|
||||||
|
import "DPI-C" context function int uvm_polling_get_callback_enable(chandle hnd);
|
||||||
|
|
||||||
|
// Get the signal's value.
|
||||||
|
|
||||||
|
// Get the signal's static properties.
|
||||||
|
import "DPI-C" context function int uvm_polling_setup_notifier(string fullname);
|
||||||
|
import "DPI-C" context function void uvm_polling_process_changelist();
|
||||||
|
|
||||||
|
import "DPI-C" context function int uvm_hdl_signal_size(string path);
|
||||||
|
// import "DPI-C" context function void uvm_polling_free_mem_structures();
|
||||||
|
|
||||||
|
|
||||||
|
`else
|
||||||
|
// uvm_polling_create
|
||||||
|
function chandle uvm_polling_create(input string name, input int sv_key);
|
||||||
|
chandle ch;
|
||||||
|
uvm_report_fatal("UVM_HDL_POLLING",
|
||||||
|
$sformatf("VPI access is disabled. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
return ch;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// uvm_polling_set_enable_callback
|
||||||
|
function void uvm_polling_set_enable_callback(chandle hnd, int enable);
|
||||||
|
uvm_report_fatal("UVM_HDL_POLLING",
|
||||||
|
$sformatf("VPI access is disabled. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// uvm_polling_get_callback_enable
|
||||||
|
function int uvm_polling_get_callback_enable(chandle hnd);
|
||||||
|
uvm_report_fatal("UVM_HDL_POLLING",
|
||||||
|
$sformatf("VPI access is disabled. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
// uvm_polling_setup_notifier
|
||||||
|
function int uvm_polling_setup_notifier(string fullname);
|
||||||
|
uvm_report_fatal("UVM_HDL_POLLING",
|
||||||
|
$sformatf("VPI access is disabled. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// uvm_polling_process_changelist
|
||||||
|
function void uvm_polling_process_changelist();
|
||||||
|
uvm_report_fatal("UVM_HDL_POLLING",
|
||||||
|
$sformatf("VPI access is disabled. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function int uvm_hdl_signal_size(string path);
|
||||||
|
uvm_report_fatal("UVM_HDL_POLLING",
|
||||||
|
$sformatf("VPI access is disabled. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
@ -0,0 +1,368 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2010-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2023 Marvell International Ltd.
|
||||||
|
// Copyright 2007-2011 Mentor Graphics Corporation
|
||||||
|
// Copyright 2013-2024 NVIDIA Corporation
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_regex.cc $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "uvm_dpi.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
const char uvm_re_bracket_char = '/';
|
||||||
|
const char uvm_re_escape_char = '\\';
|
||||||
|
#define UVM_REGEX_MAX_LENGTH 2048
|
||||||
|
|
||||||
|
static const char* empty_regex="^$";
|
||||||
|
static const char* empty_regex_brackets = "/^$/";
|
||||||
|
|
||||||
|
typedef regex_t* regex_ptr;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// uvm_re_buffer
|
||||||
|
//
|
||||||
|
// Returns the current value of the uvm re buffer string. Note that
|
||||||
|
// the contents are only valid until the next call to a uvm_re_* method.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
char * uvm_re_buffer()
|
||||||
|
{
|
||||||
|
static char buffer[UVM_REGEX_MAX_LENGTH+4];
|
||||||
|
return &buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// uvm_re_deglobbed
|
||||||
|
//
|
||||||
|
// Convert a glob expression to a normal regular expression.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
const char * uvm_re_deglobbed(const char *glob, unsigned char with_brackets)
|
||||||
|
{
|
||||||
|
char* buffer = uvm_re_buffer();
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
// safety check. Glob should never be ~null~ since this is called
|
||||||
|
// from DPI. But we'll check anyway.
|
||||||
|
if(glob == NULL) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re called with glob=NULL");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t glob_len;
|
||||||
|
glob_len = strlen(glob);
|
||||||
|
|
||||||
|
// If either of the following cases appear then return an empty string
|
||||||
|
//
|
||||||
|
// 1. The glob string is empty (it has zero characters)
|
||||||
|
// 2. The glob string has a single character that is the
|
||||||
|
// uvm_re_bracket_char (i.e. "/")
|
||||||
|
if(glob_len == 0 || (glob_len == 1 && *glob == uvm_re_bracket_char)) {
|
||||||
|
if (with_brackets) {
|
||||||
|
return empty_regex_brackets;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return empty_regex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If bracketed with the /glob/, then it's already a regex
|
||||||
|
if (glob[0] == uvm_re_bracket_char && glob[glob_len-1] == uvm_re_bracket_char) {
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re() glob exceeds max length (%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (with_brackets) {
|
||||||
|
strcpy(buffer,glob);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strncpy(buffer, &glob[1], glob_len-2);
|
||||||
|
buffer[glob_len-2] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Convert the glob to a true regular expression (Posix syntax)
|
||||||
|
size_t iter;
|
||||||
|
iter = 0;
|
||||||
|
|
||||||
|
// Add the opening bracket
|
||||||
|
if (with_brackets) {
|
||||||
|
glob_len += 1;
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re glob expansion exceeds max length (%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[iter++] = uvm_re_bracket_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^ goes at the beginning...
|
||||||
|
if (*glob != '^') {
|
||||||
|
glob_len += 1;
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re glob expansion exceeds max length (%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[iter++] = '^';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that this for loop auto-terminates when '*p' is \0
|
||||||
|
for(p = glob; *p; p++) {
|
||||||
|
// Replace the glob metacharacters with corresponding regular
|
||||||
|
// expression metacharacters.
|
||||||
|
switch(*p)
|
||||||
|
{
|
||||||
|
// '.' Expansion
|
||||||
|
case '*':
|
||||||
|
case '+':
|
||||||
|
glob_len += 2;
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re() expansion exceeds max length(%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[iter++] = '.';
|
||||||
|
buffer[iter++] = *p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Escape Expansion
|
||||||
|
case '.':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
glob_len += 2;
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re() expansion exceeds max length(%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[iter++] = uvm_re_escape_char;
|
||||||
|
buffer[iter++] = *p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// '?' --> '.'
|
||||||
|
case '?':
|
||||||
|
buffer[iter++] = '.';
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Default (copy char)
|
||||||
|
default:
|
||||||
|
buffer[iter++] = *p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Let's check to see if the regular expression is bounded by ^ at
|
||||||
|
// the beginning and $ at the end. If not, add those characters in
|
||||||
|
// the appropriate position.
|
||||||
|
|
||||||
|
if (buffer[iter-1] != '$') {
|
||||||
|
glob_len += 1;
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re glob expansion exceeds max length (%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[iter++] = '$';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (with_brackets) {
|
||||||
|
glob_len += 1;
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re glob expansion exceeds max length (%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[iter++] = uvm_re_bracket_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
glob_len += 1;
|
||||||
|
if (glob_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_glob_to_re glob expansion exceeds max length (%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[iter++] = '\0';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// vpi_printf("uvm_re_deglobbed(%s, %0d)\n-->%s\n", glob, with_brackets, buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// uvm_re_free
|
||||||
|
//
|
||||||
|
// Frees a previously compiled regular expression.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void uvm_re_free(regex_ptr rexp)
|
||||||
|
{
|
||||||
|
if (rexp != NULL) {
|
||||||
|
regfree(rexp);
|
||||||
|
free(rexp);
|
||||||
|
}
|
||||||
|
// vpi_printf("uvm_re_free(%p)\n", rexp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// uvm_re_comp
|
||||||
|
//
|
||||||
|
// Compiles a regular expression and returns pointer to the compiled
|
||||||
|
// expression. A return value of NULL indicates that there was
|
||||||
|
// an error during compilation, and the error information is available
|
||||||
|
// via uvm_re_err.
|
||||||
|
//
|
||||||
|
// Note that the regular expression is on the heap, and must be freed
|
||||||
|
// by the caller.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
regex_ptr uvm_re_comp(const char* re, unsigned char deglob)
|
||||||
|
{
|
||||||
|
|
||||||
|
// vpi_printf("uvm_re_comp(%s)\n", re);
|
||||||
|
char* buffer = uvm_re_buffer();
|
||||||
|
|
||||||
|
// Optionally de-globify regular expression
|
||||||
|
const char* deglobbed;
|
||||||
|
if (deglob) {
|
||||||
|
deglobbed = uvm_re_deglobbed(re, false /* no brackets */);
|
||||||
|
} else {
|
||||||
|
// No glob, need to copy to buffer manually
|
||||||
|
size_t re_len;
|
||||||
|
re_len = strlen(re);
|
||||||
|
if (re_len > UVM_REGEX_MAX_LENGTH) {
|
||||||
|
sprintf(buffer, "uvm_re_comp() re exceeds max length (%0d)", UVM_REGEX_MAX_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Strip brackets if necessary
|
||||||
|
if (re[0] == uvm_re_bracket_char && re[re_len-1] == uvm_re_bracket_char) {
|
||||||
|
strncpy(buffer, &re[1], re_len-2);
|
||||||
|
buffer[re_len-2] = '\0';
|
||||||
|
deglobbed = buffer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deglobbed = re;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safety check. Args should never be ~null~ since this is called
|
||||||
|
// from DPI, but we'll check anyways.
|
||||||
|
if (deglobbed == NULL) {
|
||||||
|
// uvm_glob_to_re already set the debug buffer
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// deglobbed is a const pointer to uvm_re_buffer, so never free it.
|
||||||
|
|
||||||
|
regex_ptr rexp;
|
||||||
|
rexp = (regex_ptr)malloc(sizeof(regex_t));
|
||||||
|
if (rexp == NULL) {
|
||||||
|
sprintf(buffer, "uvm_re_comp: internal memory allocation error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err;
|
||||||
|
err = regcomp(rexp, deglobbed, REG_EXTENDED);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
regerror(err, rexp, buffer, UVM_REGEX_MAX_LENGTH-1);
|
||||||
|
uvm_re_free(rexp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vpi_printf("uvm_re_comp(%s)\n-->%p\n", buffer, rexp);
|
||||||
|
return rexp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// uvm_re_exec
|
||||||
|
//
|
||||||
|
// Match a string to a pre-compiled regular expression.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int uvm_re_exec(regex_ptr rexp, const char * str) {
|
||||||
|
// Safety check.
|
||||||
|
if (rexp == NULL) {
|
||||||
|
sprintf(uvm_re_buffer(), "uvm_re_exec: NULL rexp");
|
||||||
|
return REG_NOMATCH;
|
||||||
|
}
|
||||||
|
if (str == NULL) {
|
||||||
|
sprintf(uvm_re_buffer(), "uvm_re_exec: NULL str");
|
||||||
|
return REG_NOMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int retval;
|
||||||
|
retval = regexec(rexp, str, 0, NULL, 0);
|
||||||
|
// vpi_printf("uvm_re_exec(%p, %s)\n-->%0d\n", rexp, str, retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// uvm_re_compexec
|
||||||
|
//
|
||||||
|
// Compiles a regular expression and executes it in a single operation.
|
||||||
|
// Reduces the number of necessary language boundary crossings from
|
||||||
|
// 2 to 1.
|
||||||
|
//
|
||||||
|
// Note that the regular expression is on the heap, and must be freed
|
||||||
|
// by the caller.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
regex_ptr uvm_re_compexec(const char* re, const char* str, unsigned char deglob, int* exec_ret)
|
||||||
|
{
|
||||||
|
regex_ptr rexp;
|
||||||
|
rexp = uvm_re_comp(re, deglob);
|
||||||
|
if (rexp != NULL) {
|
||||||
|
// Successful compile
|
||||||
|
*exec_ret = uvm_re_exec(rexp, str);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*exec_ret = REG_NOMATCH;
|
||||||
|
}
|
||||||
|
// vpi_printf("uvm_re_compexec(%s,%s,%0d)\n-->%p\n", re, str, *exec_ret, rexp);
|
||||||
|
return rexp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// uvm_re_compexecfree
|
||||||
|
//
|
||||||
|
// Compiles a regular expression, executes and frees it in a single operation.
|
||||||
|
// Reduces the number of necessary language boundary crossings from
|
||||||
|
// 3 to 1.
|
||||||
|
//
|
||||||
|
// Returns 1 on successful execution, 0 on failure.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned char uvm_re_compexecfree(const char* re, const char* str, unsigned char deglob, int* exec_ret)
|
||||||
|
{
|
||||||
|
regex_ptr rexp;
|
||||||
|
rexp = uvm_re_compexec(re, str, deglob, exec_ret);
|
||||||
|
unsigned char success = (rexp != NULL);
|
||||||
|
if (success) {
|
||||||
|
uvm_re_free(rexp);
|
||||||
|
}
|
||||||
|
// vpi_printf("uvm_re_compexecfree(%s,%s,%0d)\n-->%0d\n", re, str, *exec_ret, success);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Copyright 2010-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2010-2012 Mentor Graphics Corporation
|
||||||
|
// Copyright 2020-2024 NVIDIA Corporation
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_regex.svh $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef UVM_REGEX_NO_DPI
|
||||||
|
import "DPI-C" function string uvm_re_deglobbed(string glob, bit with_brackets);
|
||||||
|
import "DPI-C" function string uvm_re_buffer();
|
||||||
|
import "DPI-C" function void uvm_re_free(chandle rexp);
|
||||||
|
import "DPI-C" function chandle uvm_re_comp(string re, bit deglob);
|
||||||
|
import "DPI-C" function int uvm_re_exec(chandle rexp, string str);
|
||||||
|
import "DPI-C" function chandle uvm_re_compexec(string re, string str, bit deglob, output int exec_ret);
|
||||||
|
import "DPI-C" function bit uvm_re_compexecfree(string re, string str, bit deglob, output int exec_ret);
|
||||||
|
|
||||||
|
typedef class uvm_regex_cache;
|
||||||
|
|
||||||
|
// The uvm_re_match cache is disabled by default, to avoid
|
||||||
|
// potential issues with save-and-restore causing illegal c-side
|
||||||
|
// dereferencing. When enabled, uvm_re_match should be significantly
|
||||||
|
// faster.
|
||||||
|
`ifdef UVM_ENABLE_RE_MATCH_CACHE
|
||||||
|
function int uvm_re_match(string re, string str, bit deglob = 0);
|
||||||
|
uvm_regex_cache cache;
|
||||||
|
chandle cached[$];
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
cache = uvm_regex_cache::get_inst();
|
||||||
|
cached = cache.get(re);
|
||||||
|
if (cached.size()) begin
|
||||||
|
// Cache hit, use pre-compiled regex
|
||||||
|
retval = uvm_re_exec(cached[0], str);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
// Cache miss, compile and cache regex
|
||||||
|
chandle rexp;
|
||||||
|
rexp = uvm_re_compexec(re, str, deglob, retval);
|
||||||
|
if (rexp == null) begin
|
||||||
|
uvm_report_error("UVM/DPI/REGEX", uvm_re_buffer());
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
cache.put(re, rexp);
|
||||||
|
end
|
||||||
|
end // else: !if(cached.size())
|
||||||
|
return retval;
|
||||||
|
endfunction : uvm_re_match
|
||||||
|
|
||||||
|
`else // !`ifdef UVM_ENABLE_RE_MATCH_CACHE
|
||||||
|
|
||||||
|
function int uvm_re_match(string re, string str, bit deglob = 0);
|
||||||
|
int retval;
|
||||||
|
bit success;
|
||||||
|
success = uvm_re_compexecfree(re, str, deglob, retval);
|
||||||
|
if (!success) begin
|
||||||
|
uvm_report_error("UVM/DPI/REGEX", uvm_re_buffer());
|
||||||
|
end
|
||||||
|
return retval;
|
||||||
|
endfunction : uvm_re_match
|
||||||
|
|
||||||
|
`endif // !`ifdef UVM_ENABLE_RE_MATCH_CACHE
|
||||||
|
|
||||||
|
|
||||||
|
function string uvm_glob_to_re(string glob);
|
||||||
|
return uvm_re_deglobbed(glob, 1);
|
||||||
|
endfunction : uvm_glob_to_re
|
||||||
|
|
||||||
|
`else
|
||||||
|
|
||||||
|
// The Verilog only version does not match regular expressions,
|
||||||
|
// it only does glob style matching.
|
||||||
|
// NOTE: The deglob argument is unused in Verilog only mode,
|
||||||
|
// as it doesn't make any sense.
|
||||||
|
function int uvm_re_match(string re, string str, bit deglob = 0);
|
||||||
|
int e, es, s, ss;
|
||||||
|
string tmp;
|
||||||
|
e = 0; s = 0;
|
||||||
|
es = 0; ss = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if(re.len() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// The ^ used to be used to remove the implicit wildcard, but now we don't
|
||||||
|
// use implicit wildcard so this character is just stripped.
|
||||||
|
if(re[0] == "^")
|
||||||
|
re = re.substr(1, re.len()-1);
|
||||||
|
|
||||||
|
//This loop is only needed when the first character of the re may not
|
||||||
|
//be a *.
|
||||||
|
while (s != str.len() && re.getc(e) != "*") begin
|
||||||
|
if ((re.getc(e) != str.getc(s)) && (re.getc(e) != "?"))
|
||||||
|
return 1;
|
||||||
|
e++; s++;
|
||||||
|
end
|
||||||
|
|
||||||
|
while (s != str.len()) begin
|
||||||
|
if (re.getc(e) == "*") begin
|
||||||
|
e++;
|
||||||
|
if (e == re.len()) begin
|
||||||
|
return 0;
|
||||||
|
end
|
||||||
|
es = e;
|
||||||
|
ss = s+1;
|
||||||
|
end
|
||||||
|
else if (re.getc(e) == str.getc(s) || re.getc(e) == "?") begin
|
||||||
|
e++;
|
||||||
|
s++;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
e = es;
|
||||||
|
s = ss++;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
while (e < re.len() && re.getc(e) == "*")
|
||||||
|
e++;
|
||||||
|
if(e == re.len()) begin
|
||||||
|
return 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
return 1;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function string uvm_glob_to_re(string glob);
|
||||||
|
return glob;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright 2010-2012 AMD
|
||||||
|
// Copyright 2011-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2011-2014 Mentor Graphics Corporation
|
||||||
|
// Copyright 2013-2024 NVIDIA Corporation
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_svcmd_dpi.c $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#include "uvm_dpi.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define ARGV_STACK_PTR_SIZE 32
|
||||||
|
|
||||||
|
// the total number of arguments (minus the -f/-F minus associated filenames)
|
||||||
|
int argc_total;
|
||||||
|
// the ptr to the array of ptrs to the args
|
||||||
|
char** argv_stack=NULL;
|
||||||
|
|
||||||
|
char ** argv_ptr=NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void push_data(int lvl,char *entry, int cmd) {
|
||||||
|
if(cmd==0)
|
||||||
|
argc_total++;
|
||||||
|
else
|
||||||
|
*argv_ptr++=entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// walk one level (potentially recursive)
|
||||||
|
void walk_level(int lvl, int argc, char**argv,int cmd) {
|
||||||
|
int idx;
|
||||||
|
for(idx=0; ((lvl==0) && idx<argc) || ((lvl>0) && (*argv));idx++,argv++) {
|
||||||
|
if(strcmp(*argv, "-f") && strcmp(*argv, "-F")) {
|
||||||
|
push_data(lvl,*argv,cmd);
|
||||||
|
} else {
|
||||||
|
argv++;
|
||||||
|
idx++;
|
||||||
|
char **n=(char**) *argv;
|
||||||
|
walk_level(lvl+1,argc,++n,cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *uvm_dpi_get_next_arg_c (int init) {
|
||||||
|
s_vpi_vlog_info info;
|
||||||
|
static int idx=0;
|
||||||
|
|
||||||
|
if(init==1)
|
||||||
|
{
|
||||||
|
// free if necessary
|
||||||
|
free(argv_stack);
|
||||||
|
argc_total=0;
|
||||||
|
|
||||||
|
vpi_get_vlog_info(&info);
|
||||||
|
walk_level(0,info.argc,info.argv,0);
|
||||||
|
|
||||||
|
argv_stack = (char**) malloc (sizeof(char*)*argc_total);
|
||||||
|
argv_ptr=argv_stack;
|
||||||
|
walk_level(0,info.argc,info.argv,1);
|
||||||
|
idx=0;
|
||||||
|
argv_ptr=argv_stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(idx++>=argc_total)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return *argv_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char* uvm_dpi_get_tool_name_c ()
|
||||||
|
{
|
||||||
|
s_vpi_vlog_info info;
|
||||||
|
vpi_get_vlog_info(&info);
|
||||||
|
return info.product;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char* uvm_dpi_get_tool_version_c ()
|
||||||
|
{
|
||||||
|
s_vpi_vlog_info info;
|
||||||
|
vpi_get_vlog_info(&info);
|
||||||
|
return info.version;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright 2010-2012 AMD
|
||||||
|
// Copyright 2013-2018 Cadence Design Systems, Inc.
|
||||||
|
// Copyright 2022 Marvell International Ltd.
|
||||||
|
// Copyright 2010-2011 Mentor Graphics Corporation
|
||||||
|
// Copyright 2020-2024 NVIDIA Corporation
|
||||||
|
// All Rights Reserved Worldwide
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in
|
||||||
|
// compliance with the License. You may obtain a copy of
|
||||||
|
// the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in
|
||||||
|
// writing, software distributed under the License is
|
||||||
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
||||||
|
// the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Git details (see DEVELOPMENT.md):
|
||||||
|
//
|
||||||
|
// $File: src/dpi/uvm_svcmd_dpi.svh $
|
||||||
|
// $Rev: 2024-02-08 13:43:04 -0800 $
|
||||||
|
// $Hash: 29e1e3f8ee4d4aa2035dba1aba401ce1c19aa340 $
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// Import DPI functions used by the interface to generate the
|
||||||
|
// lists.
|
||||||
|
|
||||||
|
`ifndef UVM_CMDLINE_NO_DPI
|
||||||
|
import "DPI-C" function string uvm_dpi_get_next_arg_c (int init);
|
||||||
|
import "DPI-C" function string uvm_dpi_get_tool_name_c ();
|
||||||
|
import "DPI-C" function string uvm_dpi_get_tool_version_c ();
|
||||||
|
|
||||||
|
function string uvm_dpi_get_next_arg(int init=0);
|
||||||
|
return uvm_dpi_get_next_arg_c(init);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function string uvm_dpi_get_tool_name();
|
||||||
|
return uvm_dpi_get_tool_name_c();
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function string uvm_dpi_get_tool_version();
|
||||||
|
return uvm_dpi_get_tool_version_c();
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function chandle uvm_dpi_regcomp(string regex);
|
||||||
|
return uvm_re_comp(regex, .deglob(0));
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int uvm_dpi_regexec(chandle preg, string str);
|
||||||
|
return uvm_re_exec(preg, str);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function void uvm_dpi_regfree(chandle preg);
|
||||||
|
uvm_re_free(preg);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
`else
|
||||||
|
function string uvm_dpi_get_next_arg(int init=0);
|
||||||
|
return "";
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function string uvm_dpi_get_tool_name();
|
||||||
|
return "?";
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function string uvm_dpi_get_tool_version();
|
||||||
|
return "?";
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function chandle uvm_dpi_regcomp(string regex); return null; endfunction
|
||||||
|
function int uvm_dpi_regexec(chandle preg, string str); return 0; endfunction
|
||||||
|
function void uvm_dpi_regfree(chandle preg); endfunction
|
||||||
|
|
||||||
|
`endif
|
||||||
Loading…
Reference in New Issue