From 862d5fcc6612d6bab42ec05982eadf6654beda8a Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Sun, 29 Aug 2021 13:15:54 -0300 Subject: [PATCH 01/12] vunit/sim_if/xcelium.py: added as a modified copy of incisive.py Incisive and irun were replaced by Xcelium and xrun. --- vunit/sim_if/cds_file.py | 4 +- vunit/sim_if/factory.py | 2 + vunit/sim_if/xcelium.py | 419 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 vunit/sim_if/xcelium.py diff --git a/vunit/sim_if/cds_file.py b/vunit/sim_if/cds_file.py index 51c68c679..73b576eab 100644 --- a/vunit/sim_if/cds_file.py +++ b/vunit/sim_if/cds_file.py @@ -5,7 +5,7 @@ # Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com """ -Handles Cadence Incisive .cds files +Handles Cadence Incisive/Xcelium .cds files """ import re @@ -14,7 +14,7 @@ class CDSFile(dict): """ - Handles Cadence Incisive .cds files + Handles Cadence Incisive/Xcelium .cds files Only cares about 'define' but other lines are kept intact """ diff --git a/vunit/sim_if/factory.py b/vunit/sim_if/factory.py index 9a2f4f827..2ab3a37a0 100644 --- a/vunit/sim_if/factory.py +++ b/vunit/sim_if/factory.py @@ -12,6 +12,7 @@ from .activehdl import ActiveHDLInterface from .ghdl import GHDLInterface from .incisive import IncisiveInterface +from .xcelium import XceliumInterface from .modelsim import ModelSimInterface from .rivierapro import RivieraProInterface from . import BooleanOption, ListOfStringOption, VHDLAssertLevelOption @@ -33,6 +34,7 @@ def supported_simulators(): ActiveHDLInterface, GHDLInterface, IncisiveInterface, + XceliumInterface, ] def _extract_compile_options(self): diff --git a/vunit/sim_if/xcelium.py b/vunit/sim_if/xcelium.py new file mode 100644 index 000000000..153d7a936 --- /dev/null +++ b/vunit/sim_if/xcelium.py @@ -0,0 +1,419 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com + +""" +Interface for the Cadence Xcelium simulator +""" + +from pathlib import Path +from os.path import relpath +import os +import subprocess +import logging +from ..exceptions import CompileError +from ..ostools import write_file, file_exists +from ..vhdl_standard import VHDL +from . import SimulatorInterface, run_command, ListOfStringOption +from .cds_file import CDSFile + +LOGGER = logging.getLogger(__name__) + + +class XceliumInterface( # pylint: disable=too-many-instance-attributes + SimulatorInterface +): + """ + Interface for the Cadence Xcelium simulator + """ + + name = "xcelium" + supports_gui_flag = True + package_users_depend_on_bodies = False + + compile_options = [ + ListOfStringOption("xcelium.xrun_vhdl_flags"), + ListOfStringOption("xcelium.xrun_verilog_flags"), + ] + + sim_options = [ListOfStringOption("xcelium.xrun_sim_flags")] + + @staticmethod + def add_arguments(parser): + """ + Add command line arguments + """ + group = parser.add_argument_group( + "Xcelium xrun", description="Xcelium xrun-specific flags" + ) + group.add_argument( + "--cdslib", + default=None, + help="The cds.lib file to use. If not given, VUnit maintains its own cds.lib file.", + ) + group.add_argument( + "--hdlvar", + default=None, + help="The hdl.var file to use. If not given, VUnit does not use a hdl.var file.", + ) + + @classmethod + def from_args(cls, args, output_path, **kwargs): + """ + Create new instance from command line arguments object + """ + return cls( + prefix=cls.find_prefix(), + output_path=output_path, + log_level=args.log_level, + gui=args.gui, + cdslib=args.cdslib, + hdlvar=args.hdlvar, + ) + + @classmethod + def find_prefix_from_path(cls): + """ + Find xcelium simulator from PATH environment variable + """ + return cls.find_toolchain(["xrun"]) + + @staticmethod + def supports_vhdl_contexts(): + """ + Returns True when this simulator supports VHDL 2008 contexts + """ + return False + + def __init__( # pylint: disable=too-many-arguments + self, prefix, output_path, gui=False, log_level=None, cdslib=None, hdlvar=None + ): + SimulatorInterface.__init__(self, output_path, gui) + self._prefix = prefix + self._libraries = [] + self._log_level = log_level + if cdslib is None: + self._cdslib = str((Path(output_path) / "cds.lib").resolve()) + else: + self._cdslib = str(Path(cdslib).resolve()) + self._hdlvar = hdlvar + self._cds_root_xrun = self.find_cds_root_xrun() + self._create_cdslib() + + def find_cds_root_xrun(self): + """ + Finds xrun cds root + """ + return subprocess.check_output( + [str(Path(self._prefix) / "cds_root"), "xrun"] + ).splitlines()[0] + + def find_cds_root_virtuoso(self): + """ + Finds virtuoso cds root + """ + try: + return subprocess.check_output( + [str(Path(self._prefix) / "cds_root"), "virtuoso"] + ).splitlines()[0] + except subprocess.CalledProcessError: + return None + + def _create_cdslib(self): + """ + Create the cds.lib file in the output directory if it does not exist + """ + cds_root_virtuoso = self.find_cds_root_virtuoso() + + if cds_root_virtuoso is None: + contents = """\ +## cds.lib: Defines the locations of compiled libraries. +softinclude {0}/tools/inca/files/cds.lib +# needed for referencing the library 'basic' for cells 'cds_alias', 'cds_thru' etc. in analog models: +# NOTE: 'virtuoso' executable not found! +# define basic ".../tools/dfII/etc/cdslib/basic" +define work "{1}/libraries/work" +""".format( + self._cds_root_xrun, self._output_path + ) + else: + contents = """\ +## cds.lib: Defines the locations of compiled libraries. +softinclude {0}/tools/inca/files/cds.lib +# needed for referencing the library 'basic' for cells 'cds_alias', 'cds_thru' etc. in analog models: +define basic "{1}/tools/dfII/etc/cdslib/basic" +define work "{2}/libraries/work" +""".format( + self._cds_root_xrun, cds_root_virtuoso, self._output_path + ) + + write_file(self._cdslib, contents) + + def setup_library_mapping(self, project): + """ + Compile project using vhdl_standard + """ + mapped_libraries = self._get_mapped_libraries() + + for library in project.get_libraries(): + self._libraries.append(library) + self.create_library(library.name, library.directory, mapped_libraries) + + def compile_source_file_command(self, source_file): + """ + Returns the command to compile a single source file + """ + if source_file.is_vhdl: + return self.compile_vhdl_file_command(source_file) + + if source_file.is_any_verilog: + return self.compile_verilog_file_command(source_file) + + raise CompileError + + @staticmethod + def _vhdl_std_opt(vhdl_standard): + """ + Convert standard to format of xrun command line flag + """ + if vhdl_standard == VHDL.STD_2002: + return "-v200x -extv200x" + + if vhdl_standard == VHDL.STD_2008: + return "-v200x -extv200x" + + if vhdl_standard == VHDL.STD_1993: + return "-v93" + + raise ValueError("Invalid VHDL standard %s" % vhdl_standard) + + def compile_vhdl_file_command(self, source_file): + """ + Returns command to compile a VHDL file + """ + cmd = str(Path(self._prefix) / "xrun") + args = [] + args += ["-compile"] + args += ["-nocopyright"] + args += ["-licqueue"] + args += ["-nowarn DLCPTH"] # "cds.lib Invalid path" + args += ["-nowarn DLCVAR"] # "cds.lib Invalid environment variable ''." + args += ["%s" % self._vhdl_std_opt(source_file.get_vhdl_standard())] + args += ["-work work"] + args += ['-cdslib "%s"' % self._cdslib] + args += self._hdlvar_args() + args += [ + '-log "%s"' + % str( + Path(self._output_path) + / ("xrun_compile_vhdl_file_%s.log" % source_file.library.name) + ) + ] + if not self._log_level == "debug": + args += ["-quiet"] + else: + args += ["-messages"] + args += ["-libverbose"] + args += source_file.compile_options.get("xcelium.xrun_vhdl_flags", []) + args += ['-nclibdirname "%s"' % str(Path(source_file.library.directory).parent)] + args += ["-makelib %s" % source_file.library.directory] + args += ['"%s"' % source_file.name] + args += ["-endlib"] + argsfile = str( + Path(self._output_path) + / ("xrun_compile_vhdl_file_%s.args" % source_file.library.name) + ) + write_file(argsfile, "\n".join(args)) + return [cmd, "-f", argsfile] + + def compile_verilog_file_command(self, source_file): + """ + Returns commands to compile a Verilog file + """ + cmd = str(Path(self._prefix) / "xrun") + args = [] + args += ["-compile"] + args += ["-nocopyright"] + args += ["-licqueue"] + # "Ignored unexpected semicolon following SystemVerilog description keyword (endfunction)." + args += ["-nowarn UEXPSC"] + # "cds.lib Invalid path" + args += ["-nowarn DLCPTH"] + # "cds.lib Invalid environment variable ''." + args += ["-nowarn DLCVAR"] + args += ["-work work"] + args += source_file.compile_options.get("xcelium.xrun_verilog_flags", []) + args += ['-cdslib "%s"' % self._cdslib] + args += self._hdlvar_args() + args += [ + '-log "%s"' + % str( + Path(self._output_path) + / ("xrun_compile_verilog_file_%s.log" % source_file.library.name) + ) + ] + if not self._log_level == "debug": + args += ["-quiet"] + else: + args += ["-messages"] + args += ["-libverbose"] + for include_dir in source_file.include_dirs: + args += ['-incdir "%s"' % include_dir] + + # for "disciplines.vams" etc. + args += ['-incdir "%s/tools/spectre/etc/ahdl/"' % self._cds_root_xrun] + + for key, value in source_file.defines.items(): + args += ["-define %s=%s" % (key, value.replace('"', '\\"'))] + args += ['-nclibdirname "%s"' % str(Path(source_file.library.directory).parent)] + args += ["-makelib %s" % source_file.library.name] + args += ['"%s"' % source_file.name] + args += ["-endlib"] + argsfile = str( + Path(self._output_path) + / ("xrun_compile_verilog_file_%s.args" % source_file.library.name) + ) + write_file(argsfile, "\n".join(args)) + return [cmd, "-f", argsfile] + + def create_library(self, library_name, library_path, mapped_libraries=None): + """ + Create and map a library_name to library_path + """ + mapped_libraries = mapped_libraries if mapped_libraries is not None else {} + + lpath = str(Path(library_path).resolve().parent) + + if not file_exists(lpath): + os.makedirs(lpath) + + if ( + library_name in mapped_libraries + and mapped_libraries[library_name] == library_path + ): + return + + cds = CDSFile.parse(self._cdslib) + cds[library_name] = library_path + cds.write(self._cdslib) + + def _get_mapped_libraries(self): + """ + Get mapped libraries from cds.lib file + """ + cds = CDSFile.parse(self._cdslib) + return cds + + def simulate( # pylint: disable=too-many-locals + self, output_path, test_suite_name, config, elaborate_only=False + ): + """ + Elaborates and Simulates with entity as top level using generics + """ + + script_path = str(Path(output_path) / self.name) + launch_gui = self._gui is not False and not elaborate_only + + if elaborate_only: + steps = ["elaborate"] + else: + steps = ["elaborate", "simulate"] + + for step in steps: + cmd = str(Path(self._prefix) / "xrun") + args = [] + if step == "elaborate": + args += ["-elaborate"] + args += ["-nocopyright"] + args += ["-licqueue"] + # args += ['-dumpstack'] + # args += ['-gdbsh'] + # args += ['-rebuild'] + # args += ['-gdb'] + # args += ['-gdbelab'] + args += ["-errormax 10"] + args += ["-nowarn WRMNZD"] + args += ["-nowarn DLCPTH"] # "cds.lib Invalid path" + args += ["-nowarn DLCVAR"] # "cds.lib Invalid environment variable ''." + args += [ + "-ncerror EVBBOL" + ] # promote to error: "bad boolean literal in generic association" + args += [ + "-ncerror EVBSTR" + ] # promote to error: "bad string literal in generic association" + args += [ + "-ncerror EVBNAT" + ] # promote to error: "bad natural literal in generic association" + args += ["-work work"] + args += [ + '-nclibdirname "%s"' % (str(Path(self._output_path) / "libraries")) + ] # @TODO: ugly + args += config.sim_options.get("xcelium.xrun_sim_flags", []) + args += ['-cdslib "%s"' % self._cdslib] + args += self._hdlvar_args() + args += ['-log "%s"' % str(Path(script_path) / ("xrun_%s.log" % step))] + if not self._log_level == "debug": + args += ["-quiet"] + else: + args += ["-messages"] + # args += ['-libverbose'] + args += self._generic_args(config.entity_name, config.generics) + for library in self._libraries: + args += ['-reflib "%s"' % library.directory] + if launch_gui: + args += ["-access +rwc"] + # args += ['-linedebug'] + args += ["-gui"] + else: + args += ["-access +r"] + args += ['-input "@run"'] + + if config.architecture_name is None: + # we have a SystemVerilog toplevel: + args += ["-top %s.%s:sv" % (config.library_name, config.entity_name)] + else: + # we have a VHDL toplevel: + args += [ + "-top %s.%s:%s" + % ( + config.library_name, + config.entity_name, + config.architecture_name, + ) + ] + argsfile = "%s/xrun_%s.args" % (script_path, step) + write_file(argsfile, "\n".join(args)) + if not run_command( + [cmd, "-f", relpath(argsfile, script_path)], + cwd=script_path, + env=self.get_env(), + ): + return False + return True + + def _hdlvar_args(self): + """ + Return hdlvar argument if available + """ + if self._hdlvar is None: + return [] + return ['-hdlvar "%s"' % self._hdlvar] + + @staticmethod + def _generic_args(entity_name, generics): + """ + Create xrun arguments for generics/parameters + """ + args = [] + for name, value in generics.items(): + if _generic_needs_quoting(value): + args += ['''-gpg "%s.%s => \\"%s\\""''' % (entity_name, name, value)] + else: + args += ['''-gpg "%s.%s => %s"''' % (entity_name, name, value)] + return args + + +def _generic_needs_quoting(value): # pylint: disable=missing-docstring + return isinstance(value, (str, bool)) From f85ba248ae69a873d7ea6529b774c3eea250fcea Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Sun, 29 Aug 2021 15:53:27 -0300 Subject: [PATCH 02/12] xcelium: replaced nclibdirname (deprecated) by xmlibdirname, to avoid warnings --- vunit/sim_if/xcelium.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vunit/sim_if/xcelium.py b/vunit/sim_if/xcelium.py index 153d7a936..ef3cd029f 100644 --- a/vunit/sim_if/xcelium.py +++ b/vunit/sim_if/xcelium.py @@ -217,7 +217,7 @@ def compile_vhdl_file_command(self, source_file): args += ["-messages"] args += ["-libverbose"] args += source_file.compile_options.get("xcelium.xrun_vhdl_flags", []) - args += ['-nclibdirname "%s"' % str(Path(source_file.library.directory).parent)] + args += ['-xmlibdirname "%s"' % str(Path(source_file.library.directory).parent)] args += ["-makelib %s" % source_file.library.directory] args += ['"%s"' % source_file.name] args += ["-endlib"] @@ -267,7 +267,7 @@ def compile_verilog_file_command(self, source_file): for key, value in source_file.defines.items(): args += ["-define %s=%s" % (key, value.replace('"', '\\"'))] - args += ['-nclibdirname "%s"' % str(Path(source_file.library.directory).parent)] + args += ['-xmlibdirname "%s"' % str(Path(source_file.library.directory).parent)] args += ["-makelib %s" % source_file.library.name] args += ['"%s"' % source_file.name] args += ["-endlib"] @@ -348,7 +348,7 @@ def simulate( # pylint: disable=too-many-locals ] # promote to error: "bad natural literal in generic association" args += ["-work work"] args += [ - '-nclibdirname "%s"' % (str(Path(self._output_path) / "libraries")) + '-xmlibdirname "%s"' % (str(Path(self._output_path) / "libraries")) ] # @TODO: ugly args += config.sim_options.get("xcelium.xrun_sim_flags", []) args += ['-cdslib "%s"' % self._cdslib] From 9ef0feb6181eb94a4a8d366ac765c4ae462e5358 Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Sun, 29 Aug 2021 15:57:27 -0300 Subject: [PATCH 03/12] xcelium: replaced ncerror by xmerror --- vunit/sim_if/xcelium.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vunit/sim_if/xcelium.py b/vunit/sim_if/xcelium.py index ef3cd029f..609ce47fb 100644 --- a/vunit/sim_if/xcelium.py +++ b/vunit/sim_if/xcelium.py @@ -338,13 +338,13 @@ def simulate( # pylint: disable=too-many-locals args += ["-nowarn DLCPTH"] # "cds.lib Invalid path" args += ["-nowarn DLCVAR"] # "cds.lib Invalid environment variable ''." args += [ - "-ncerror EVBBOL" + "-xmerror EVBBOL" ] # promote to error: "bad boolean literal in generic association" args += [ - "-ncerror EVBSTR" + "-xmerror EVBSTR" ] # promote to error: "bad string literal in generic association" args += [ - "-ncerror EVBNAT" + "-xmerror EVBNAT" ] # promote to error: "bad natural literal in generic association" args += ["-work work"] args += [ From 1717700c81e1cf51f02ddb7f8a5645bd11245895 Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Sun, 29 Aug 2021 15:59:52 -0300 Subject: [PATCH 04/12] Fixed acceptance testing issue with Incisive and Xcelium (spaces in path not supported) --- tests/acceptance/test_artificial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/acceptance/test_artificial.py b/tests/acceptance/test_artificial.py index a5df1a0f2..236809679 100644 --- a/tests/acceptance/test_artificial.py +++ b/tests/acceptance/test_artificial.py @@ -27,7 +27,7 @@ class TestVunitArtificial(unittest.TestCase): """ def setUp(self): - if simulator_is("activehdl"): + if simulator_is("activehdl", "incisive", "xcelium"): self.output_path = str(ROOT / "artificial_out") else: # Spaces in path intentional to verify that it is supported From d20440547be0dbdcb21916b93b7d823b29f2c9a9 Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Mon, 30 Aug 2021 09:06:50 -0300 Subject: [PATCH 05/12] Fixed an issue with the shared command-line arguments of Incisive and Xcelium --- vunit/sim_if/incisive.py | 19 +------------------ vunit/sim_if/xcelium.py | 2 +- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/vunit/sim_if/incisive.py b/vunit/sim_if/incisive.py index 455de667b..76187102f 100644 --- a/vunit/sim_if/incisive.py +++ b/vunit/sim_if/incisive.py @@ -40,24 +40,7 @@ class IncisiveInterface( # pylint: disable=too-many-instance-attributes sim_options = [ListOfStringOption("incisive.irun_sim_flags")] - @staticmethod - def add_arguments(parser): - """ - Add command line arguments - """ - group = parser.add_argument_group( - "Incisive irun", description="Incisive irun-specific flags" - ) - group.add_argument( - "--cdslib", - default=None, - help="The cds.lib file to use. If not given, VUnit maintains its own cds.lib file.", - ) - group.add_argument( - "--hdlvar", - default=None, - help="The hdl.var file to use. If not given, VUnit does not use a hdl.var file.", - ) + # NOTE: Incisive shares the command-line arguments with Xcelium @classmethod def from_args(cls, args, output_path, **kwargs): diff --git a/vunit/sim_if/xcelium.py b/vunit/sim_if/xcelium.py index 609ce47fb..9a9a2b298 100644 --- a/vunit/sim_if/xcelium.py +++ b/vunit/sim_if/xcelium.py @@ -46,7 +46,7 @@ def add_arguments(parser): Add command line arguments """ group = parser.add_argument_group( - "Xcelium xrun", description="Xcelium xrun-specific flags" + "Xcelium/Incisive", description="Xcelium/Incisive specific flags" ) group.add_argument( "--cdslib", From fbd3c7cbb658b52f4fee71de67fcd8aa05087ec9 Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Mon, 30 Aug 2021 18:39:11 -0300 Subject: [PATCH 06/12] Fix compile issues under vunit/vhdl/data_types/src --- vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd | 3 ++- vunit/vhdl/data_types/src/queue_pkg.vhd | 3 ++- vunit/vhdl/data_types/src/string_ptr_pkg.vhd | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd index 103497a0c..e029243ab 100644 --- a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd +++ b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd @@ -91,6 +91,8 @@ package integer_vector_ptr_pkg is code : string ) return ptr_t; + alias decode_ptr_t is decode[string return ptr_t]; + procedure decode ( constant code : string; variable index : inout positive; @@ -98,7 +100,6 @@ package integer_vector_ptr_pkg is ); alias encode_ptr_t is encode[ptr_t return string]; - alias decode_ptr_t is decode[string return ptr_t]; constant integer_vector_ptr_t_code_length : positive := integer_code_length; diff --git a/vunit/vhdl/data_types/src/queue_pkg.vhd b/vunit/vhdl/data_types/src/queue_pkg.vhd index 5732b4531..0a94922c9 100644 --- a/vunit/vhdl/data_types/src/queue_pkg.vhd +++ b/vunit/vhdl/data_types/src/queue_pkg.vhd @@ -344,6 +344,8 @@ package queue_pkg is code : string ) return queue_t; + alias decode_queue_t is decode[string return queue_t]; + procedure decode ( constant code : string; variable index : inout positive; @@ -351,7 +353,6 @@ package queue_pkg is ); alias encode_queue_t is encode[queue_t return string]; - alias decode_queue_t is decode[string return queue_t]; procedure push_type ( queue : queue_t; diff --git a/vunit/vhdl/data_types/src/string_ptr_pkg.vhd b/vunit/vhdl/data_types/src/string_ptr_pkg.vhd index f1ecbf1a0..877f6641d 100644 --- a/vunit/vhdl/data_types/src/string_ptr_pkg.vhd +++ b/vunit/vhdl/data_types/src/string_ptr_pkg.vhd @@ -105,6 +105,8 @@ package string_ptr_pkg is code : string ) return ptr_t; + alias decode_ptr_t is decode[string return ptr_t]; + procedure decode ( constant code : string; variable index : inout positive; @@ -112,7 +114,6 @@ package string_ptr_pkg is ); alias encode_ptr_t is encode[ptr_t return string]; - alias decode_ptr_t is decode[string return ptr_t]; constant string_ptr_t_code_length : positive := integer_code_length; From cfc070a7ee10e5cd000f8d67bac8c81e7f34d702 Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Tue, 31 Aug 2021 10:29:08 -0300 Subject: [PATCH 07/12] Added options into xcelium.py taken from #684 Added to ignore a too-many-branches complain of pylint due to the additions. --- vunit/sim_if/xcelium.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/vunit/sim_if/xcelium.py b/vunit/sim_if/xcelium.py index 9a9a2b298..14b69e404 100644 --- a/vunit/sim_if/xcelium.py +++ b/vunit/sim_if/xcelium.py @@ -85,7 +85,7 @@ def supports_vhdl_contexts(): """ Returns True when this simulator supports VHDL 2008 contexts """ - return False + return True def __init__( # pylint: disable=too-many-arguments self, prefix, output_path, gui=False, log_level=None, cdslib=None, hdlvar=None @@ -182,7 +182,7 @@ def _vhdl_std_opt(vhdl_standard): return "-v200x -extv200x" if vhdl_standard == VHDL.STD_2008: - return "-v200x -extv200x" + return "-v200x -extv200x -inc_v200x_pkg" if vhdl_standard == VHDL.STD_1993: return "-v93" @@ -306,7 +306,7 @@ def _get_mapped_libraries(self): cds = CDSFile.parse(self._cdslib) return cds - def simulate( # pylint: disable=too-many-locals + def simulate( # pylint: disable=too-many-locals, too-many-branches self, output_path, test_suite_name, config, elaborate_only=False ): """ @@ -362,6 +362,14 @@ def simulate( # pylint: disable=too-many-locals args += self._generic_args(config.entity_name, config.generics) for library in self._libraries: args += ['-reflib "%s"' % library.directory] + args += ['-input "@set intovf_severity_level ignore"'] + if config.sim_options.get("disable_ieee_warnings", False): + args += [ + '-input "@set pack_assert_off { std_logic_arith numeric_std }"' + ] + args += [ + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level + ] if launch_gui: args += ["-access +rwc"] # args += ['-linedebug'] From 12301ac15be95ac99860581eadcf5618e6beccb2 Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Fri, 10 Sep 2021 19:48:29 -0300 Subject: [PATCH 08/12] tools: add xcelium_verilog_fixup.py --- tools/xcelium_verilog_fixup.py | 59 ++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tools/xcelium_verilog_fixup.py diff --git a/tools/xcelium_verilog_fixup.py b/tools/xcelium_verilog_fixup.py new file mode 100644 index 000000000..e0eca2ede --- /dev/null +++ b/tools/xcelium_verilog_fixup.py @@ -0,0 +1,59 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com + +""" +Perform necessary modifications to VUnit Verilog code to support +Cadence Xcelium +""" + +import os +import re +from pathlib import Path + + +def replace_stop_by_finish(file_name): + """ + Replace $stop by $finish + """ + + with Path(file_name).open("r", encoding="iso-8859-1") as fptr: + text = fptr.read() + + text = text.replace("$stop(", "$finish(") + + with Path(file_name).open("w", encoding="iso-8859-1") as fptr: + fptr.write(text) + + +def add_finish_after_error(file_name): + """ + Add $finish after a $error + """ + + with Path(file_name).open("r", encoding="iso-8859-1") as fptr: + text = fptr.read() + + text = re.sub(r"(\$error\(.*\))", "\\1; $finish(1)", text) + + with Path(file_name).open("w", encoding="iso-8859-1") as fptr: + fptr.write(text) + + +def main(): + """ + Remove xcelium incompatabilities from source code + """ + where = "../vunit/verilog" + root = os.path.abspath(os.path.join(os.path.dirname(__file__), where)) + for base, _, files in os.walk(root): + for file_name in files: + if file_name.endswith(".sv") or file_name.endswith(".svh"): + replace_stop_by_finish(os.path.join(base, file_name)) + add_finish_after_error(os.path.join(base, file_name)) + + +if __name__ == "__main__": + main() From e7fc20642dc06fe681b8c4358b34a6c8194932d0 Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Fri, 10 Sep 2021 20:16:05 -0300 Subject: [PATCH 09/12] Modified to find Xcelium before Incisive --- vunit/sim_if/factory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vunit/sim_if/factory.py b/vunit/sim_if/factory.py index 2ab3a37a0..832722197 100644 --- a/vunit/sim_if/factory.py +++ b/vunit/sim_if/factory.py @@ -11,8 +11,8 @@ import os from .activehdl import ActiveHDLInterface from .ghdl import GHDLInterface -from .incisive import IncisiveInterface from .xcelium import XceliumInterface +from .incisive import IncisiveInterface from .modelsim import ModelSimInterface from .rivierapro import RivieraProInterface from . import BooleanOption, ListOfStringOption, VHDLAssertLevelOption @@ -33,8 +33,8 @@ def supported_simulators(): RivieraProInterface, ActiveHDLInterface, GHDLInterface, - IncisiveInterface, XceliumInterface, + IncisiveInterface, ] def _extract_compile_options(self): From 36d1d17aab25b0eabccb2268f57998ac0868cf3d Mon Sep 17 00:00:00 2001 From: "Rodrigo A. Melo" Date: Sun, 19 Sep 2021 11:43:06 -0300 Subject: [PATCH 10/12] Added test for the Xcelium interface --- tests/unit/test_xcelium_interface.py | 1150 ++++++++++++++++++++++++++ 1 file changed, 1150 insertions(+) create mode 100644 tests/unit/test_xcelium_interface.py diff --git a/tests/unit/test_xcelium_interface.py b/tests/unit/test_xcelium_interface.py new file mode 100644 index 000000000..ed68e421f --- /dev/null +++ b/tests/unit/test_xcelium_interface.py @@ -0,0 +1,1150 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Copyright (c) 2014-2021, Lars Asplund lars.anders.asplund@gmail.com + +# pylint: disable=too-many-public-methods, too-many-lines + +""" +Test the Xcelium interface +""" + + +import unittest +from pathlib import Path +import os +from shutil import rmtree +from unittest import mock +from vunit.sim_if.xcelium import XceliumInterface +from vunit.project import Project +from vunit.ostools import renew_path, write_file, read_file +from vunit.test.bench import Configuration +from vunit.vhdl_standard import VHDL + + +class TestXceliumInterface(unittest.TestCase): + """ + Test the Xcelium interface + """ + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_vhdl_2008( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + project.add_source_file( + "file.vhd", "lib", file_type="vhdl", vhdl_standard=VHDL.standard("2008") + ) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-v200x -extv200x -inc_v200x_pkg", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.log"), + "-quiet", + '-xmlibdirname "."', + "-makelib lib_path", + '"file.vhd"', + "-endlib", + ], + ) + + self.assertEqual( + read_file(str(Path(self.output_path) / "cds.lib")), + """\ +## cds.lib: Defines the locations of compiled libraries. +softinclude cds_root_xrun/tools/inca/files/cds.lib +# needed for referencing the library 'basic' for cells 'cds_alias', 'cds_thru' etc. in analog models: +# NOTE: 'virtuoso' executable not found! +# define basic ".../tools/dfII/etc/cdslib/basic" +define lib "lib_path" +define work "%s/libraries/work" +""" + % self.output_path, + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_vhdl_2002( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + project.add_source_file( + "file.vhd", "lib", file_type="vhdl", vhdl_standard=VHDL.standard("2002") + ) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-v200x -extv200x", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.log"), + "-quiet", + '-xmlibdirname "."', + "-makelib lib_path", + '"file.vhd"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_vhdl_93( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + project.add_source_file( + "file.vhd", "lib", file_type="vhdl", vhdl_standard=VHDL.standard("93") + ) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-v93", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.log"), + "-quiet", + '-xmlibdirname "."', + "-makelib lib_path", + '"file.vhd"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_vhdl_extra_flags( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + source_file = project.add_source_file("file.vhd", "lib", file_type="vhdl") + source_file.set_compile_option("xcelium.xrun_vhdl_flags", ["custom", "flags"]) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-v200x -extv200x -inc_v200x_pkg", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.log"), + "-quiet", + "custom", + "flags", + '-xmlibdirname "."', + "-makelib lib_path", + '"file.vhd"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_vhdl_hdlvar( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface( + prefix="prefix", output_path=self.output_path, hdlvar="custom_hdlvar" + ) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + project.add_source_file("file.vhd", "lib", file_type="vhdl") + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-v200x -extv200x -inc_v200x_pkg", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-hdlvar "custom_hdlvar"', + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_vhdl_file_lib.log"), + "-quiet", + '-xmlibdirname "."', + "-makelib lib_path", + '"file.vhd"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_verilog( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.v", "") + project.add_source_file("file.v", "lib", file_type="verilog") + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_verilog_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn UEXPSC", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_verilog_file_lib.log"), + "-quiet", + '-incdir "cds_root_xrun/tools/spectre/etc/ahdl/"', + '-xmlibdirname "."', + "-makelib lib", + '"file.v"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_system_verilog( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.sv", "") + project.add_source_file("file.sv", "lib", file_type="systemverilog") + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_verilog_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn UEXPSC", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_verilog_file_lib.log"), + "-quiet", + '-incdir "cds_root_xrun/tools/spectre/etc/ahdl/"', + '-xmlibdirname "."', + "-makelib lib", + '"file.sv"', + "-endlib", + ], + ) + + self.assertEqual( + read_file(str(Path(self.output_path) / "cds.lib")), + """\ +## cds.lib: Defines the locations of compiled libraries. +softinclude cds_root_xrun/tools/inca/files/cds.lib +# needed for referencing the library 'basic' for cells 'cds_alias', 'cds_thru' etc. in analog models: +# NOTE: 'virtuoso' executable not found! +# define basic ".../tools/dfII/etc/cdslib/basic" +define lib "lib_path" +define work "%s/libraries/work" +""" + % self.output_path, + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_verilog_extra_flags( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.v", "") + source_file = project.add_source_file("file.v", "lib", file_type="verilog") + source_file.set_compile_option( + "xcelium.xrun_verilog_flags", ["custom", "flags"] + ) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_verilog_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn UEXPSC", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-work work", + "custom", + "flags", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_verilog_file_lib.log"), + "-quiet", + '-incdir "cds_root_xrun/tools/spectre/etc/ahdl/"', + '-xmlibdirname "."', + "-makelib lib", + '"file.v"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_verilog_include( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.v", "") + project.add_source_file( + "file.v", "lib", file_type="verilog", include_dirs=["include"] + ) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_verilog_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn UEXPSC", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_verilog_file_lib.log"), + "-quiet", + '-incdir "include"', + '-incdir "cds_root_xrun/tools/spectre/etc/ahdl/"', + '-xmlibdirname "."', + "-makelib lib", + '"file.v"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_verilog_define( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.v", "") + project.add_source_file( + "file.v", "lib", file_type="verilog", defines=dict(defname="defval") + ) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_verilog_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn UEXPSC", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_verilog_file_lib.log"), + "-quiet", + '-incdir "cds_root_xrun/tools/spectre/etc/ahdl/"', + "-define defname=defval", + '-xmlibdirname "."', + "-makelib lib", + '"file.v"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.check_output", autospec=True, return_value="") + def test_compile_project_verilog_hdlvar( + self, check_output, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface( + prefix="prefix", output_path=self.output_path, hdlvar="custom_hdlvar" + ) + project = Project() + project.add_library("lib", "lib_path") + write_file("file.v", "") + project.add_source_file( + "file.v", "lib", file_type="verilog", defines=dict(defname="defval") + ) + simif.compile_project(project) + args_file = str(Path(self.output_path) / "xrun_compile_verilog_file_lib.args") + check_output.assert_called_once_with( + [str(Path("prefix") / "xrun"), "-f", args_file], env=simif.get_env() + ) + self.assertEqual( + read_file(args_file).splitlines(), + [ + "-compile", + "-nocopyright", + "-licqueue", + "-nowarn UEXPSC", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-work work", + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-hdlvar "custom_hdlvar"', + '-log "%s"' + % str(Path(self.output_path) / "xrun_compile_verilog_file_lib.log"), + "-quiet", + '-incdir "cds_root_xrun/tools/spectre/etc/ahdl/"', + "-define defname=defval", + '-xmlibdirname "."', + "-makelib lib", + '"file.v"', + "-endlib", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + def test_create_cds_lib(self, find_cds_root_xrun, find_cds_root_virtuoso): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + XceliumInterface(prefix="prefix", output_path=self.output_path) + self.assertEqual( + read_file(str(Path(self.output_path) / "cds.lib")), + """\ +## cds.lib: Defines the locations of compiled libraries. +softinclude cds_root_xrun/tools/inca/files/cds.lib +# needed for referencing the library 'basic' for cells 'cds_alias', 'cds_thru' etc. in analog models: +# NOTE: 'virtuoso' executable not found! +# define basic ".../tools/dfII/etc/cdslib/basic" +define work "%s/libraries/work" +""" + % self.output_path, + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + def test_create_cds_lib_virtuoso(self, find_cds_root_xrun, find_cds_root_virtuoso): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = "cds_root_virtuoso" + XceliumInterface(prefix="prefix", output_path=self.output_path) + self.assertEqual( + read_file(str(Path(self.output_path) / "cds.lib")), + """\ +## cds.lib: Defines the locations of compiled libraries. +softinclude cds_root_xrun/tools/inca/files/cds.lib +# needed for referencing the library 'basic' for cells 'cds_alias', 'cds_thru' etc. in analog models: +define basic "cds_root_virtuoso/tools/dfII/etc/cdslib/basic" +define work "%s/libraries/work" +""" + % self.output_path, + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=True) + def test_simulate_vhdl( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + project.add_source_file("file.vhd", "lib", file_type="vhdl") + + with mock.patch( + "vunit.sim_if.check_output", autospec=True, return_value="" + ) as dummy: + simif.compile_project(project) + + config = make_config() + self.assertTrue(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + simulate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_simulate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ), + mock.call( + [str(Path("prefix") / "xrun"), "-f", Path(simulate_args_file).name], + cwd=str(Path(simulate_args_file).parent), + env=simif.get_env(), + ), + ] + ) + + self.assertEqual( + read_file(elaborate_args_file).splitlines(), + [ + "-elaborate", + "-nocopyright", + "-licqueue", + "-errormax 10", + "-nowarn WRMNZD", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-xmerror EVBBOL", + "-xmerror EVBSTR", + "-xmerror EVBNAT", + "-work work", + '-xmlibdirname "%s"' % str(Path(self.output_path) / "libraries"), + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path("suite_output_path") / simif.name / "xrun_elaborate.log"), + "-quiet", + '-reflib "lib_path"', + '-input "@set intovf_severity_level ignore"', + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level, + "-access +r", + '-input "@run"', + "-top lib.ent:arch", + ], + ) + + self.assertEqual( + read_file(simulate_args_file).splitlines(), + [ + "-nocopyright", + "-licqueue", + "-errormax 10", + "-nowarn WRMNZD", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-xmerror EVBBOL", + "-xmerror EVBSTR", + "-xmerror EVBNAT", + "-work work", + '-xmlibdirname "%s"' % str(Path(self.output_path) / "libraries"), + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path("suite_output_path") / simif.name / "xrun_simulate.log"), + "-quiet", + '-reflib "lib_path"', + '-input "@set intovf_severity_level ignore"', + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level, + "-access +r", + '-input "@run"', + "-top lib.ent:arch", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=True) + def test_simulate_verilog( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + project.add_source_file("file.vhd", "lib", file_type="vhdl") + + with mock.patch( + "vunit.sim_if.check_output", autospec=True, return_value="" + ) as dummy: + simif.compile_project(project) + + config = make_config(verilog=True) + self.assertTrue(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + simulate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_simulate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ), + mock.call( + [str(Path("prefix") / "xrun"), "-f", Path(simulate_args_file).name], + cwd=str(Path(simulate_args_file).parent), + env=simif.get_env(), + ), + ] + ) + + self.assertEqual( + read_file(elaborate_args_file).splitlines(), + [ + "-elaborate", + "-nocopyright", + "-licqueue", + "-errormax 10", + "-nowarn WRMNZD", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-xmerror EVBBOL", + "-xmerror EVBSTR", + "-xmerror EVBNAT", + "-work work", + '-xmlibdirname "%s"' % str(Path(self.output_path) / "libraries"), + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path("suite_output_path") / simif.name / "xrun_elaborate.log"), + "-quiet", + '-reflib "lib_path"', + '-input "@set intovf_severity_level ignore"', + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level, + "-access +r", + '-input "@run"', + "-top lib.modulename:sv", + ], + ) + + self.assertEqual( + read_file(simulate_args_file).splitlines(), + [ + "-nocopyright", + "-licqueue", + "-errormax 10", + "-nowarn WRMNZD", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-xmerror EVBBOL", + "-xmerror EVBSTR", + "-xmerror EVBNAT", + "-work work", + '-xmlibdirname "%s"' % str(Path(self.output_path) / "libraries"), + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path("suite_output_path") / simif.name / "xrun_simulate.log"), + "-quiet", + '-reflib "lib_path"', + '-input "@set intovf_severity_level ignore"', + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level, + "-access +r", + '-input "@run"', + "-top lib.modulename:sv", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=True) + def test_simulate_extra_flags( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + config = make_config( + sim_options={"xcelium.xrun_sim_flags": ["custom", "flags"]} + ) + self.assertTrue(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + simulate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_simulate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ), + mock.call( + [str(Path("prefix") / "xrun"), "-f", Path(simulate_args_file).name], + cwd=str(Path(simulate_args_file).parent), + env=simif.get_env(), + ), + ] + ) + + args = read_file(elaborate_args_file).splitlines() + self.assertIn("custom", args) + self.assertIn("flags", args) + + args = read_file(simulate_args_file).splitlines() + self.assertIn("custom", args) + self.assertIn("flags", args) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=True) + def test_simulate_generics_and_parameters( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + config = make_config( + verilog=True, generics={"genstr": "genval", "genint": 1, "genbool": True} + ) + self.assertTrue(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + simulate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_simulate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ), + mock.call( + [str(Path("prefix") / "xrun"), "-f", Path(simulate_args_file).name], + cwd=str(Path(simulate_args_file).parent), + env=simif.get_env(), + ), + ] + ) + + for args_file in [elaborate_args_file, simulate_args_file]: + args = read_file(args_file).splitlines() + self.assertIn('-gpg "modulename.genstr => \\"genval\\""', args) + self.assertIn('-gpg "modulename.genint => 1"', args) + self.assertIn('-gpg "modulename.genbool => \\"True\\""', args) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=True) + def test_simulate_hdlvar( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface( + prefix="prefix", output_path=self.output_path, hdlvar="custom_hdlvar" + ) + config = make_config() + self.assertTrue(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + simulate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_simulate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ), + mock.call( + [str(Path("prefix") / "xrun"), "-f", Path(simulate_args_file).name], + cwd=str(Path(simulate_args_file).parent), + env=simif.get_env(), + ), + ] + ) + + for args_file in [elaborate_args_file, simulate_args_file]: + args = read_file(args_file).splitlines() + self.assertIn('-hdlvar "custom_hdlvar"', args) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=True) + def test_elaborate(self, run_command, find_cds_root_xrun, find_cds_root_virtuoso): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + config = make_config(verilog=True) + self.assertTrue( + simif.simulate( + "suite_output_path", "test_suite_name", config, elaborate_only=True + ) + ) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ) + ] + ) + + self.assertEqual( + read_file(elaborate_args_file).splitlines(), + [ + "-elaborate", + "-nocopyright", + "-licqueue", + "-errormax 10", + "-nowarn WRMNZD", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-xmerror EVBBOL", + "-xmerror EVBSTR", + "-xmerror EVBNAT", + "-work work", + '-xmlibdirname "%s"' % str(Path(self.output_path) / "libraries"), + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path("suite_output_path") / simif.name / "xrun_elaborate.log"), + "-quiet", + '-input "@set intovf_severity_level ignore"', + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level, + "-access +r", + '-input "@run"', + "-top lib.modulename:sv", + ], + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=False) + def test_elaborate_fail( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + config = make_config() + self.assertFalse(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ) + ] + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch( + "vunit.sim_if.xcelium.run_command", autospec=True, side_effect=[True, False] + ) + def test_simulate_fail( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + simif = XceliumInterface(prefix="prefix", output_path=self.output_path) + config = make_config() + self.assertFalse(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + simulate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_simulate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ), + mock.call( + [str(Path("prefix") / "xrun"), "-f", Path(simulate_args_file).name], + cwd=str(Path(simulate_args_file).parent), + env=simif.get_env(), + ), + ] + ) + + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_virtuoso") + @mock.patch("vunit.sim_if.xcelium.XceliumInterface.find_cds_root_xrun") + @mock.patch("vunit.sim_if.xcelium.run_command", autospec=True, return_value=True) + def test_simulate_gui( + self, run_command, find_cds_root_xrun, find_cds_root_virtuoso + ): + find_cds_root_xrun.return_value = "cds_root_xrun" + find_cds_root_virtuoso.return_value = None + + project = Project() + project.add_library("lib", "lib_path") + write_file("file.vhd", "") + project.add_source_file("file.vhd", "lib", file_type="vhdl") + + simif = XceliumInterface( + prefix="prefix", output_path=self.output_path, gui=True + ) + with mock.patch( + "vunit.sim_if.check_output", autospec=True, return_value="" + ) as dummy: + simif.compile_project(project) + config = make_config() + self.assertTrue(simif.simulate("suite_output_path", "test_suite_name", config)) + elaborate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_elaborate.args" + ) + simulate_args_file = str( + Path("suite_output_path") / simif.name / "xrun_simulate.args" + ) + run_command.assert_has_calls( + [ + mock.call( + [ + str(Path("prefix") / "xrun"), + "-f", + Path(elaborate_args_file).name, + ], + cwd=str(Path(elaborate_args_file).parent), + env=simif.get_env(), + ), + mock.call( + [str(Path("prefix") / "xrun"), "-f", Path(simulate_args_file).name], + cwd=str(Path(simulate_args_file).parent), + env=simif.get_env(), + ), + ] + ) + self.assertEqual( + read_file(elaborate_args_file).splitlines(), + [ + "-elaborate", + "-nocopyright", + "-licqueue", + "-errormax 10", + "-nowarn WRMNZD", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-xmerror EVBBOL", + "-xmerror EVBSTR", + "-xmerror EVBNAT", + "-work work", + '-xmlibdirname "%s"' % str(Path(self.output_path) / "libraries"), + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path("suite_output_path") / simif.name / "xrun_elaborate.log"), + "-quiet", + '-reflib "lib_path"', + '-input "@set intovf_severity_level ignore"', + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level, + "-access +rwc", + "-gui", + "-top lib.ent:arch", + ], + ) + + self.assertEqual( + read_file(simulate_args_file).splitlines(), + [ + "-nocopyright", + "-licqueue", + "-errormax 10", + "-nowarn WRMNZD", + "-nowarn DLCPTH", + "-nowarn DLCVAR", + "-xmerror EVBBOL", + "-xmerror EVBSTR", + "-xmerror EVBNAT", + "-work work", + '-xmlibdirname "%s"' % str(Path(self.output_path) / "libraries"), + '-cdslib "%s"' % str(Path(self.output_path) / "cds.lib"), + '-log "%s"' + % str(Path("suite_output_path") / simif.name / "xrun_simulate.log"), + "-quiet", + '-reflib "lib_path"', + '-input "@set intovf_severity_level ignore"', + '-input "@set assert_stop_level %s"' % config.vhdl_assert_stop_level, + "-access +rwc", + "-gui", + "-top lib.ent:arch", + ], + ) + + def setUp(self): + self.output_path = str(Path(__file__).parent / "test_xcelium_out") + renew_path(self.output_path) + self.project = Project() + self.cwd = os.getcwd() + os.chdir(self.output_path) + + def tearDown(self): + os.chdir(self.cwd) + if Path(self.output_path).exists(): + rmtree(self.output_path) + + +def make_config(sim_options=None, generics=None, verilog=False): + """ + Utility to reduce boiler plate in tests + """ + cfg = mock.Mock(spec=Configuration) + cfg.library_name = "lib" + + if verilog: + cfg.entity_name = "modulename" + cfg.architecture_name = None + else: + cfg.entity_name = "ent" + cfg.architecture_name = "arch" + + cfg.sim_options = {} if sim_options is None else sim_options + cfg.generics = {} if generics is None else generics + return cfg From 9d3f446224f2f1a9aadaad1a79cee4801dc67322 Mon Sep 17 00:00:00 2001 From: Joe Warner Date: Fri, 27 May 2022 16:26:21 -0500 Subject: [PATCH 11/12] Fix string type error by decoding bytes returned by subprocess --- vunit/sim_if/incisive.py | 4 ++-- vunit/sim_if/xcelium.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vunit/sim_if/incisive.py b/vunit/sim_if/incisive.py index 60dbf0f84..e57aaaa1f 100644 --- a/vunit/sim_if/incisive.py +++ b/vunit/sim_if/incisive.py @@ -87,14 +87,14 @@ def find_cds_root_irun(self): """ Finds irun cds root """ - return subprocess.check_output([str(Path(self._prefix) / "cds_root"), "irun"]).splitlines()[0] + return subprocess.check_output([str(Path(self._prefix) / "cds_root"), "irun"]).splitlines()[0].decode() def find_cds_root_virtuoso(self): """ Finds virtuoso cds root """ try: - return subprocess.check_output([str(Path(self._prefix) / "cds_root"), "virtuoso"]).splitlines()[0] + return subprocess.check_output([str(Path(self._prefix) / "cds_root"), "virtuoso"]).splitlines()[0].decode() except subprocess.CalledProcessError: return None diff --git a/vunit/sim_if/xcelium.py b/vunit/sim_if/xcelium.py index 14b69e404..f7ef350ed 100644 --- a/vunit/sim_if/xcelium.py +++ b/vunit/sim_if/xcelium.py @@ -108,7 +108,7 @@ def find_cds_root_xrun(self): """ return subprocess.check_output( [str(Path(self._prefix) / "cds_root"), "xrun"] - ).splitlines()[0] + ).splitlines()[0].decode() def find_cds_root_virtuoso(self): """ @@ -117,7 +117,7 @@ def find_cds_root_virtuoso(self): try: return subprocess.check_output( [str(Path(self._prefix) / "cds_root"), "virtuoso"] - ).splitlines()[0] + ).splitlines()[0].decode() except subprocess.CalledProcessError: return None From cd70d5dd2c4a2c40d06656ceda7177417dcc0fff Mon Sep 17 00:00:00 2001 From: Joe Warner Date: Tue, 1 Nov 2022 17:22:26 -0500 Subject: [PATCH 12/12] Working Xcelium + Indago support with single command commpilation plus a basic rerun script. --- tools/xcelium_verilog_fixup.py | 3 +- vunit/configuration.py | 3 +- vunit/project.py | 3 +- vunit/sim_if/__init__.py | 4 +- vunit/sim_if/xcelium.py | 299 ++++++++++++++++++++++-- vunit/source_file.py | 32 ++- vunit/ui/__init__.py | 30 ++- vunit/ui/source.py | 16 ++ vunit/verilog/check/test/check_tb.sv | 4 + vunit/verilog/include/vunit_defines.svh | 8 +- vunit/verilog/vunit_pkg.sv | 30 ++- 11 files changed, 398 insertions(+), 34 deletions(-) diff --git a/tools/xcelium_verilog_fixup.py b/tools/xcelium_verilog_fixup.py index e0eca2ede..0bd276470 100644 --- a/tools/xcelium_verilog_fixup.py +++ b/tools/xcelium_verilog_fixup.py @@ -56,4 +56,5 @@ def main(): if __name__ == "__main__": - main() + #main() + print("nothing to do") diff --git a/vunit/configuration.py b/vunit/configuration.py index b3ea9f1b6..1e0910505 100644 --- a/vunit/configuration.py +++ b/vunit/configuration.py @@ -12,7 +12,7 @@ import inspect from pathlib import Path from copy import copy -from vunit.sim_if.factory import SIMULATOR_FACTORY + LOGGER = logging.getLogger(__name__) @@ -123,6 +123,7 @@ def set_sim_option(self, name, value): """ Set sim option """ + from vunit.sim_if.factory import SIMULATOR_FACTORY SIMULATOR_FACTORY.check_sim_option(name, value) self.sim_options[name] = copy(value) diff --git a/vunit/project.py b/vunit/project.py index 81411749a..d35c94303 100644 --- a/vunit/project.py +++ b/vunit/project.py @@ -27,6 +27,7 @@ ) from vunit.vhdl_standard import VHDL, VHDLStandard from vunit.library import Library +from typing import List LOGGER = logging.getLogger(__name__) @@ -430,7 +431,7 @@ def _get_compile_timestamps(self, files): timestamps[source_file] = ostools.get_modification_time(hash_file_name) return timestamps - def get_files_in_compile_order(self, incremental=True, dependency_graph=None, files=None): + def get_files_in_compile_order(self, incremental=True, dependency_graph=None, files=None) -> List[SourceFile]: """ Get a list of all files in compile order param: incremental: Only return files that need recompile if True diff --git a/vunit/sim_if/__init__.py b/vunit/sim_if/__init__.py index 8b472dd62..78a6b13f3 100644 --- a/vunit/sim_if/__init__.py +++ b/vunit/sim_if/__init__.py @@ -49,6 +49,8 @@ class SimulatorInterface(object): # pylint: disable=too-many-public-methods # True if simulator supports ANSI colors in GUI mode supports_colors_in_gui = False + incremental_compile = True + def __init__(self, output_path, gui): self._output_path = output_path self._gui = gui @@ -259,7 +261,7 @@ def compile_source_files( failures = [] if target_files is None: - source_files = project.get_files_in_compile_order(dependency_graph=dependency_graph) + source_files = project.get_files_in_compile_order(incremental=self.incremental_compile, dependency_graph=dependency_graph) else: source_files = project.get_minimal_file_set_in_compile_order(target_files) diff --git a/vunit/sim_if/xcelium.py b/vunit/sim_if/xcelium.py index f7ef350ed..5cd0fe408 100644 --- a/vunit/sim_if/xcelium.py +++ b/vunit/sim_if/xcelium.py @@ -10,14 +10,24 @@ from pathlib import Path from os.path import relpath +from typing import Dict, List +from copy import copy +import sys import os +import stat import subprocess import logging from ..exceptions import CompileError -from ..ostools import write_file, file_exists +from ..ostools import write_file, file_exists, simplify_path from ..vhdl_standard import VHDL -from . import SimulatorInterface, run_command, ListOfStringOption +from . import SimulatorInterface, run_command, ListOfStringOption, check_output from .cds_file import CDSFile +from ..color_printer import NO_COLOR_PRINTER +from ..configuration import Configuration +from ..project import Project +from vunit.source_file import SourceFile +from vunit.library import Library + LOGGER = logging.getLogger(__name__) @@ -32,13 +42,18 @@ class XceliumInterface( # pylint: disable=too-many-instance-attributes name = "xcelium" supports_gui_flag = True package_users_depend_on_bodies = False + incremental = False compile_options = [ ListOfStringOption("xcelium.xrun_vhdl_flags"), ListOfStringOption("xcelium.xrun_verilog_flags"), + ListOfStringOption("xcelium.xrun_cdslib"), ] - sim_options = [ListOfStringOption("xcelium.xrun_sim_flags")] + sim_options = [ListOfStringOption("xcelium.xrun_sim_flags"), + ListOfStringOption("xcelium.xrun_sim_flags.gui")] + + _global_compile_options: Dict @staticmethod def add_arguments(parser): @@ -58,6 +73,12 @@ def add_arguments(parser): default=None, help="The hdl.var file to use. If not given, VUnit does not use a hdl.var file.", ) + group.add_argument( + "--use_indago", + default=False, + help="Indicate whether to use Indago instead of Simvision when running in GUI mode.", + action="store_true", + ) @classmethod def from_args(cls, args, output_path, **kwargs): @@ -71,6 +92,7 @@ def from_args(cls, args, output_path, **kwargs): gui=args.gui, cdslib=args.cdslib, hdlvar=args.hdlvar, + use_indago=args.use_indago ) @classmethod @@ -80,6 +102,7 @@ def find_prefix_from_path(cls): """ return cls.find_toolchain(["xrun"]) + @staticmethod def supports_vhdl_contexts(): """ @@ -88,9 +111,10 @@ def supports_vhdl_contexts(): return True def __init__( # pylint: disable=too-many-arguments - self, prefix, output_path, gui=False, log_level=None, cdslib=None, hdlvar=None + self, prefix, output_path, gui=False, log_level=None, cdslib=None, hdlvar=None, use_indago=False ): SimulatorInterface.__init__(self, output_path, gui) + self._global_compile_options = {} self._prefix = prefix self._libraries = [] self._log_level = log_level @@ -99,8 +123,9 @@ def __init__( # pylint: disable=too-many-arguments else: self._cdslib = str(Path(cdslib).resolve()) self._hdlvar = hdlvar + self._use_indago = use_indago self._cds_root_xrun = self.find_cds_root_xrun() - self._create_cdslib() + def find_cds_root_xrun(self): """ @@ -116,7 +141,8 @@ def find_cds_root_virtuoso(self): """ try: return subprocess.check_output( - [str(Path(self._prefix) / "cds_root"), "virtuoso"] + [str(Path(self._prefix) / "cds_root"), "virtuoso"], + stderr=subprocess.STDOUT ).splitlines()[0].decode() except subprocess.CalledProcessError: return None @@ -135,6 +161,8 @@ def _create_cdslib(self): # NOTE: 'virtuoso' executable not found! # define basic ".../tools/dfII/etc/cdslib/basic" define work "{1}/libraries/work" + +# user defined cds by changing: global.xcelium.xrun_cdslib """.format( self._cds_root_xrun, self._output_path ) @@ -145,16 +173,40 @@ def _create_cdslib(self): # needed for referencing the library 'basic' for cells 'cds_alias', 'cds_thru' etc. in analog models: define basic "{1}/tools/dfII/etc/cdslib/basic" define work "{2}/libraries/work" + +# user defined cds by changing: global.xcelium.xrun_cdslib """.format( self._cds_root_xrun, cds_root_virtuoso, self._output_path ) + + # add our cdslib customization + xrun_cdslibs = self.get_global_compile_option("xcelium.xrun_cdslib") + for xrun_cdslib in xrun_cdslibs: + contents += xrun_cdslib + "\n" + + + contents += "\n" + contents += "# project libraries \n" write_file(self._cdslib, contents) - def setup_library_mapping(self, project): + def set_global_compile_options(self, global_options: Dict): + self._global_compile_options = global_options + + def get_global_compile_option(self, name): + """ + Return a copy of the compile option list + """ + if name not in self._global_compile_options: + self._global_compile_options[name] = [] + + return copy(self._global_compile_options[name]) + + def setup_library_mapping(self, project: Project): """ Compile project using vhdl_standard """ + self._create_cdslib() mapped_libraries = self._get_mapped_libraries() for library in project.get_libraries(): @@ -171,8 +223,87 @@ def compile_source_file_command(self, source_file): if source_file.is_any_verilog: return self.compile_verilog_file_command(source_file) + LOGGER.error("Unknown file type: %s", source_file.file_type) raise CompileError + def _compile_all_source_files(self, source_files_by_library: Dict[Library, List[SourceFile]], printer): + """ + Compiles all source files and prints status information + """ + try: + command = self.compile_all_files_command(source_files_by_library) + except CompileError: + command = None + printer.write("failed", fg="ri") + printer.write("\n") + printer.write(f"File type not supported by {self.name!s} simulator\n") + + return False + + try: + output = check_output(command, env=self.get_env()) + printer.write("passed", fg="gi") + printer.write("\n") + printer.write(output) + + except subprocess.CalledProcessError as err: + printer.write("failed", fg="ri") + printer.write("\n") + printer.write(f"=== Command used: ===\n{subprocess.list2cmdline(command)!s}\n") + printer.write("\n") + printer.write(f"=== Command output: ===\n{err.output!s}\n") + + return False + + return True + + def compile_source_files( + self, + project: Project, + printer=NO_COLOR_PRINTER, + continue_on_error=False, + target_files=None, + ): + """ + Use compile_source_file_command to compile all source_files + param: target_files: Given a list of SourceFiles only these and dependent files are compiled + """ + dependency_graph = project.create_dependency_graph() + failures = [] + + if target_files is None: + source_files: List[SourceFile] = project.get_files_in_compile_order(dependency_graph=dependency_graph) + else: + source_files: List[SourceFile] = project.get_minimal_file_set_in_compile_order(target_files) + + source_files_to_skip = set() + + max_library_name = 0 + max_source_file_name = 0 + if source_files: + max_library_name = max(len(source_file.library.name) for source_file in source_files) + max_source_file_name = max(len(simplify_path(source_file.name)) for source_file in source_files) + + source_files_by_library: Dict[Library, List[SourceFile]] = {} + for source_file in source_files: + if source_file.library in source_files_by_library: + source_files_by_library[source_file.library].append(source_file) + else: + source_files_by_library[source_file.library] = [source_file] + # import pprint + # pprint.pprint(source_files_by_library) + + printer.write("Compiling all source files") + sys.stdout.flush() + if self._compile_all_source_files(source_files_by_library, printer): + printer.write("All source files compiled!\n") + printer.write("Compile passed\n", fg="gi") + else: + printer.write("One or more source files failed to compile.\n") + printer.write("Compile failed\n", fg="ri") + raise CompileError + + @staticmethod def _vhdl_std_opt(vhdl_standard): """ @@ -189,6 +320,109 @@ def _vhdl_std_opt(vhdl_standard): raise ValueError("Invalid VHDL standard %s" % vhdl_standard) + def _compile_all_files_in_library_subcommand(self, library, source_files): + """ + Return a command to compile all source files in a library + """ + args = [] + args += ["-makelib %s" % library.directory] + search_list = [] + + for source_file in source_files: + unique_args = [] + if source_file.is_vhdl: + unique_args += ["%s" % self._vhdl_std_opt(source_file.get_vhdl_standard())] + unique_args += source_file.get_compile_option("xcelium.xrun_vhdl_flags", include_global=False) + + if source_file.is_any_verilog: + unique_args += source_file.get_compile_option("xcelium.xrun_verilog_flags", include_global=False) + for include_dir in source_file.include_dirs: + if include_dir not in search_list: + search_list.append(include_dir) + for key, value in source_file.defines.items(): + unique_args += ["-define %s=%s" % (key, value.replace('"', '\\"'))] + + args += [source_file.name] + if len(unique_args) > 0: + # args += ["-filemap %s" % source_file.name] + args += unique_args + # args += ["-endfilemap"] + else: + # args += [source_file.name] + pass + + for include_dir in search_list: + args += ['-incdir "%s"' % include_dir] + + args += ["-endlib"] + argsfile = str( + Path(self._output_path) + / ("xrun_compile_library_%s.args" % library.name) + ) + write_file(argsfile, "\n".join(args)) + return ["-F", argsfile] + + + def compile_all_files_command(self, source_files: Dict[Library, List[SourceFile]]): + """ + Return a command to compile all source files + """ + first_library = True + launch_gui = self._gui is not False + use_indago = self._use_indago is not False + + cmd = str(Path(self._prefix) / "xrun") + args = [] + + args += ["-compile"] + args += ["-nocopyright"] + args += ["-licqueue"] + # "Ignored unexpected semicolon following SystemVerilog description keyword (endfunction)." + args += ["-nowarn UEXPSC"] + # "cds.lib Invalid path" + args += ["-nowarn DLCPTH"] + # "cds.lib Invalid environment variable ''." + args += ["-nowarn DLCVAR"] + args += ['-cdslib "%s"' % self._cdslib] + args += self._hdlvar_args() + args += [ + '-log "%s"' + % str( + Path(self._output_path) + / ("xrun_compile_all.log") + ) + ] + if not self._log_level == "debug": + args += ["-quiet"] + else: + args += ["-messages"] + args += ["-libverbose"] + # for "disciplines.vams" etc. + args += ['-incdir "%s/tools/spectre/etc/ahdl/"' % self._cds_root_xrun] + + args += self.get_global_compile_option("xcelium.xrun_vhdl_flags") + args += self.get_global_compile_option("xcelium.xrun_verilog_flags") + + args += ["-define XCELIUM "] + if launch_gui and use_indago: + args += ["-debug_opts indago_interactive"] + args += ["-linedebug"] + #args += ["-uvmlinedebug"] + + for library, _source_files in source_files.items(): + if first_library: + args += ['-xmlibdirname "%s"' % str(Path(library.directory).parent)] + first_library = False + + args += self._compile_all_files_in_library_subcommand(library, _source_files) + + argsfile = str( + Path(self._output_path) + / ("xrun_compile_all.args") + ) + write_file(argsfile, "\n".join(args)) + return [cmd, "-F", argsfile, "-clean"] + def compile_vhdl_file_command(self, source_file): """ Returns command to compile a VHDL file @@ -201,7 +435,6 @@ def compile_vhdl_file_command(self, source_file): args += ["-nowarn DLCPTH"] # "cds.lib Invalid path" args += ["-nowarn DLCVAR"] # "cds.lib Invalid environment variable ''." args += ["%s" % self._vhdl_std_opt(source_file.get_vhdl_standard())] - args += ["-work work"] args += ['-cdslib "%s"' % self._cdslib] args += self._hdlvar_args() args += [ @@ -226,7 +459,7 @@ def compile_vhdl_file_command(self, source_file): / ("xrun_compile_vhdl_file_%s.args" % source_file.library.name) ) write_file(argsfile, "\n".join(args)) - return [cmd, "-f", argsfile] + return [cmd, "-F", argsfile] def compile_verilog_file_command(self, source_file): """ @@ -243,7 +476,6 @@ def compile_verilog_file_command(self, source_file): args += ["-nowarn DLCPTH"] # "cds.lib Invalid environment variable ''." args += ["-nowarn DLCVAR"] - args += ["-work work"] args += source_file.compile_options.get("xcelium.xrun_verilog_flags", []) args += ['-cdslib "%s"' % self._cdslib] args += self._hdlvar_args() @@ -276,7 +508,7 @@ def compile_verilog_file_command(self, source_file): / ("xrun_compile_verilog_file_%s.args" % source_file.library.name) ) write_file(argsfile, "\n".join(args)) - return [cmd, "-f", argsfile] + return [cmd, "-F", argsfile] def create_library(self, library_name, library_path, mapped_libraries=None): """ @@ -307,7 +539,7 @@ def _get_mapped_libraries(self): return cds def simulate( # pylint: disable=too-many-locals, too-many-branches - self, output_path, test_suite_name, config, elaborate_only=False + self, output_path, test_suite_name, config:Configuration, elaborate_only=False ): """ Elaborates and Simulates with entity as top level using generics @@ -315,6 +547,21 @@ def simulate( # pylint: disable=too-many-locals, too-many-branches script_path = str(Path(output_path) / self.name) launch_gui = self._gui is not False and not elaborate_only + use_indago = self._use_indago is not False + + + rerun_file_path="%s/rerun.sh" % script_path + rerun_content=[] + rerun_content+=["#/bin/bash"] + rerun_content+=["set -euo pipefail"] + rerun_content+=["echo 'running compile all'"] + rerun_content+=["xrun -F %s/xrun_compile_all.args" % Path(self._output_path)] + rerun_content+=["echo 'running elaborate'"] + rerun_content+=["xrun -F %s/xrun_elaborate.args" % script_path] + write_file(rerun_file_path, "\n".join(rerun_content)) + st = os.stat(rerun_file_path) + os.chmod(rerun_file_path, st.st_mode | stat.S_IEXEC) + if elaborate_only: steps = ["elaborate"] @@ -346,11 +593,11 @@ def simulate( # pylint: disable=too-many-locals, too-many-branches args += [ "-xmerror EVBNAT" ] # promote to error: "bad natural literal in generic association" - args += ["-work work"] args += [ '-xmlibdirname "%s"' % (str(Path(self._output_path) / "libraries")) ] # @TODO: ugly args += config.sim_options.get("xcelium.xrun_sim_flags", []) + args += ['-cdslib "%s"' % self._cdslib] args += self._hdlvar_args() args += ['-log "%s"' % str(Path(script_path) / ("xrun_%s.log" % step))] @@ -372,8 +619,27 @@ def simulate( # pylint: disable=too-many-locals, too-many-branches ] if launch_gui: args += ["-access +rwc"] - # args += ['-linedebug'] - args += ["-gui"] + args += ['-linedebug'] + args += ['-classlinedebug'] + if use_indago: + args += ["-debug_opts indago_interactive"] + if step == "elaborate": + args += ['-persistent_sources_debug'] + else: + args += ["-nolock"] + else: + # Use simvision + args += ["-gui"] + + if step == "elaborate": + pass + #args += ["-uvmlinedebug"] + + gui_options = config.sim_options.get("xcelium.xrun_sim_flags.gui", []) + if gui_options is not None: + args = gui_options + args + else: + args += ['-input "@run"'] else: args += ["-access +r"] args += ['-input "@run"'] @@ -394,11 +660,12 @@ def simulate( # pylint: disable=too-many-locals, too-many-branches argsfile = "%s/xrun_%s.args" % (script_path, step) write_file(argsfile, "\n".join(args)) if not run_command( - [cmd, "-f", relpath(argsfile, script_path)], + [cmd, "-F", relpath(argsfile, script_path)], cwd=script_path, env=self.get_env(), ): return False + return True def _hdlvar_args(self): diff --git a/vunit/source_file.py b/vunit/source_file.py index c0ae6e0a7..7cc05ab91 100644 --- a/vunit/source_file.py +++ b/vunit/source_file.py @@ -8,11 +8,10 @@ Functionality to represent and operate on VHDL and Verilog source files """ from pathlib import Path -from typing import Union +from typing import Union, Dict import logging from copy import copy import traceback -from vunit.sim_if.factory import SIMULATOR_FACTORY from vunit.hashing import hash_string from vunit.vhdl_parser import VHDLReference from vunit.cached import file_content_hash @@ -28,14 +27,16 @@ class SourceFile(object): """ Represents a generic source file """ + _global_compile_options: Dict def __init__(self, name, library, file_type): self.name = name - self.library = library - self.file_type = file_type + self.library: Library = library + self.file_type: str = file_type self.design_units = [] self._content_hash = None self._compile_options = {} + self._global_compile_options = {} # The file name before preprocessing self.original_name = name @@ -74,6 +75,7 @@ def set_compile_option(self, name, value): """ Set compile option """ + from vunit.sim_if.factory import SIMULATOR_FACTORY SIMULATOR_FACTORY.check_compile_option(name, value) self._compile_options[name] = copy(value) @@ -81,6 +83,7 @@ def add_compile_option(self, name, value): """ Add compile option """ + from vunit.sim_if.factory import SIMULATOR_FACTORY SIMULATOR_FACTORY.check_compile_option(name, value) if name not in self._compile_options: @@ -88,28 +91,41 @@ def add_compile_option(self, name, value): else: self._compile_options[name] += value + def set_global_compile_options(self, global_options: Dict): + self._global_compile_options = global_options + @property def compile_options(self): return self._compile_options - def get_compile_option(self, name): + def get_compile_option(self, name, include_global=True): """ Return a copy of the compile option list """ + from vunit.sim_if.factory import SIMULATOR_FACTORY SIMULATOR_FACTORY.check_compile_option_name(name) if name not in self._compile_options: self._compile_options[name] = [] - return copy(self._compile_options[name]) + if include_global and name in self._global_compile_options: + return copy(self._compile_options[name] + self._global_compile_options[name]) + else: + return copy(self._compile_options[name]) - def _compile_options_hash(self): + def _compile_options_hash(self, include_global=True): """ Compute hash of compile options Needs to be updated if there are nested dictionaries """ - return hash_string(repr(sorted(self._compile_options.items()))) + if include_global: + return hash_string( + repr(sorted(self._compile_options.items())) + + repr(sorted(self._global_compile_options.items())) + ) + else: + return hash_string(repr(sorted(self._compile_options.items()))) @property def content_hash(self): diff --git a/vunit/ui/__init__.py b/vunit/ui/__init__.py index 67e22a6ec..848449e2d 100644 --- a/vunit/ui/__init__.py +++ b/vunit/ui/__init__.py @@ -16,7 +16,8 @@ import logging import json import os -from typing import Optional, Set, Union +from copy import copy +from typing import Optional, Set, Union, Dict from pathlib import Path from fnmatch import fnmatch @@ -54,6 +55,7 @@ class VUnit(object): # pylint: disable=too-many-instance-attributes, too-many-p from vunit import VUnit """ + _global_compile_options : Dict @classmethod def from_argv( @@ -190,6 +192,7 @@ def test_filter(name, attribute_names): """ ) print(hline) + self._global_compile_options = {} def _create_database(self): """ @@ -489,6 +492,26 @@ def add_compile_option(self, name: str, value: str, allow_empty: Optional[bool] for source_file in check_not_empty(source_files, allow_empty, "No source files found"): source_file.add_compile_option(name, value) + + def set_global_compile_options(self, name: str, value: str, allow_empty: Optional[bool] = False): + self._global_compile_options[name] = copy(value) + + source_files = self._project.get_source_files_in_order() + for source_file in check_not_empty(source_files, allow_empty, "No source files found"): + source_file.set_global_compile_options(self._global_compile_options) + + + def add_global_compile_options(self, name: str, value: str, allow_empty: Optional[bool] = False): + if name not in self._global_compile_options: + self._global_compile_options[name] = copy(value) + else: + self._global_compile_options[name] += value + + source_files = self._project.get_source_files_in_order() + for source_file in check_not_empty(source_files, allow_empty, "No source files found"): + source_file.set_global_compile_options(self._global_compile_options) + + def get_source_file(self, file_name: Union[str, Path], library_name: Optional[str] = None): """ Get a source file @@ -795,6 +818,11 @@ def _main_run(self, post_run): Main with running tests """ simulator_if = self._create_simulator_if() + try: + simulator_if.set_global_compile_options(self._global_compile_options) + except Exception as e: + pass + test_list = self._create_tests(simulator_if) self._compile(simulator_if) print() diff --git a/vunit/ui/source.py b/vunit/ui/source.py index 8244034ee..5eaf87f14 100644 --- a/vunit/ui/source.py +++ b/vunit/ui/source.py @@ -7,6 +7,7 @@ """ UI classes SourceFile and SourceFileList """ +from typing import Dict from .. import ostools @@ -15,9 +16,11 @@ class SourceFileList(list): """ A list of :class:`.SourceFile` """ + _global_compile_options : Dict def __init__(self, source_files): list.__init__(self, source_files) + self._global_compile_options = {} def set_compile_option(self, name, value): """ @@ -45,6 +48,11 @@ def add_compile_option(self, name, value): for source_file in self: source_file.add_compile_option(name, value) + def set_global_compile_options(self, global_options: Dict): + self._global_compile_options = global_options + for source_file in self: + source_file.set_global_compile_options(global_options) + def add_dependency_on(self, source_file): """ Add manual dependency of these files on other file(s) @@ -66,11 +74,13 @@ class SourceFile(object): """ A single file """ + _global_compile_options : Dict def __init__(self, source_file, project, ui): self._source_file = source_file self._project = project self._ui = ui + self._global_compile_options = {} @property def name(self): @@ -129,6 +139,12 @@ def get_compile_option(self, name): """ return self._source_file.get_compile_option(name) + def set_global_compile_options(self, global_options: Dict): + self._global_compile_options = global_options + + def get_global_compile_options(self): + return self._global_compile_options + def add_dependency_on(self, source_file): """ Add manual dependency of this file other file(s) diff --git a/vunit/verilog/check/test/check_tb.sv b/vunit/verilog/check/test/check_tb.sv index 18501fc6e..08482c030 100644 --- a/vunit/verilog/check/test/check_tb.sv +++ b/vunit/verilog/check/test/check_tb.sv @@ -43,6 +43,10 @@ module check_tb; begin $sformat(err_msg, "CHECK_EQUAL_ERROR: Failure message not as expected.\n RECV: |%f|\n EXP: |%f|\n", actual, expected); $error(err_msg); + `ifdef XCELIUM + $finish(1); + `else + `endif end; endfunction; `TEST_SUITE begin diff --git a/vunit/verilog/include/vunit_defines.svh b/vunit/verilog/include/vunit_defines.svh index 651f08882..a86d0ba2a 100644 --- a/vunit/verilog/include/vunit_defines.svh +++ b/vunit/verilog/include/vunit_defines.svh @@ -26,7 +26,13 @@ `define TEST_CASE_SETUP if (__runner__.is_test_case_setup()) `define TEST_CASE_CLEANUP if (__runner__.is_test_case_cleanup()) -`define __ERROR_FUNC(msg) $error(msg) + +`ifdef XCELIUM + `define __ERROR_FUNC(msg) $error(msg); $finish(1) +`else + `define __ERROR_FUNC(msg) $error(msg) +`endif + `define CREATE_ARG_STRING(arg, arg_str) \ $swrite(arg_str, arg); \ for (int i=0; i