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-variable],
|
||||
[-Wno-unused-parameter],
|
||||
[-Wno-unused-variable]],[
|
||||
[-Wno-unused-variable],
|
||||
[-Wno-vla-cxx-extension]],[
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,cflag)
|
||||
# CMake will test what flags work itself, so pass all flags through to it
|
||||
CFG_CXX_FLAGS_CMAKE="$CFG_CXX_FLAGS_CMAKE cflag"
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ for filename in files.split():
|
|||
continue
|
||||
if "include/gtkwave/" in filename: # Standard file - can't change it
|
||||
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
|
||||
filename = os.path.join(test.root, filename)
|
||||
if not os.path.exists(filename):
|
||||
|
|
|
|||
|
|
@ -4,6 +4,16 @@
|
|||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// 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
|
||||
`include "dpi/uvm_dpi.svh"
|
||||
// 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_re
|
||||
= uvm_hdl_check_path
|
||||
|
|
@ -6,7 +6,7 @@ uvm_dpi_get_tool_name_c() = Verilator
|
|||
= uvm_hdl_read not found (bad)
|
||||
===
|
||||
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
|
||||
= uvm_hdl_deposit simple variable
|
||||
= 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 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
|
||||
===
|
||||
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
|
||||
= uvm_hdl_force
|
||||
===
|
||||
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 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 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 *-*
|
||||
|
|
@ -10,13 +10,16 @@
|
|||
import vltest_bootstrap
|
||||
|
||||
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):
|
||||
test.skip("uvm_regex.cc from upstream has clang warnings")
|
||||
|
||||
test.compile(
|
||||
verilator_flags2=["--binary", "--build-jobs 4", "--vpi", "+incdir+t/uvm", test.pli_filename])
|
||||
test.compile(verilator_flags2=[
|
||||
"--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)
|
||||
|
||||
|
|
@ -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::*;
|
||||
initial begin
|
||||
// verilator lint_off WIDTHTRUNC
|
||||
`uvm_info("TOP", "Hello World!", UVM_MEDIUM);
|
||||
`uvm_info("TOP", "UVM TEST PASSED", UVM_MEDIUM);
|
||||
end
|
||||
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=[
|
||||
"--binary",
|
||||
"-j 0",
|
||||
"--CFLAGS -O0",
|
||||
"-Wall",
|
||||
"+incdir+t/uvm", #
|
||||
"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()
|
||||
|
|
|
|||
|
|
@ -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=[
|
||||
"--binary",
|
||||
"-j 0",
|
||||
"--CFLAGS -O0",
|
||||
"-Wall",
|
||||
"+incdir+t/uvm", #
|
||||
"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()
|
||||
|
|
|
|||
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
|
||||
// @uvm-ieee 1800.2-2017 auto 19.6.1
|
||||
`define UVM_HDL_MAX_WIDTH 1024
|
||||
`endif
|
||||
|
||||
|
|
@ -50,8 +51,6 @@
|
|||
* 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;
|
||||
|
||||
|
||||
|
|
@ -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"));
|
||||
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",
|
||||
$sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
|
||||
return 0;
|
||||
|
|
@ -167,4 +166,5 @@ typedef logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t;
|
|||
|
||||
`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