diff --git a/docs/news.d/1201.breaking.rst b/docs/news.d/1201.breaking.rst new file mode 100644 index 000000000..6d5d549aa --- /dev/null +++ b/docs/news.d/1201.breaking.rst @@ -0,0 +1,9 @@ +``vunit.vivado`` has been removed. Vivado support is now provided through a separate package. + +Install it with: + +.. code-block:: shell + + pip install vunit-vivado + +Then import ``vunit_vivado.vivado`` instead of ``vunit.vivado``. diff --git a/examples/vhdl/vivado/generate_vivado_project.py b/examples/vhdl/vivado/generate_vivado_project.py deleted file mode 100644 index cacd22ecb..000000000 --- a/examples/vhdl/vivado/generate_vivado_project.py +++ /dev/null @@ -1,21 +0,0 @@ -# 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-2026, Lars Asplund lars.anders.asplund@gmail.com - -from pathlib import Path -from shutil import rmtree -from vunit.vivado import run_vivado - - -def main(): - root = Path(__file__).parent.resolve() - project_name = "myproject" - if (root / project_name).exists(): - rmtree(root / project_name) - run_vivado(root / "tcl" / "generate_project.tcl", tcl_args=[root, "myproject"]) - - -if __name__ == "__main__": - main() diff --git a/examples/vhdl/vivado/readme.md b/examples/vhdl/vivado/readme.md deleted file mode 100644 index 99ee9df5a..000000000 --- a/examples/vhdl/vivado/readme.md +++ /dev/null @@ -1,44 +0,0 @@ -# Vivado and VUnit example -The purpose of this example is to show an example of how compilation -and behavioral simulation of Vivado IPs can be performed in a VUnit -project. In this example a simple Vivado project with a single fifo IP -is generated by a script. The Vivado project is generated just to have -a project for the example and is beside the point. The user can -substitute his or her manually created or generated project. - -The example demonstrates two key tasks to automate simulation with Vivado: - -1. Compile the Vivado standard libraries; unisim, etc using the - simulator of choice and add them to VUnit as external libraries. If - the user have these libraries pre-compiled in some other for they - can skip this automation and add them as external libraries - manually. - -2. Generate the behavioral simulation files for all IP:s (XCI-files) within a - project and add them to the VUnit project. - -Tested with Vivado 2018.1 and RivieraPro on a Windows 10 machine. -Should work on Linux or with Modelsim as well, if it does not let us know. - -## Outputs -Created by generate_vivado_project.py: -- Vivado project is generated into myproject together with ip in my_project_ip. - -Created by run.py -- Standard libraries are compiled into vivado_libs/standard/ -- Project ip libraries are compiled into vivado_libs/project_ip/ - -Project and standard libraries are are re-used and not re-compiled on -subsequent run.py invocations. Remove the project ip folder when -changeing the project to cause re-compilation. - -## Running -```shell -python generate_vivado_project.py -python run.py -``` - -## Requirements -- Vivado should be available in the [PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable. -- VUnit -- A simulator supported by Vivado diff --git a/examples/vhdl/vivado/run.py b/examples/vhdl/vivado/run.py deleted file mode 100644 index 9920eafb5..000000000 --- a/examples/vhdl/vivado/run.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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-2026, Lars Asplund lars.anders.asplund@gmail.com - -""" -Vivado IP ---------- - -Demonstrates compiling and performing behavioral simulation of -Vivado IPs with VUnit. -""" - -from pathlib import Path -from vunit import VUnit -from vivado_util import add_vivado_ip - -ROOT = Path(__file__).parent -SRC_PATH = ROOT / "src" - -VU = VUnit.from_argv() -VU.add_vhdl_builtins() - -VU.add_library("lib").add_source_files(SRC_PATH / "*.vhd") -VU.add_library("tb_lib").add_source_files(SRC_PATH / "test" / "*.vhd") - -add_vivado_ip( - VU, - output_path=ROOT / "vivado_libs", - project_file=ROOT / "myproject" / "myproject.xpr", -) - -VU.main() diff --git a/examples/vhdl/vivado/src/test/tb_top.vhd b/examples/vhdl/vivado/src/test/tb_top.vhd deleted file mode 100644 index e67897da7..000000000 --- a/examples/vhdl/vivado/src/test/tb_top.vhd +++ /dev/null @@ -1,87 +0,0 @@ --- 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-2026, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library vunit_lib; -context vunit_lib.vunit_context; - -library lib; - -entity tb_top is - generic (runner_cfg : string); -end entity; - -architecture tb of tb_top is - signal clk : std_logic := '0'; - signal rstn : std_logic := '0'; - signal in_valid : std_logic := '0'; - signal in_ready : std_logic; - signal in_data : std_logic_vector(7 downto 0) := (others => '0'); - signal out_valid : std_logic; - signal out_ready : std_logic := '0'; - signal out_data : std_logic_vector(7 downto 0); - - constant num_data : integer := 128; - signal start, done : boolean := false; -begin - main : process - begin - test_runner_setup(runner, runner_cfg); - - wait until rising_edge(clk); - wait until rising_edge(clk); - rstn <= '1'; - wait until rising_edge(clk); - - start <= true; - wait until done; - test_runner_cleanup(runner); - end process; - - stimuli : process - begin - wait until start and rising_edge(clk); - for i in 1 to num_data loop - info("input " & integer'image(i) & " of " & integer'image(num_data)); - in_valid <= '1'; - in_data <= std_logic_vector(to_unsigned(i, in_data'length)); - wait until (in_ready and in_valid) = '1' and rising_edge(clk); - in_valid <= '0'; - end loop; - wait; - end process; - - data_check : process - begin - wait until start and rising_edge(clk); - for i in 1 to num_data loop - info("output " & integer'image(i) & " of " & integer'image(num_data)); - out_ready <= '1'; - wait until (out_valid and out_ready) = '1' and rising_edge(clk); - out_ready <= '0'; - check_equal(unsigned(out_data), i); - end loop; - done <= true; - wait; - end process; - - clk <= not clk after 1 ns; - dut : entity lib.top - port map ( - clk => clk, - rstn => rstn, - in_valid => in_valid, - in_ready => in_ready, - in_data => in_data, - out_valid => out_valid, - out_ready => out_ready, - out_data => out_data); - - test_runner_watchdog(runner, 1 ms); -end architecture; diff --git a/examples/vhdl/vivado/src/top.vhd b/examples/vhdl/vivado/src/top.vhd deleted file mode 100644 index 9644fdc7b..000000000 --- a/examples/vhdl/vivado/src/top.vhd +++ /dev/null @@ -1,51 +0,0 @@ --- 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-2026, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -library xil_defaultlib; - --- A simple entity just for example -entity top is - port ( - clk : in std_logic; - rstn : in std_logic; - in_valid : in std_logic; - in_ready : out std_logic; - in_data : in std_logic_vector(7 downto 0); - out_valid : out std_logic; - out_ready : in std_logic; - out_data : out std_logic_vector(7 downto 0)); -end entity; - - -architecture arch of top is - component fifo_8b_32w is - port ( - s_aclk : IN STD_LOGIC; - s_aresetn : IN STD_LOGIC; - s_axis_tvalid : IN STD_LOGIC; - s_axis_tready : OUT STD_LOGIC; - s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0); - m_axis_tvalid : OUT STD_LOGIC; - m_axis_tready : IN STD_LOGIC; - m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); - end component fifo_8b_32w; -begin - -- Just pass through data to prove that component is not a black box - -- and that compiled ip simulation model is used - fifo_8b_32w_inst : component fifo_8b_32w - port map ( - s_aclk => clk, - s_aresetn => rstn, - s_axis_tvalid => in_valid, - s_axis_tready => in_ready, - s_axis_tdata => in_data, - m_axis_tvalid => out_valid, - m_axis_tready => out_ready, - m_axis_tdata => out_data); -end architecture; diff --git a/examples/vhdl/vivado/tcl/compile_standard_libs.tcl b/examples/vhdl/vivado/tcl/compile_standard_libs.tcl deleted file mode 100644 index 7c7b5a3d1..000000000 --- a/examples/vhdl/vivado/tcl/compile_standard_libs.tcl +++ /dev/null @@ -1,26 +0,0 @@ -set simulator_name [lindex $argv 0] -set simulator_exec_path [lindex $argv 1] -set output_path [lindex $argv 2] - -puts "simulator_name=${simulator_name}" -puts "simulator_exec_path=${simulator_exec_path}" -puts "output_path=${output_path}" - -set_param general.maxThreads 8 - -# If you do not have System Verilog Assert license -config_compile_simlib -reset -config_compile_simlib -cfgopt {riviera.verilog.xpm:-sv2k12 -na sva} - -compile_simlib -force \ - -language all \ - -simulator ${simulator_name} \ - -32bit \ - -verbose \ - -library unisim \ - -library simprim \ - -library xpm \ - -family all \ - -no_ip_compile \ - -simulator_exec_path ${simulator_exec_path} \ - -directory ${output_path} diff --git a/examples/vhdl/vivado/tcl/generate_project.tcl b/examples/vhdl/vivado/tcl/generate_project.tcl deleted file mode 100644 index b128323a1..000000000 --- a/examples/vhdl/vivado/tcl/generate_project.tcl +++ /dev/null @@ -1,26 +0,0 @@ -# Create a Vivado project to suit the needs of this example -# the reader of this example could generate his vivado project in a similar maner or -# have a manually maintained project. - -set root [lindex ${argv} 0] -set project_name [lindex ${argv} 1] - -# Create project -create_project -force myproject ${root}/${project_name} - -# Configure general project settings -set obj [get_projects myproject] -set_property "default_lib" "xil_defaultlib" $obj -set_property "part" "xc7z010clg400-1" $obj - -set_property "simulator_language" "Mixed" $obj -set_property "source_mgmt_mode" "DisplayOnly" $obj -set_property "target_language" "VHDL" $obj - -# Create ip directory -set ip_dir ${root}/${project_name}_ip -file mkdir ${ip_dir} - -# Create one fifo as an example of an IP -create_ip -name fifo_generator -vendor xilinx.com -library ip -module_name fifo_8b_32w -dir ${ip_dir} -set_property -dict [list CONFIG.INTERFACE_TYPE {AXI_STREAM} CONFIG.TDATA_NUM_BYTES {1} CONFIG.TUSER_WIDTH {0} CONFIG.FIFO_Implementation_axis {Common_Clock_Distributed_RAM} CONFIG.Input_Depth_axis {32} CONFIG.TSTRB_WIDTH {1} CONFIG.TKEEP_WIDTH {1} CONFIG.FIFO_Implementation_wach {Common_Clock_Distributed_RAM} CONFIG.Full_Threshold_Assert_Value_wach {15} CONFIG.Empty_Threshold_Assert_Value_wach {14} CONFIG.FIFO_Implementation_wrch {Common_Clock_Distributed_RAM} CONFIG.Full_Threshold_Assert_Value_wrch {15} CONFIG.Empty_Threshold_Assert_Value_wrch {14} CONFIG.FIFO_Implementation_rach {Common_Clock_Distributed_RAM} CONFIG.Full_Threshold_Assert_Value_rach {15} CONFIG.Empty_Threshold_Assert_Value_rach {14} CONFIG.Full_Threshold_Assert_Value_axis {31} CONFIG.Empty_Threshold_Assert_Value_axis {30}] [get_ips fifo_8b_32w] diff --git a/examples/vhdl/vivado/vivado_util.py b/examples/vhdl/vivado/vivado_util.py deleted file mode 100644 index a38fc6310..000000000 --- a/examples/vhdl/vivado/vivado_util.py +++ /dev/null @@ -1,89 +0,0 @@ -# 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-2026, Lars Asplund lars.anders.asplund@gmail.com - -import sys -from pathlib import Path -from vunit.sim_if.factory import SIMULATOR_FACTORY -from vunit.vivado import ( - run_vivado, - add_from_compile_order_file, - create_compile_order_file, -) - - -def add_vivado_ip(vunit_obj, output_path, project_file): - """ - Add vivado (and compile if necessary) vivado ip to vunit project. - """ - - if not Path(project_file).exists(): - print("Could not find vivado project %s" % project_file) - sys.exit(1) - - opath = Path(output_path) - - standard_library_path = str(opath / "standard") - compile_standard_libraries(vunit_obj, standard_library_path) - - project_ip_path = str(opath / "project_ip") - add_project_ip(vunit_obj, project_file, project_ip_path) - - -def compile_standard_libraries(vunit_obj, output_path): - """ - Compile Xilinx standard libraries using Vivado TCL command - """ - done_token = Path(output_path) / "all_done.txt" - - simulator_class = SIMULATOR_FACTORY.select_simulator() - - if not done_token.exists(): - print("Compiling standard libraries into %s ..." % str(Path(output_path).resolve())) - simname = simulator_class.name - - # Vivado calls rivierapro for riviera - if simname == "rivierapro": - simname = "riviera" - - run_vivado( - str(Path(__file__).parent / "tcl" / "compile_standard_libs.tcl"), - tcl_args=[ - simname, - simulator_class.find_prefix().replace("\\", "/"), - output_path, - ], - ) - - else: - print("Standard libraries already exists in %s, skipping" % str(Path(output_path).resolve())) - - for library_name in ["unisim", "unimacro", "unifast", "secureip", "xpm"]: - path = str(Path(output_path) / library_name) - if Path(path).exists(): - vunit_obj.add_external_library(library_name, path) - - with done_token.open("w") as fptr: - fptr.write("done") - - -def add_project_ip(vunit_obj, project_file, output_path, vivado_path=None, clean=False): - """ - Add all IP files from Vivado project to the vunit project - - Caching is used to save time where Vivado is not called again if the compile order already exists. - If Clean is True the compile order is always re-generated - - returns the list of SourceFile objects added - """ - - compile_order_file = str(Path(output_path) / "compile_order.txt") - - if clean or not Path(compile_order_file).exists(): - create_compile_order_file(project_file, compile_order_file, vivado_path=vivado_path) - else: - print("Vivado project Compile order already exists, re-using: %s" % str(Path(compile_order_file).resolve())) - - return add_from_compile_order_file(vunit_obj, compile_order_file) diff --git a/pyproject.toml b/pyproject.toml index 6e911e28e..fdb585d33 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ include-package-data = false where = ["."] include = [ "vunit", "vunit.com", "vunit.parsing","vunit.parsing.verilog", "vunit.sim_if", - "vunit.test", "vunit.ui", "vunit.vivado" + "vunit.test", "vunit.ui" ] [tool.black] diff --git a/vunit/vivado/__init__.py b/vunit/vivado/__init__.py index f78c8bfa8..aaeb477f4 100644 --- a/vunit/vivado/__init__.py +++ b/vunit/vivado/__init__.py @@ -4,12 +4,13 @@ # # Copyright (c) 2014-2026, Lars Asplund lars.anders.asplund@gmail.com -""" -Utilities for integrating with Vivado -""" - -from vunit.vivado.vivado import ( - run_vivado, - add_from_compile_order_file, - create_compile_order_file, -) +"""Deprecated package.""" + +raise RuntimeError("""\ +vunit.vivado has been removed. Vivado support is now provided through a separate package. + +Install it with: + +pip install vunit-vivado + +Then import vunit_vivado.vivado instead of vunit.vivado.""") diff --git a/vunit/vivado/tcl/extract_compile_order.tcl b/vunit/vivado/tcl/extract_compile_order.tcl deleted file mode 100644 index a087e744a..000000000 --- a/vunit/vivado/tcl/extract_compile_order.tcl +++ /dev/null @@ -1,15 +0,0 @@ -set project_file [lindex $argv 0] -set output_file [lindex $argv 1] - -open_project ${project_file} - -set file_out [open ${output_file} w] -foreach ip [get_ips -filter {SCOPE == ""}] { - generate_target {simulation synthesis} ${ip} - foreach src_file [get_files -used_in simulation -compile_order sources -of_objects ${ip}] { - set library [get_property LIBRARY ${src_file}] - set file_type [get_property FILE_TYPE ${src_file}] - puts ${file_out} "${library},${file_type},${src_file}" - } -} -close ${file_out} diff --git a/vunit/vivado/vivado.py b/vunit/vivado/vivado.py deleted file mode 100644 index ca4c2ea5d..000000000 --- a/vunit/vivado/vivado.py +++ /dev/null @@ -1,130 +0,0 @@ -# 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-2026, Lars Asplund lars.anders.asplund@gmail.com - -""" -Utilities for integrating with Vivado -""" - -from subprocess import check_call -from os import makedirs -from pathlib import Path - - -def add_from_compile_order_file( - vunit_obj, compile_order_file, dependency_scan_defaultlib=True, fail_on_non_hdl_files=True -): # pylint: disable=too-many-locals - """ - Add Vivado IP:s from a compile order file - """ - compile_order, libraries, include_dirs = _read_compile_order(compile_order_file, fail_on_non_hdl_files) - - # Create libraries - for library_name in libraries: - vunit_obj.add_library(library_name, vhdl_standard="93") - - # Add all source files to VUnit - source_files = [] - - no_dependency_scan = [] - with_dependency_scan = [] - for library_name, file_name in compile_order: - is_verilog = file_name.endswith(".v") or file_name.endswith(".vp") - - # Optionally use VUnit dependency scanning for everything in xil_defaultlib, which - # typically contains unencrypted top levels that instantiate encrypted implementations. - scan_dependencies = dependency_scan_defaultlib and library_name == "xil_defaultlib" - source_file = vunit_obj.library(library_name).add_source_file( - file_name, - no_parse=not scan_dependencies, - include_dirs=include_dirs if is_verilog else None, - ) - - if scan_dependencies: - with_dependency_scan.append(source_file) - else: - no_dependency_scan.append(source_file) - - source_files.append(source_file) - - # Use hardcoded dependency for everthing outside of xil_defaultlib - for idx in range(1, len(no_dependency_scan)): - no_dependency_scan[idx].add_dependency_on(no_dependency_scan[idx - 1]) - - # Add dependency of last item in non-dependency scanned files to the each scanned file - if no_dependency_scan: - for source_file in with_dependency_scan: - source_file.add_dependency_on(no_dependency_scan[-1]) - - return source_files - - -def create_compile_order_file(project_file, compile_order_file, vivado_path=None): - """ - Create compile file from Vivado project - """ - print(f"Generating Vivado project compile order into {str(Path(compile_order_file).resolve())} ...") - - fpath = Path(compile_order_file) - if not fpath.parent.exists(): - makedirs(str(fpath.parent)) - - print("Extracting compile order ...") - run_vivado( - str(Path(__file__).parent / "tcl" / "extract_compile_order.tcl"), - tcl_args=[project_file, compile_order_file], - vivado_path=vivado_path, - ) - - -def _read_compile_order(file_name, fail_on_non_hdl_files): - """ - Read the compile order file and filter out duplicate files - """ - compile_order = [] - unique = set() - include_dirs = set() - libraries = set() - - with Path(file_name).open("r", encoding="utf-8") as ifile: - for line in ifile.readlines(): - library_name, file_type, file_name = line.strip().split(",", 2) - - if file_type not in ("Verilog", "VHDL", "Verilog Header"): - if fail_on_non_hdl_files: - raise RuntimeError(f"Unsupported compile order file: {file_name}") - print(f"Compile order file ignored: {file_name}") - continue - - libraries.add(library_name) - - # Vivado generates duplicate files for different IP:s - # using the same underlying libraries. We remove duplicates here - key = (library_name, Path(file_name).name) - if key in unique: - continue - unique.add(key) - - if file_type == "Verilog Header": - include_dirs.add(str(Path(file_name).parent)) - else: - compile_order.append((library_name, file_name)) - - return compile_order, libraries, list(sorted(include_dirs)) - - -def run_vivado(tcl_file_name, tcl_args=None, cwd=None, vivado_path=None): - """ - Run tcl script in Vivado in batch mode. - - Note: the shell=True is important in windows where Vivado is just a bat file. - """ - vivado = "vivado" if vivado_path is None else str(Path(vivado_path).resolve() / "bin" / "vivado") - cmd = f"{vivado} -nojournal -nolog -notrace -mode batch -source {str(Path(tcl_file_name).resolve())}" - if tcl_args is not None: - cmd += " -tclargs " + " ".join([str(val) for val in tcl_args]) - - print(cmd) - check_call(cmd, cwd=cwd, shell=True)