From 7c2ea7ca7436791e00e223dfb479528cf163b19d Mon Sep 17 00:00:00 2001 From: Martin Troiber Date: Tue, 26 Sep 2023 15:49:43 +0100 Subject: [PATCH 1/2] Check tool versions at beginning of run --- siliconcompiler/core.py | 12 ++++++++++++ tests/core/test_error_manifest.py | 14 ++++++++------ tests/core/test_fail_early.py | 15 +++++++++------ tests/core/test_version_early.py | 23 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 tests/core/test_version_early.py diff --git a/siliconcompiler/core.py b/siliconcompiler/core.py index 1c29ac736..23e7060a8 100644 --- a/siliconcompiler/core.py +++ b/siliconcompiler/core.py @@ -4211,6 +4211,18 @@ def _local_process(self, flow, status, steplist, indexlist): for (step, index) in flowgraph_nodes: # Setting up tool is optional self._setup_node(step, index) + # Env vars are necessary as test_multiple_tools.py requires it for its version check + self._set_env_vars(step, index) + tool, task = self._get_tool_task(step, index, flow) + # Icarus compiles its executable during the run so we can't check its version + if (tool, task) != ('execute', 'exec_input'): + run_func = getattr(self._get_task_module(step, index, flow=flow), 'run', None) + try: + self._check_tool_version(step, index, run_func) + # Convert sys.exit(1) from haltstep() in version check to SilicoCompilerError + except SystemExit: + self.error('Pre-run version check failed. Please update your tools.', + fatal=True) # Check validity of setup self.logger.info("Checking manifest before running.") diff --git a/tests/core/test_error_manifest.py b/tests/core/test_error_manifest.py index 54b50a616..b6ea71bf3 100644 --- a/tests/core/test_error_manifest.py +++ b/tests/core/test_error_manifest.py @@ -1,9 +1,12 @@ import siliconcompiler from siliconcompiler.tools.surelog import parse -from siliconcompiler._common import SiliconCompilerError import os +import pytest + +@pytest.mark.quick +@pytest.mark.eda def test_error_manifest(): ''' Executing a node with errors should still produce an output manifest @@ -18,9 +21,8 @@ def test_error_manifest(): index = '0' chip.node(flow, step, parse, index=index) - try: + with pytest.raises(siliconcompiler.SiliconCompilerError): chip.run() - except SiliconCompilerError: - workdir = chip._getworkdir(jobname=chip._get_in_job(step, index), step=step, index=index) - cfg = os.path.join(workdir, 'outputs', f'{chip.top()}.pkg.json') - assert os.path.isfile(cfg) + workdir = chip._getworkdir(jobname=chip._get_in_job(step, index), step=step, index=index) + cfg = os.path.join(workdir, 'outputs', f'{chip.top()}.pkg.json') + assert os.path.isfile(cfg) diff --git a/tests/core/test_fail_early.py b/tests/core/test_fail_early.py index 10cb63fb4..06ec1574d 100644 --- a/tests/core/test_fail_early.py +++ b/tests/core/test_fail_early.py @@ -1,9 +1,12 @@ import siliconcompiler from siliconcompiler.tools.yosys import syn_asic from siliconcompiler.tools.surelog import parse -from siliconcompiler._common import SiliconCompilerError +import pytest + +@pytest.mark.quick +@pytest.mark.eda def test_fail_early(capfd): chip = siliconcompiler.Chip('test') chip.set('input', 'rtl', 'verilog', 'fake.v') @@ -15,9 +18,9 @@ def test_fail_early(capfd): chip.node(flow, 'syn', syn_asic) chip.edge(flow, 'import', 'syn') - try: + with pytest.raises(siliconcompiler.SiliconCompilerError): chip.run() - except SiliconCompilerError: - # Fail if 'syn' step is run - out, _ = capfd.readouterr() - assert "Halting step 'syn'" not in out + # Fail if 'syn' step is run + out, _ = capfd.readouterr() + assert "Halting step 'import'" in out + assert "Halting step 'syn'" not in out diff --git a/tests/core/test_version_early.py b/tests/core/test_version_early.py new file mode 100644 index 000000000..93b196567 --- /dev/null +++ b/tests/core/test_version_early.py @@ -0,0 +1,23 @@ +import siliconcompiler +from siliconcompiler.tools.surelog import parse + +import pytest + + +def test_version_early(capfd): + chip = siliconcompiler.Chip('test') + chip.set('input', 'rtl', 'verilog', 'fake.v') + chip.load_target('freepdk45_demo') + chip.set('option', 'mode', 'asic') + flow = 'test' + chip.set('option', 'flow', flow) + chip.node(flow, 'import', parse) + chip.set('tool', 'surelog', 'version', '==100.0') + + with pytest.raises(siliconcompiler.SiliconCompilerError, + match='Pre-run version check failed. Please update your tools.'): + chip.run() + # Fail if any task is run + out, _ = capfd.readouterr() + assert "Halting step 'import'" in out + assert "Finished task in" not in out From 658dd482cbe1e77af6a8823ff041288f4b2f68a5 Mon Sep 17 00:00:00 2001 From: Martin Troiber Date: Thu, 28 Sep 2023 15:35:11 +0100 Subject: [PATCH 2/2] Address feedback --- siliconcompiler/core.py | 25 ++++++++++++------------ siliconcompiler/tools/execute/execute.py | 3 ++- tests/core/test_version_early.py | 7 ++++--- tests/flows/test_multiple_tools.py | 3 +++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/siliconcompiler/core.py b/siliconcompiler/core.py index 23e7060a8..9e84a120b 100644 --- a/siliconcompiler/core.py +++ b/siliconcompiler/core.py @@ -4196,6 +4196,17 @@ def _check_nodes_status(self, flow, status, steplist, indexlist): if status[node] != NodeStatus.PENDING: self.set('flowgraph', flow, step, index, 'status', status[node]) + def _pre_run_version_check(self, flow, flowgraph_nodes): + # Don't print information messages produced by _check_tool_version() + prev_log_level = self.logger.level + self.logger.setLevel(logging.WARNING) + + for (step, index) in flowgraph_nodes: + run_func = getattr(self._get_task_module(step, index, flow=flow), 'run', None) + self._check_tool_version(step, index, run_func) + + self.logger.setLevel(prev_log_level) + def _local_process(self, flow, status, steplist, indexlist): # Populate status dict with any flowgraph status values that have already # been set. @@ -4211,18 +4222,6 @@ def _local_process(self, flow, status, steplist, indexlist): for (step, index) in flowgraph_nodes: # Setting up tool is optional self._setup_node(step, index) - # Env vars are necessary as test_multiple_tools.py requires it for its version check - self._set_env_vars(step, index) - tool, task = self._get_tool_task(step, index, flow) - # Icarus compiles its executable during the run so we can't check its version - if (tool, task) != ('execute', 'exec_input'): - run_func = getattr(self._get_task_module(step, index, flow=flow), 'run', None) - try: - self._check_tool_version(step, index, run_func) - # Convert sys.exit(1) from haltstep() in version check to SilicoCompilerError - except SystemExit: - self.error('Pre-run version check failed. Please update your tools.', - fatal=True) # Check validity of setup self.logger.info("Checking manifest before running.") @@ -4236,6 +4235,8 @@ def _local_process(self, flow, status, steplist, indexlist): if self._error: self.error('Implementation errors encountered. See previous errors.', fatal=True) + self._pre_run_version_check(flow, flowgraph_nodes) + nodes_to_run = {} processes = {} self._prepare_nodes(nodes_to_run, processes, flow, status, steplist, indexlist) diff --git a/siliconcompiler/tools/execute/execute.py b/siliconcompiler/tools/execute/execute.py index a40221200..babcab6c6 100644 --- a/siliconcompiler/tools/execute/execute.py +++ b/siliconcompiler/tools/execute/execute.py @@ -11,5 +11,6 @@ def setup(chip): tool, task = chip._get_tool_task(step, index) - chip.set('tool', tool, 'exe', ":exe:", clobber=False) + # Use dummy bash executable 'true' to pass pre-run version check + chip.set('tool', tool, 'exe', 'true', clobber=False) chip.set('tool', tool, 'task', task, 'option', [], step=step, index=index, clobber=False) diff --git a/tests/core/test_version_early.py b/tests/core/test_version_early.py index 93b196567..89c368f97 100644 --- a/tests/core/test_version_early.py +++ b/tests/core/test_version_early.py @@ -4,6 +4,8 @@ import pytest +@pytest.mark.eda +@pytest.mark.quick def test_version_early(capfd): chip = siliconcompiler.Chip('test') chip.set('input', 'rtl', 'verilog', 'fake.v') @@ -14,10 +16,9 @@ def test_version_early(capfd): chip.node(flow, 'import', parse) chip.set('tool', 'surelog', 'version', '==100.0') - with pytest.raises(siliconcompiler.SiliconCompilerError, - match='Pre-run version check failed. Please update your tools.'): + with pytest.raises(SystemExit): chip.run() # Fail if any task is run out, _ = capfd.readouterr() - assert "Halting step 'import'" in out + assert "Version check failed" in out assert "Finished task in" not in out diff --git a/tests/flows/test_multiple_tools.py b/tests/flows/test_multiple_tools.py index da7830ad1..f46855118 100644 --- a/tests/flows/test_multiple_tools.py +++ b/tests/flows/test_multiple_tools.py @@ -55,6 +55,9 @@ def test_multiple_tools(): chip.set('tool', 'surelog', 'licenseserver', 'ACME_LICENSE', '1700@server', step='slog', index=1) + # Set env vars for slog1 for pre-run version check + chip._set_env_vars('slog', '1') + # Don't run tools, just version check chip.set('option', 'skipall', True) chip.run()