diff --git a/test_regress/t/t_dist_cinclude.py b/test_regress/t/t_dist_cinclude.py index a7ee86009..7ecafce76 100755 --- a/test_regress/t/t_dist_cinclude.py +++ b/test_regress/t/t_dist_cinclude.py @@ -27,6 +27,8 @@ 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 + continue filename = os.path.join(root, filename) if not os.path.exists(filename): continue diff --git a/test_regress/t/t_dist_copyright.py b/test_regress/t/t_dist_copyright.py index 92b4ff4a9..dab107117 100755 --- a/test_regress/t/t_dist_copyright.py +++ b/test_regress/t/t_dist_copyright.py @@ -45,6 +45,7 @@ EXEMPT_FILES_LIST = """ test_regress/t/t_incr_void.v test_regress/t/tsub/t_flag_f_tsub.v test_regress/t/tsub/t_flag_f_tsub_inc.v + test_regress/t/uvm/dpi test_regress/t/uvm/uvm_pkg_all.svh test_regress/t/uvm/uvm_pkg_todo.svh verilator.pc.in diff --git a/test_regress/t/t_uvm_dpi.out b/test_regress/t/t_uvm_dpi.out new file mode 100644 index 000000000..37b3ebd24 --- /dev/null +++ b/test_regress/t/t_uvm_dpi.out @@ -0,0 +1,37 @@ +uvm_dpi_get_tool_name_c() = Verilator +uvm_dpi_get_tool_version_c() = 5.039 devel += 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/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/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]) + 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_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_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' +*-* All Finished *-* diff --git a/test_regress/t/t_uvm_dpi.py b/test_regress/t/t_uvm_dpi.py new file mode 100755 index 000000000..b4f073231 --- /dev/null +++ b/test_regress/t/t_uvm_dpi.py @@ -0,0 +1,20 @@ +#!/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.pli_filename = "t/uvm/dpi/uvm_dpi.cc" + +test.compile( + verilator_flags2=["--binary", "--build-jobs 4", "--vpi", "+incdir+t/uvm", test.pli_filename]) + +test.execute(expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_uvm_dpi.v b/test_regress/t/t_uvm_dpi.v new file mode 100644 index 000000000..4c44dc9cf --- /dev/null +++ b/test_regress/t/t_uvm_dpi.v @@ -0,0 +1,161 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// verilator lint_off WIDTH +`include "dpi/uvm_dpi.svh" +// verilator lint_on WIDTH + +// verilog_format: off +`define stop $stop +`define checkh(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +`define checks(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +// verilog_format: on + +// Undocumented DPI available version of uvm_report +// UVM declares without 'context' +package uvm_pkg; + export "DPI-C" function m__uvm_report_dpi; + function void m__uvm_report_dpi(int severity, string id, string message, int verbosity, + string filename, int line); + $display("UVM Report %s:%d: %s %s", filename, line, id, message); + endfunction : m__uvm_report_dpi +endpackage + +module t; + int i; + string s; + chandle h; + + // To cover testing cases, this has non-zero LSB/LO + logic [31+8:8] exposed /*verilator public*/; + + uvm_hdl_data_t lval; + + initial begin + // TODO TEST: + // extern const char* uvm_dpi_get_next_arg_c(int init); + + //===== Tool + s = uvm_dpi_get_tool_name_c(); + $display("uvm_dpi_get_tool_name_c() = %s", s); + `checks(s, "Verilator"); + + s = uvm_dpi_get_tool_version_c(); + $display("uvm_dpi_get_tool_version_c() = %s", s); + if (s == "") $stop; + + //===== Regexp + $display("= uvm_re"); + h = uvm_dpi_regcomp("a.*b"); + + i = uvm_dpi_regexec(h, "__a_b__"); + `checkh(i, 0); + i = uvm_dpi_regexec(h, "__a_z__"); + `checkh(i, 1); + + uvm_dpi_regfree(h); + + i = uvm_re_match("a.*b", "__a__b__"); + `checkh(i, 0); + + i = uvm_re_match("a.*b", "__a__z__"); + `checkh(i, 1); + + s = uvm_glob_to_re("a foo bar"); + `checks(s, "/^a foo bar$/"); + + //===== Hier +`ifdef VERILATOR +`ifdef TEST_VERBOSE + $c("Verilated::scopesDump();"); +`endif +`endif + + $display("= uvm_hdl_check_path"); + i = uvm_hdl_check_path("t.__NOT_FOUND"); + `checkh(i, 0); + i = uvm_hdl_check_path("t.exposed"); + `checkh(i, 1); + i = uvm_hdl_check_path("$root.t.exposed"); + `checkh(i, 1); + + $display("= uvm_hdl_read simple variable"); + exposed = 32'hb001; + lval = '0; // Upper bits not cleared by uvm_hdl_read + i = uvm_hdl_read("t.exposed", lval); + `checkh(i, 1); + `checkh(lval[31:0], exposed); + + lval = '0; + $display("= uvm_hdl_read not found (bad)"); + $display("===\nUVM Report expected on next line:"); + i = uvm_hdl_deposit("t.__DEPOSIT_NOT_FOUND", lval); + `checkh(i, 0); + + $display("= uvm_hdl_deposit simple variable"); + lval = 1024'hab; + i = uvm_hdl_deposit("t.exposed", lval); + `checkh(i, 1); + `checkh(exposed, 32'hab); + + $display("= uvm_hdl_read single bit"); + exposed = 32'habcd; + lval = '0; // Upper bits not cleared by uvm_hdl_read + i = uvm_hdl_read("t.exposed[11]", lval); + `checkh(i, 1); + `checkh(lval[0], exposed[11]); + + $display("= uvm_hdl_deposit single bit"); + lval = 1024'h0; + i = uvm_hdl_deposit("t.exposed[11]", lval); + `checkh(i, 1); + `checkh(exposed, 32'habc5); + + $display("= uvm_hdl_read multi-bit"); + exposed = 32'habcd; + lval = '0; // Upper bits not cleared by uvm_hdl_read + i = uvm_hdl_read("t.exposed[19:12]", lval); + `checkh(i, 1); + `checkh(lval[7:0], exposed[19:12]); + + $display("= uvm_hdl_deposit multi-bit"); + lval = 1024'h12; + i = uvm_hdl_deposit("t.exposed[19:12]", lval); + `checkh(i, 1); + `checkh(exposed, 32'ha12d); + + $display("= uvm_hdl_deposit bad ranges"); + $display("===\nUVM Report expected on next line:"); + i = uvm_hdl_deposit("t.exposed[10:3]", lval); + `checkh(i, 0); + $display("===\nUVM Report expected on next line:"); + i = uvm_hdl_deposit("t.exposed[99:15]", lval); + `checkh(i, 0); + +`ifdef VERILATOR + // UNSUPPORTED: force/release via VPI + // If support, validate or throw unsupported on force/release part-selects + $display("= uvm_hdl_force"); + $display("===\nUVM Report expected on next line:"); + i = uvm_hdl_force("t.exposed", 62); + `checkh(i, 0); + + $display("= uvm_hdl_release"); + $display("===\nUVM Report expected on next line:"); + i = uvm_hdl_release("t.exposed"); + `checkh(i, 0); + + $display("= uvm_hdl_release_and_read"); + $display("===\nUVM Report expected on next line:"); + i = uvm_hdl_release_and_read("t.exposed", lval); + `checkh(i, 0); +`endif + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/uvm/dpi/.clang-format b/test_regress/t/uvm/dpi/.clang-format new file mode 100644 index 000000000..9225372c1 --- /dev/null +++ b/test_regress/t/uvm/dpi/.clang-format @@ -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 +... diff --git a/test_regress/t/uvm/dpi/uvm_common.c b/test_regress/t/uvm/dpi/uvm_common.c new file mode 100644 index 000000000..018c24804 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_common.c @@ -0,0 +1,52 @@ +//---------------------------------------------------------------------- +// Copyright 2010-2011 Mentor Graphics Corporation +// Copyright 2010-2013 Synopsys, Inc. +// Copyright 2010-2018 Cadence Design Systems, Inc. +// Copyright 2010 AMD +// Copyright 2013 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. +//---------------------------------------------------------------------- + +// 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; +} diff --git a/test_regress/t/uvm/dpi/uvm_dpi.cc b/test_regress/t/uvm/dpi/uvm_dpi.cc new file mode 100644 index 000000000..3739aba9b --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_dpi.cc @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------- +// Copyright 2010-2017 Mentor Graphics Corporation +// Copyright 2010-2013 Synopsys, Inc. +// Copyright 2010-2018 Cadence Design Systems, Inc. +// Copyright 2013 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. +//---------------------------------------------------------------------- + +// +// 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 +#include "uvm_dpi.h" + +// Avoid -Wmissing-definitions + int uvm_re_match(const char * re, const char *str); + const char * uvm_glob_to_re(const char *glob); + 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 regex_t* uvm_dpi_regcomp (char* pattern); + extern int uvm_dpi_regexec (regex_t* re, char* str); + extern void uvm_dpi_regfree (regex_t* re); + +#include "uvm_common.c" +#include "uvm_regex.cc" +#include "uvm_hdl.c" +#include "uvm_svcmd_dpi.c" + +#ifdef __cplusplus +} +#endif diff --git a/test_regress/t/uvm/dpi/uvm_dpi.h b/test_regress/t/uvm/dpi/uvm_dpi.h new file mode 100644 index 000000000..6ccee7da5 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_dpi.h @@ -0,0 +1,84 @@ +//---------------------------------------------------------------------- +// Copyright 2010-2017 Mentor Graphics Corporation +// Copyright 2010 Synopsys, Inc. +// Copyright 2010-2018 Cadence Design Systems, Inc. +// Copyright 2013 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. +//---------------------------------------------------------------------- + +// +// 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 +#include "vpi_user.h" +#include "veriuser.h" +#include "svdpi.h" +#include +#include +#include +#include +#include + +// 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 ); + +int uvm_re_match(const char * re, const char *str); +const char * uvm_glob_to_re(const char *glob); + +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 regex_t* uvm_dpi_regcomp (char* pattern); +extern int uvm_dpi_regexec (regex_t* re, char* str); +extern void uvm_dpi_regfree (regex_t* re); + +#endif diff --git a/test_regress/t/uvm/dpi/uvm_dpi.svh b/test_regress/t/uvm/dpi/uvm_dpi.svh new file mode 100644 index 000000000..e89597f5e --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_dpi.svh @@ -0,0 +1,44 @@ +//---------------------------------------------------------------------- +// Copyright 2010-2011 Mentor Graphics Corporation +// Copyright 2010 Synopsys, Inc. +// Copyright 2010-2018 Cadence Design Systems, Inc. +// Copyright 2010 AMD +// 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. +//---------------------------------------------------------------------- + +`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" + +`endif // UVM_DPI_SVH diff --git a/test_regress/t/uvm/dpi/uvm_hdl.c b/test_regress/t/uvm/dpi/uvm_hdl.c new file mode 100644 index 000000000..0b2041aca --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_hdl.c @@ -0,0 +1,40 @@ +//---------------------------------------------------------------------- +// Copyright 2009-2011 Mentor Graphics Corporation +// Copyright 2010-2011 Synopsys, Inc. +// Copyright 2007-2018 Cadence Design Systems, Inc. +// Copyright 2013 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. +//---------------------------------------------------------------------- + +// 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 diff --git a/test_regress/t/uvm/dpi/uvm_hdl.svh b/test_regress/t/uvm/dpi/uvm_hdl.svh new file mode 100644 index 000000000..2e1d6e3b6 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_hdl.svh @@ -0,0 +1,170 @@ +//------------------------------------------------------------ +// Copyright 2007-2011 Mentor Graphics Corporation +// Copyright 2015 Analog Devices, Inc. +// Copyright 2010 Synopsys, Inc. +// Copyright 2010-2018 Cadence Design Systems, Inc. +// Copyright 2014-2018 NVIDIA Corporation +// Copyright 2014 Cisco Systems, Inc. +// Copyright 2012 Accellera Systems Initiative +// 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. +//------------------------------------------------------------ + +// 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, 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)) + return; + #force_time; + void'(uvm_hdl_release_and_read(path, value)); + endtask + + + // Function -- NODOCS -- uvm_hdl_release_and_read + // + // Releases a value previously set with . + // 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 . + // 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 diff --git a/test_regress/t/uvm/dpi/uvm_hdl_verilator.c b/test_regress/t/uvm/dpi/uvm_hdl_verilator.c new file mode 100644 index 000000000..41b798f62 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_hdl_verilator.c @@ -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 +#include +#include + +static void m_uvm_error(const char *ID, const char *msg, ...); +static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag); +static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag, int partsel); +static int uvm_hdl_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=", + 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=", + 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); +} diff --git a/test_regress/t/uvm/dpi/uvm_regex.cc b/test_regress/t/uvm/dpi/uvm_regex.cc new file mode 100644 index 000000000..bf4a13b02 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_regex.cc @@ -0,0 +1,239 @@ +//---------------------------------------------------------------------- +// Copyright 2007-2011 Mentor Graphics Corporation +// Copyright 2010-2018 Cadence Design Systems, Inc. +// Copyright 2013-2014 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. +//---------------------------------------------------------------------- + + +#include "uvm_dpi.h" +#include + + +const char uvm_re_bracket_char = '/'; +#define UVM_REGEX_MAX_LENGTH 2048 +static char uvm_re[UVM_REGEX_MAX_LENGTH+4]; + +static const char* empty_regex="/^$/"; + +//-------------------------------------------------------------------- +// uvm_re_match +// +// Match a string to a regular expression. The regex is first lookup +// up in the regex cache to see if it has already been compiled. If +// so, the compile version is retrieved from the cache. Otherwise, it +// is compiled and cached for future use. After compilation the +// matching is done using regexec(). +//-------------------------------------------------------------------- +int uvm_re_match(const char * re, const char *str) +{ + regex_t *rexp; + int err; + + // safety check. Args should never be ~null~ since this is called + // from DPI. But we'll check anyway. + if(re == NULL) + return 1; + if(str == NULL) + return 1; + + int len = strlen(re); + char * rex = &uvm_re[0]; + + if (len > UVM_REGEX_MAX_LENGTH) { + const char* err_str = "uvm_re_match : regular expression greater than max %0d: |%s|"; + char buffer[strlen(err_str) + int_str_max(10) + strlen(re)]; + sprintf(buffer, err_str, UVM_REGEX_MAX_LENGTH, re); + m_uvm_report_dpi(M_UVM_ERROR, + (char*) "UVM/DPI/REGEX_MAX", + &buffer[0], + M_UVM_NONE, + (char*)__FILE__, + __LINE__); + return 1; + } + + // we copy the regexp because we need to remove any brackets around it + strncpy(&uvm_re[0],re,UVM_REGEX_MAX_LENGTH); + if (len>1 && (re[0] == uvm_re_bracket_char) && re[len-1] == uvm_re_bracket_char) { + uvm_re[len-1] = '\0'; + rex++; + } + + rexp = (regex_t*)malloc(sizeof(regex_t)); + + if (rexp == NULL) { + m_uvm_report_dpi(M_UVM_ERROR, + (char*) "UVM/DPI/REGEX_ALLOC", + (char*) "uvm_re_match: internal memory allocation error", + M_UVM_NONE, + (char*)__FILE__, + __LINE__); + return 1; + } + + err = regcomp(rexp, rex, REG_EXTENDED); + + if (err != 0) { + regerror(err,rexp,uvm_re,UVM_REGEX_MAX_LENGTH-1); + const char * err_str = "uvm_re_match : invalid glob or regular expression: |%s||%s|"; + char buffer[strlen(err_str) + strlen(re) + strlen(uvm_re)+1]; + sprintf(buffer, err_str, re, uvm_re); + m_uvm_report_dpi(M_UVM_ERROR, + (char*) "UVM/DPI/REGEX_INV", + &buffer[0], + M_UVM_NONE, + (char*)__FILE__, + __LINE__); + regfree(rexp); + free(rexp); + return err; + } + + err = regexec(rexp, str, 0, NULL, 0); + + //vpi_printf((PLI_BYTE8*) "UVM_INFO: uvm_re_match: re=%s str=%s ERR=%0d\n",rex,str,err); + regfree(rexp); + free(rexp); + + return err; +} + + +//-------------------------------------------------------------------- +// uvm_glob_to_re +// +// Convert a glob expression to a normal regular expression. +//-------------------------------------------------------------------- + +const char * uvm_glob_to_re(const char *glob) +{ + const char *p; + int len; + + // safety check. Glob should never be ~null~ since this is called + // from DPI. But we'll check anyway. + if(glob == NULL) + return NULL; + + len = strlen(glob); + + if (len > 2040) { + const char * err_str = "uvm_re_match : glob expression greater than max 2040: |%s|"; + char buffer[strlen(err_str) + strlen(glob)+1]; + sprintf(buffer, err_str, glob); + m_uvm_report_dpi(M_UVM_ERROR, + (char*) "UVM/DPI/REGEX_MAX", + &buffer[0], + M_UVM_NONE, + (char*)__FILE__, + __LINE__); + return 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(len == 0 || (len == 1 && *glob == uvm_re_bracket_char)) + { + return empty_regex; + } + + // If bracketed with the /glob/, then it's already a regex + if(glob[0] == uvm_re_bracket_char && glob[len-1] == uvm_re_bracket_char) + { + strcpy(uvm_re,glob); + return &uvm_re[0]; + } + else + { + // Convert the glob to a true regular expression (Posix syntax) + len = 0; + + uvm_re[len++] = uvm_re_bracket_char; + + // ^ goes at the beginning... + if (*glob != '^') + uvm_re[len++] = '^'; + + for(p = glob; *p; p++) + { + // Replace the glob metacharacters with corresponding regular + // expression metacharacters. + switch(*p) + { + case '*': + uvm_re[len++] = '.'; + uvm_re[len++] = '*'; + break; + + case '+': + uvm_re[len++] = '.'; + uvm_re[len++] = '+'; + break; + + case '.': + uvm_re[len++] = '\\'; + uvm_re[len++] = '.'; + break; + + case '?': + uvm_re[len++] = '.'; + break; + + case '[': + uvm_re[len++] = '\\'; + uvm_re[len++] = '['; + break; + + case ']': + uvm_re[len++] = '\\'; + uvm_re[len++] = ']'; + break; + + case '(': + uvm_re[len++] = '\\'; + uvm_re[len++] = '('; + break; + + case ')': + uvm_re[len++] = '\\'; + uvm_re[len++] = ')'; + break; + + default: + uvm_re[len++] = *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 (uvm_re[len-1] != '$') + uvm_re[len++] = '$'; + + uvm_re[len++] = uvm_re_bracket_char; + + uvm_re[len++] = '\0'; + + return &uvm_re[0]; +} diff --git a/test_regress/t/uvm/dpi/uvm_regex.svh b/test_regress/t/uvm/dpi/uvm_regex.svh new file mode 100644 index 000000000..825a78307 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_regex.svh @@ -0,0 +1,85 @@ +//---------------------------------------------------------------------- +// Copyright 2010-2012 Mentor Graphics Corporation +// Copyright 2010-2018 Cadence Design Systems, 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. +//---------------------------------------------------------------------- + + + +`ifndef UVM_REGEX_NO_DPI +import "DPI-C" context function int uvm_re_match(string re, string str); +import "DPI-C" context function string uvm_glob_to_re(string glob); + +`else + +// The Verilog only version does not match regular expressions, +// it only does glob style matching. +function int uvm_re_match(string re, string str); + 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 diff --git a/test_regress/t/uvm/dpi/uvm_svcmd_dpi.c b/test_regress/t/uvm/dpi/uvm_svcmd_dpi.c new file mode 100644 index 000000000..6947613e0 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_svcmd_dpi.c @@ -0,0 +1,135 @@ +// +//------------------------------------------------------------------------------ +// Copyright 2011-2014 Mentor Graphics Corporation +// Copyright 2011-2018 Cadence Design Systems, Inc. +// Copyright 2010-2012 AMD +// Copyright 2013 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. +//------------------------------------------------------------------------------ + +#include "uvm_dpi.h" +#include + +#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) && idx0) && (*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; +} + +extern regex_t* uvm_dpi_regcomp (char* pattern) +{ + regex_t* re = (regex_t*) malloc (sizeof(regex_t)); + int status = regcomp(re, pattern, REG_NOSUB|REG_EXTENDED); + if(status) + { + const char * err_str = "uvm_dpi_regcomp : Unable to compile regex: |%s|, Element 0 is: %c"; + char buffer[strlen(err_str) + strlen(pattern) + 1]; + sprintf(buffer, err_str, pattern, pattern[0]); + m_uvm_report_dpi(M_UVM_ERROR, + (char*)"UVM/DPI/REGCOMP", + &buffer[0], + M_UVM_NONE, + (char*) __FILE__, + __LINE__); + regfree(re); + free (re); + return NULL; + } + return re; +} + +extern int uvm_dpi_regexec (regex_t* re, char* str) +{ + if(!re ) + { + return 1; + } + return regexec(re, str, (size_t)0, NULL, 0); +} + +extern void uvm_dpi_regfree (regex_t* re) +{ + if(!re) return; + regfree(re); + free (re); +} diff --git a/test_regress/t/uvm/dpi/uvm_svcmd_dpi.svh b/test_regress/t/uvm/dpi/uvm_svcmd_dpi.svh new file mode 100644 index 000000000..885e17976 --- /dev/null +++ b/test_regress/t/uvm/dpi/uvm_svcmd_dpi.svh @@ -0,0 +1,65 @@ +// +//------------------------------------------------------------------------------ +// Copyright 2010-2011 Mentor Graphics Corporation +// Copyright 2013-2018 Cadence Design Systems, Inc. +// Copyright 2010-2012 AMD +// 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. +//------------------------------------------------------------------------------ + +// 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 + +import "DPI-C" function chandle uvm_dpi_regcomp(string regex); +import "DPI-C" function int uvm_dpi_regexec(chandle preg, string str); +import "DPI-C" function void uvm_dpi_regfree(chandle preg); + +`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