Add `-Wno-vla-cxx-extension` CLang flag, and UVM DPI tests (#6782)

This commit is contained in:
Wilson Snyder 2025-12-09 07:15:28 -05:00 committed by GitHub
parent e6a3d61d25
commit db2099a4dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 86871 additions and 16 deletions

View File

@ -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"

View File

@ -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):

View File

@ -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

View File

@ -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 *-*

View File

@ -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)

View File

@ -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 *-*

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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
...

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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