Check for supported tool versions
Define supported tool versions in tool_requirements.py, and check them
in a fusesoc run. If an unsupported tool version is found, fusesoc
outputs an error like this:
```
$ fusesoc --cores-root ../../ run --target=lint lowrisc:ip:aes
INFO: Preparing lowrisc:constants:top_pkg:0
INFO: Preparing lowrisc:lint:comportable:0.1
...
INFO: Preparing lowrisc:tool:check_tool_requirements:0.1
INFO: Preparing lowrisc:lint:common:0.1
...
INFO: Preparing lowrisc:ip:aes:0.5
ERROR: verilator is too old: found version 4.016, need at least 4.028
ERROR: Tool requirements not fulfilled. Please update the tools and retry.
ERROR: Failed to build lowrisc:ip:aes:0.5 : pre_build script \
'check_tool_requirements' exited with error code 1
```
The only version checked at this point is Verilator, which is set to
version 4.028, the first version to support wildcard matching for
`lint_off` rules.
The whole infrastructure has been created by @imphil in the Ibex
repository (see lowRISC/Ibex#604). This commit just copies the
framework over to OpenTitan.
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/util/check_tool_requirements.py b/util/check_tool_requirements.py
new file mode 100755
index 0000000..5a59d4c
--- /dev/null
+++ b/util/check_tool_requirements.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+from distutils.version import StrictVersion
+import logging as log
+import os
+import subprocess
+import sys
+
+# Display INFO log messages and up.
+log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")
+
+# Populate __TOOL_REQUIREMENTS__
+topsrcdir = os.path.join(os.path.dirname(__file__), '..')
+exec(open(os.path.join(topsrcdir, 'tool_requirements.py')).read())
+
+def get_verilator_version():
+ try:
+ # Note: "verilator" needs to be called through a shell and with all
+ # arguments in a string, as it doesn't have a shebang, but instead
+ # relies on perl magic to parse command line arguments.
+ version_str = subprocess.run('verilator --version', shell=True,
+ check=True, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ universal_newlines=True)
+ return version_str.stdout.split(' ')[1].strip()
+
+ except subprocess.CalledProcessError as e:
+ log.error("Unable to call Verilator to check version: " + str(e))
+ log.error(e.stdout)
+ return None
+
+def check_version(tool_name, required_version, actual_version):
+ if required_version is None or actual_version is None:
+ return False
+
+ if StrictVersion(actual_version) < StrictVersion(required_version):
+ log.error("%s is too old: found version %s, need at least %s",
+ tool_name, actual_version, required_version)
+ return False
+ else:
+ log.info("Found sufficiently recent version of %s (found %s, need %s)",
+ tool_name, actual_version, required_version)
+ return True
+
+
+def main():
+ any_failed = False
+
+ if not check_version('verilator', __TOOL_REQUIREMENTS__['verilator'],
+ get_verilator_version()):
+ any_failed = True
+
+ if any_failed:
+ log.error("Tool requirements not fulfilled. "
+ "Please update the tools and retry.")
+ return 1
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())