Skip to content
Open
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
45 changes: 39 additions & 6 deletions docs/vunit_packages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ and compilation defaults. For example:
[package]
requires-vunit = ">=5.0.0.dev14"
requires-vhdl = ">=2008,<2019"
requires = 'simulator != "xsim" or vhdl >= "2019"'
library = "foo_lib"
compile_option = [["<option-name>", ["<value>"]]]

Expand All @@ -41,10 +42,20 @@ and compilation defaults. For example:
library = "foo_compat"
compile_option = [["<option-name>", ["<source-value>"]]]

Each ``[[package.sources]]`` table defines a source entry. Its ``include``
patterns are relative to the package root. In this example, files matching
``hdl/src/*.vhd`` use the default library, ``foo_lib``, while files matching
``hdl/compat/*.vhd`` use ``foo_compat``.
Each ``[[package.sources]]`` table defines a source entry. Its ``files``
patterns (or the backwards-compatible ``include`` key) are relative to the
package root. In this example, files matching ``hdl/src/*.vhd`` use the
default library, ``foo_lib``, while files matching ``hdl/compat/*.vhd`` use
``foo_compat``.

A source entry can be restricted to matching environments:

.. code-block:: toml

[[package.sources]]
library = "foo_lib"
files = ["hdl/vhdl2019/*.vhd"]
when = 'vhdl >= "2019"'

Replace the compile-option placeholders with names and values supported by
the project. Each option is a two-element array containing the option name
Expand All @@ -67,14 +78,21 @@ The supported manifest fields are:
* - ``requires-vhdl``
- ``[package]``
- Constraints on the VHDL standards supported by the package.
* - ``requires``
- ``[package]``
- Environment expression that must match before the package can be used.
* - ``library``
- ``[package]``
- Default library for package sources. Required when ``sources`` is
present. VUnit creates the library for the package.
* - ``sources``
- ``[[package.sources]]``
- Repeated source tables. Each table must contain ``include``, an array
of source patterns relative to the package root.
- Repeated source tables. Each table must contain ``files`` or
``include``, an array of source patterns relative to the package root.
* - ``when``
- ``[[package.sources]]``
- Optional environment expression that controls whether this source
entry is included.
* - ``library``
- ``[[package.sources]]``
- Optional library override for this source entry. VUnit creates the
Expand All @@ -98,6 +116,21 @@ selects a compatible supported standard and issues a warning. If no such
standard is available, adding the package fails. A VUnit version that does
not satisfy ``requires-vunit`` always causes an error.

The optional ``requires`` and ``when`` expressions support marker names
``vunit``, ``vhdl``, ``simulator``, and the simulator version markers
``activehdl_version``, ``ghdl_version``, ``modelsim_version``,
``nvc_version``, and ``rivierapro_version``. Version markers are available
only when their corresponding simulator is selected. Equality and inequality
checks on an unavailable version marker are supported, but ordering checks
are unavailable. With no simulator selected, equality and inequality checks
on ``simulator`` are supported, but ordering checks are unavailable. Values
are quoted strings, comparisons use
``<=``, ``<``, ``!=``, ``==``, ``>=``, or ``>``, and ``and``, ``or``, and
parentheses group comparisons. ``and`` has higher precedence than ``or``.
The legacy ``requires-vunit`` and ``requires-vhdl`` constraints remain in
force alongside ``requires``. A source entry without ``when`` is always
included for a usable package.

Manifest validation is strict: unknown fields and values of the wrong type
are rejected.

Expand Down
164 changes: 102 additions & 62 deletions tests/unit/test_activehdl_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
Test the ActiveHDL interface
"""


import unittest
from pathlib import Path
import os
from shutil import rmtree
from unittest import mock
from vunit.sim_if.activehdl import ActiveHDLInterface, VersionConsumer, Version
from vunit.sim_if.activehdl import ActiveHDLInterface, ActiveHDLVersion, VersionConsumer
from vunit.project import Project
from vunit.ostools import renew_path, write_file
from vunit.vhdl_standard import VHDL
Expand Down Expand Up @@ -347,125 +346,166 @@ def _assert_version_correct(self, version_line, expected_major, expected_minor,
consumer(version_line)
self.assertEqual(
consumer.version,
Version(expected_major, expected_minor, expected_minor_letter),
ActiveHDLVersion(f"{expected_major}.{expected_minor}{expected_minor_letter}"),
)

def test_vendor_version_without_letters(self):
def test_version_string_without_letters(self):
self._assert_version_correct(
"Aldec, Inc. VHDL compiler version 10.5.216.6767 built for Windows on January 20, 2018.",
"10.5.216.6767",
10,
5,
"",
)

def test_vendor_version_with_letters(self):
def test_version_string_with_letters(self):
self._assert_version_correct(
"Aldec, Inc. VHDL compiler version 10.5a.12.6914 built for Windows on June 06, 2018.",
"10.5a.12.6914",
10,
5,
"a",
)


class TestVersion(unittest.TestCase):
class TestActiveHDLVersion(unittest.TestCase):
"""
Test the Version class.
Test ActiveHDL version comparisons.
Test cases = (assert true, assert false) x (with letters, without letters, mixed) x number_of_operations
Where number_of_operations = 1 for <, and 2 for <=, etc
"""

high_version_letter = Version(10, 5, "b")
low_version_letter = Version(10, 5, "a")
high_version_no_letter = Version(10, 6)
low_version_no_letter = Version(10, 5)
high_version_letter_for_mixed = Version(10, 6, "")
high_version_letter = ActiveHDLVersion("10.5b")
low_version_letter = ActiveHDLVersion("10.5a")
high_version_no_letter = ActiveHDLVersion("10.6")
low_version_no_letter = ActiveHDLVersion("10.5")
high_version_letter_for_mixed = ActiveHDLVersion("10.6")

def test_versions_are_ordered_by_major_minor_and_minor_letter(self):
self.assertLess(ActiveHDLVersion("10.5"), ActiveHDLVersion("10.5a"))
self.assertLess(ActiveHDLVersion("10.5a"), ActiveHDLVersion("10.5b"))
self.assertLess(ActiveHDLVersion("10.5b"), ActiveHDLVersion("10.6"))
self.assertEqual(ActiveHDLVersion("10.5a.12.6914"), ActiveHDLVersion("10.5a"))
self.assertEqual(str(ActiveHDLVersion("10.5a")), "10.5a")

def test_from_output_extracts_versions_from_vendor_output(self):
self.assertEqual(
ActiveHDLVersion.from_output(
"Aldec, Inc. VHDL compiler version 10.5.216.6767 built for Windows on January 20, 2018."
),
ActiveHDLVersion("10.5"),
)
self.assertEqual(
ActiveHDLVersion.from_output(
"Aldec, Inc. VHDL compiler version 10.5a.12.6914 built for Windows on June 06, 2018."
),
ActiveHDLVersion("10.5a"),
)

def test_from_output_returns_unknown_when_version_cannot_be_parsed(self):
with self.assertWarnsRegex(RuntimeWarning, "version is unknown"):
version = ActiveHDLVersion.from_output("Active-HDL version unavailable")

self.assertFalse(version.is_valid)
self.assertEqual(str(version), "unknown")

def test_unknown_versions_cannot_be_ordered(self):
with self.assertWarns(RuntimeWarning):
version = ActiveHDLVersion("unknown")

with self.assertRaisesRegex(ValueError, "Cannot order unknown ActiveHDL versions"):
version < ActiveHDLVersion("10.5")

def test_lt(self):
# Test with letters
self.assertTrue(TestVersion.low_version_letter < TestVersion.high_version_letter)
self.assertFalse(TestVersion.high_version_letter < TestVersion.low_version_letter)
self.assertTrue(TestActiveHDLVersion.low_version_letter < TestActiveHDLVersion.high_version_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter < TestActiveHDLVersion.low_version_letter)
# Test without letters
self.assertTrue(TestVersion.low_version_no_letter < TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_no_letter < TestVersion.low_version_no_letter)
self.assertTrue(TestActiveHDLVersion.low_version_no_letter < TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_no_letter < TestActiveHDLVersion.low_version_no_letter)
# Both
self.assertTrue(TestVersion.low_version_letter < TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_letter < TestVersion.low_version_no_letter)
self.assertTrue(TestActiveHDLVersion.low_version_letter < TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter < TestActiveHDLVersion.low_version_no_letter)

def test_le(self):
# Test equal
# Test with letters
self.assertTrue(TestVersion.high_version_letter <= TestVersion.high_version_letter)
self.assertFalse(TestVersion.high_version_letter <= TestVersion.low_version_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter <= TestActiveHDLVersion.high_version_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter <= TestActiveHDLVersion.low_version_letter)
# Test without letters
self.assertTrue(TestVersion.high_version_no_letter <= TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_no_letter <= TestVersion.low_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_no_letter <= TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_no_letter <= TestActiveHDLVersion.low_version_no_letter)
# Both
self.assertTrue(TestVersion.high_version_letter <= TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_letter <= TestVersion.low_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter <= TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter <= TestActiveHDLVersion.low_version_no_letter)

# Test less than
# Test with letters
self.assertTrue(TestVersion.low_version_letter <= TestVersion.high_version_letter)
self.assertFalse(TestVersion.high_version_letter <= TestVersion.low_version_letter)
self.assertTrue(TestActiveHDLVersion.low_version_letter <= TestActiveHDLVersion.high_version_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter <= TestActiveHDLVersion.low_version_letter)
# Test without letters
self.assertTrue(TestVersion.low_version_no_letter <= TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_no_letter <= TestVersion.low_version_no_letter)
self.assertTrue(TestActiveHDLVersion.low_version_no_letter <= TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_no_letter <= TestActiveHDLVersion.low_version_no_letter)
# Both
self.assertTrue(TestVersion.low_version_letter <= TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_letter <= TestVersion.low_version_no_letter)
self.assertTrue(TestActiveHDLVersion.low_version_letter <= TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter <= TestActiveHDLVersion.low_version_no_letter)

def test_gt(self):
# Test with letters
self.assertTrue(TestVersion.high_version_letter > TestVersion.low_version_letter)
self.assertFalse(TestVersion.low_version_letter > TestVersion.high_version_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter > TestActiveHDLVersion.low_version_letter)
self.assertFalse(TestActiveHDLVersion.low_version_letter > TestActiveHDLVersion.high_version_letter)
# Test without letters
self.assertTrue(TestVersion.high_version_no_letter > TestVersion.low_version_no_letter)
self.assertFalse(TestVersion.low_version_no_letter > TestVersion.high_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_no_letter > TestActiveHDLVersion.low_version_no_letter)
self.assertFalse(TestActiveHDLVersion.low_version_no_letter > TestActiveHDLVersion.high_version_no_letter)
# Both
self.assertTrue(TestVersion.high_version_letter > TestVersion.low_version_no_letter)
self.assertFalse(TestVersion.low_version_letter > TestVersion.high_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter > TestActiveHDLVersion.low_version_no_letter)
self.assertFalse(TestActiveHDLVersion.low_version_letter > TestActiveHDLVersion.high_version_no_letter)

def test_ge(self):
# Test equal
# Test with letters
self.assertTrue(TestVersion.high_version_letter >= TestVersion.high_version_letter)
self.assertFalse(TestVersion.low_version_letter >= TestVersion.high_version_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter >= TestActiveHDLVersion.high_version_letter)
self.assertFalse(TestActiveHDLVersion.low_version_letter >= TestActiveHDLVersion.high_version_letter)
# Test without letters
self.assertTrue(TestVersion.high_version_no_letter >= TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.low_version_no_letter >= TestVersion.high_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_no_letter >= TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.low_version_no_letter >= TestActiveHDLVersion.high_version_no_letter)
# Both
self.assertTrue(TestVersion.high_version_letter_for_mixed >= TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.low_version_letter >= TestVersion.high_version_no_letter)
self.assertTrue(
TestActiveHDLVersion.high_version_letter_for_mixed >= TestActiveHDLVersion.high_version_no_letter
)
self.assertFalse(TestActiveHDLVersion.low_version_letter >= TestActiveHDLVersion.high_version_no_letter)

# Test greater than
# Test with letters
self.assertTrue(TestVersion.high_version_letter >= TestVersion.low_version_letter)
self.assertFalse(TestVersion.low_version_letter >= TestVersion.high_version_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter >= TestActiveHDLVersion.low_version_letter)
self.assertFalse(TestActiveHDLVersion.low_version_letter >= TestActiveHDLVersion.high_version_letter)
# Test without letters
self.assertTrue(TestVersion.high_version_no_letter >= TestVersion.low_version_no_letter)
self.assertFalse(TestVersion.low_version_no_letter >= TestVersion.high_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_no_letter >= TestActiveHDLVersion.low_version_no_letter)
self.assertFalse(TestActiveHDLVersion.low_version_no_letter >= TestActiveHDLVersion.high_version_no_letter)
# Both
self.assertTrue(TestVersion.high_version_letter >= TestVersion.low_version_no_letter)
self.assertFalse(TestVersion.low_version_letter >= TestVersion.high_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter >= TestActiveHDLVersion.low_version_no_letter)
self.assertFalse(TestActiveHDLVersion.low_version_letter >= TestActiveHDLVersion.high_version_no_letter)

def test_eq(self):
# Test with letters
self.assertTrue(TestVersion.high_version_letter == TestVersion.high_version_letter)
self.assertFalse(TestVersion.high_version_letter == TestVersion.low_version_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter == TestActiveHDLVersion.high_version_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter == TestActiveHDLVersion.low_version_letter)
# Test without letters
self.assertTrue(TestVersion.high_version_no_letter == TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_no_letter == TestVersion.low_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_no_letter == TestActiveHDLVersion.high_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_no_letter == TestActiveHDLVersion.low_version_no_letter)
# Both
self.assertTrue(TestVersion.high_version_letter_for_mixed == TestVersion.high_version_no_letter)
self.assertFalse(TestVersion.high_version_letter == TestVersion.low_version_no_letter)
self.assertTrue(
TestActiveHDLVersion.high_version_letter_for_mixed == TestActiveHDLVersion.high_version_no_letter
)
self.assertFalse(TestActiveHDLVersion.high_version_letter == TestActiveHDLVersion.low_version_no_letter)

def test_ne(self):
# Test with letters
self.assertTrue(TestVersion.high_version_letter != TestVersion.low_version_letter)
self.assertFalse(TestVersion.high_version_letter != TestVersion.high_version_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter != TestActiveHDLVersion.low_version_letter)
self.assertFalse(TestActiveHDLVersion.high_version_letter != TestActiveHDLVersion.high_version_letter)
# Test without letters
self.assertTrue(TestVersion.high_version_no_letter != TestVersion.low_version_no_letter)
self.assertFalse(TestVersion.high_version_no_letter != TestVersion.high_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_no_letter != TestActiveHDLVersion.low_version_no_letter)
self.assertFalse(TestActiveHDLVersion.high_version_no_letter != TestActiveHDLVersion.high_version_no_letter)
# Both
self.assertTrue(TestVersion.high_version_letter != TestVersion.low_version_no_letter)
self.assertFalse(TestVersion.high_version_letter_for_mixed != TestVersion.high_version_no_letter)
self.assertTrue(TestActiveHDLVersion.high_version_letter != TestActiveHDLVersion.low_version_no_letter)
self.assertFalse(
TestActiveHDLVersion.high_version_letter_for_mixed != TestActiveHDLVersion.high_version_no_letter
)
Loading
Loading