Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions examples/vhdl/submodule/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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-2019, Lars Asplund lars.anders.asplund@gmail.com

"""
Submodule support
-------------
This script shows how to import smaller submodules in a bigger design.

The submodules contains a own run.py script in which the sources are defined.
With 'add_submodule' you can add the complete project into your top design.
Usecase could be a CPU design which uses some periphery which is managed in
seperate projects.
"""

from os.path import join, dirname
from vunit import VUnit

root = dirname(__file__)

vu = VUnit.from_argv()

vu.add_json4vhdl()

lib = vu.add_library("lib")
lib.add_source_files(join(root, "src/*.vhd"))
lib.add_source_files(join(root, "tb/*.vhd"))

vu.add_submodule('src/adder/run.py')

if __name__ == '__main__':
vu.main()
29 changes: 29 additions & 0 deletions examples/vhdl/submodule/src/adder/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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-2019, Lars Asplund lars.anders.asplund@gmail.com

"""
Submodule support
-------------

This is only a small example and shows how a complete vunit design can be
imported at once. Intended use case could be a seperately managed periphery
which gets imported in a bigger top design like a CPU or complete vhdl librarys.
"""

from os.path import join, dirname
from vunit import VUnit

root = dirname(__file__)

vu = VUnit.from_argv()

vu.add_json4vhdl()

lib = vu.add_library("adder")
lib.add_source_files(join(root, "src/*.vhd"))

if __name__ == '__main__':
vu.main()
30 changes: 30 additions & 0 deletions examples/vhdl/submodule/src/adder/src/adder.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- 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-2019, Lars Asplund lars.anders.asplund@gmail.com

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder is
generic (
BITS : positive);
port(
clk : in std_logic;
op_a : in unsigned(BITS - 1 downto 0);
op_b : in unsigned(BITS - 1 downto 0);
sum : out unsigned(BITS - 1 downto 0)
);
end entity;

architecture arch of adder is
begin
main : process(clk)
begin
if rising_edge(clk) then
sum <= op_a + op_b;
end if;
end process;
end architecture;
38 changes: 38 additions & 0 deletions examples/vhdl/submodule/src/top.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- 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-2019, Lars Asplund lars.anders.asplund@gmail.com

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library adder;

entity top is
generic (
BITS : positive);
port(
clk : in std_logic;
op_a : in unsigned(BITS - 1 downto 0);
op_b : in unsigned(BITS - 1 downto 0);
sum : out unsigned(BITS - 1 downto 0)
);
end entity;

architecture arch of top is
begin

adder_inst: entity adder.adder
generic map(
BITS => BITS
)
port map(
clk => clk,
op_a => op_a,
op_b => op_b,
sum => sum
);

end architecture;
55 changes: 55 additions & 0 deletions examples/vhdl/submodule/tb/top_tb.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
-- 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-2019, 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;

entity top_tb is
generic (
RUNNER_CFG : string);
end entity;

architecture arch of top_tb is
signal clk : std_logic := '0';

constant BITS : natural := 8;
signal in_a, in_b, add_out : unsigned(BITS - 1 downto 0);

begin
clk <= not clk after 1 ns;


main: process
begin
test_runner_setup(runner, runner_cfg);
while test_suite loop
if run("test") then
in_a <= to_unsigned(10, in_a);
in_b <= to_unsigned(15, in_b);
wait for 3 ns;
check(add_out = in_a + in_b, "Addition failed");
end if;
end loop;
test_runner_cleanup(runner);
wait;
end process;

top_module: entity work.top
generic map(
BITS => BITS
)
port map(
clk => clk,
op_a => in_a,
op_b => in_b,
sum => add_out
);

end architecture;
49 changes: 48 additions & 1 deletion vunit/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@
from os.path import exists, abspath, join, basename, splitext, normpath, dirname
from glob import glob
from fnmatch import fnmatch
import importlib
from vunit.database import PickledDataBase, DataBase
from vunit import ostools
from vunit.vunit_cli import VUnitCLI
Expand Down Expand Up @@ -288,6 +289,13 @@ class VUnit(object): # pylint: disable=too-many-instance-attributes, too-many-p

from vunit import VUnit
"""
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(VUnit, cls).__new__(cls)

return cls._instance

@classmethod
def from_argv(cls, argv=None, compile_builtins=True, vhdl_standard=None):
Expand Down Expand Up @@ -325,6 +333,9 @@ def from_args(cls, args, compile_builtins=True, vhdl_standard=None):
return cls(args, compile_builtins=compile_builtins, vhdl_standard=vhdl_standard)

def __init__(self, args, compile_builtins=True, vhdl_standard=None):
if self._initialized != False:
return

self._args = args
self._configure_logging(args.log_level)
self._output_path = abspath(args.output_path)
Expand All @@ -346,6 +357,9 @@ def test_filter(name, attribute_names):

self._test_filter = test_filter
self._vhdl_standard = select_vhdl_standard(vhdl_standard)
self._import_submodule = False
self._import_submodule_latch = False
self._import_testbenches = True

self._external_preprocessors = []
self._location_preprocessor = None
Expand Down Expand Up @@ -374,6 +388,8 @@ def test_filter(name, attribute_names):
if compile_builtins:
self.add_builtins()

self._initialized = True

def _create_database(self):
"""
Create a persistent database to store expensive parse results
Expand Down Expand Up @@ -490,6 +506,8 @@ def add_library(self, library_name, vhdl_standard=None, allow_duplicate=False):
path = join(self._simulator_output_path, "libraries", library_name)
if not self._project.has_library(library_name):
self._project.add_library(library_name, abspath(path), vhdl_standard)
elif self._import_submodule:
pass
elif not allow_duplicate:
raise ValueError("Library %s already added. Use allow_duplicate to ignore this error." % library_name)
return self.library(library_name)
Expand Down Expand Up @@ -1141,6 +1159,27 @@ def get_implementation_subset(self, source_files):
return SourceFileList([SourceFile(source_file, self._project, self)
for source_file in source_files])

def add_submodule(self, module, import_testbenches = False):
"""
Add a complete vunit build script to the design at once.

:param module: Path to the submodule's run.py file
:param import_testbenches : If set, the submodules testbenches are imported, otherwise not.
"""

f = open(module) # raises FileNotFoundError if the module is not available
rootpath = os.getcwd()
path = os.path.abspath(os.path.dirname(module))
sys.path.insert(0, path)
os.chdir(path)
self._import_submodule = True
self._import_submodule_latch = True
self._import_testbenches = import_testbenches
importlib.import_module(os.path.basename(module).split('.')[0])
self._import_testbenches = True
self._import_submodule = False
os.chdir(rootpath)
sys.path.remove(path)

class Library(object):
"""
Expand Down Expand Up @@ -1350,6 +1389,13 @@ def add_source_file(self, # pylint: disable=too-many-arguments
new_file_name = self._parent._preprocess( # pylint: disable=protected-access
self._library_name, file_name, preprocessors)

if self._parent._import_submodule_latch:
try:
duplicate = self.get_source_file('*/' + os.path.basename(file_name))
return duplicate
except ValueError:
pass

source_file = self._project.add_source_file(new_file_name,
self._library_name,
file_type=file_type,
Expand All @@ -1360,7 +1406,8 @@ def add_source_file(self, # pylint: disable=too-many-arguments
# To get correct tb_path generic
source_file.original_name = file_name

self._test_bench_list.add_from_source_file(source_file)
if self._parent._import_testbenches:
self._test_bench_list.add_from_source_file(source_file)

return SourceFile(source_file,
self._project,
Expand Down