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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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