Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 886cb15

Browse files
committedJun 11, 2025·
Hand tested the command actually finish on the first error
1 parent 05ee045 commit 886cb15

File tree

4 files changed

+72
-59
lines changed

4 files changed

+72
-59
lines changed
 

‎FABulous/FABulous_CLI/FABulous_CLI.py

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def onecmd(
221221
except Exception:
222222
logger.debug(traceback.format_exc())
223223
self.exit_code = 1
224-
if not self.interactive:
224+
if self.interactive:
225225
return False
226226
else:
227227
return not self.force
@@ -757,17 +757,18 @@ def do_place_and_route(self, args):
757757
"--log",
758758
f"{self.projectDir}/{parent}/{log_file}",
759759
]
760-
try:
761-
sp.run(
762-
" ".join(runCmd),
763-
stdout=sys.stdout,
764-
stderr=sp.STDOUT,
765-
check=True,
766-
shell=True,
760+
result = sp.run(
761+
" ".join(runCmd),
762+
stdout=sys.stdout,
763+
stderr=sp.STDOUT,
764+
check=True,
765+
shell=True,
766+
)
767+
if result.returncode != 0:
768+
logger.opt(exception=CommandError()).error(
769+
"Nextpnr failed. Please check the logs for more details."
767770
)
768-
except sp.CalledProcessError as e:
769-
logger.opt(exception=e).error("Placement and Routing failed.")
770-
771+
return
771772
else:
772773
logger.opt(exception=FileNotFoundError()).error(
773774
f'Cannot find file "{json_file}" in path "./{parent}/", which is generated by running Yosys with Nextpnr backend (e.g. synthesis).'
@@ -865,6 +866,7 @@ def do_run_simulation(self, args):
865866
if bitstreamPath.suffix != ".bin":
866867
logger.error("No bitstream file specified.")
867868
return
869+
868870
if not bitstreamPath.exists():
869871
logger.opt(exception=FileNotFoundError()).error(
870872
f"Cannot find {bitstreamPath} file which is generated by running gen_bitStream_binary. Potentially the bitstream generation failed."
@@ -894,27 +896,28 @@ def do_run_simulation(self, args):
894896
iverilog = check_if_application_exists(
895897
os.getenv("FAB_IVERILOG_PATH", "iverilog")
896898
)
897-
try:
898-
runCmd = [
899-
f"{iverilog}",
900-
"-D",
901-
f"{defined_option}",
902-
"-s",
903-
f"{topModuleTB}",
904-
"-o",
905-
f"{buildDir}/{vvpFile}",
906-
*file_list,
907-
f"{bitstreamPath.parent}/{designFile}",
908-
f"{testPath}/{testBench}",
909-
]
910-
if self.verbose or self.debug:
911-
logger.info(f"Running simulation with {args.format} format")
912-
logger.info(f"Running command: {' '.join(runCmd)}")
913-
sp.run(runCmd, check=True)
899+
runCmd = [
900+
f"{iverilog}",
901+
"-D",
902+
f"{defined_option}",
903+
"-s",
904+
f"{topModuleTB}",
905+
"-o",
906+
f"{buildDir}/{vvpFile}",
907+
*file_list,
908+
f"{bitstreamPath.parent}/{designFile}",
909+
f"{testPath}/{testBench}",
910+
]
911+
if self.verbose or self.debug:
912+
logger.info(f"Running simulation with {args.format} format")
913+
logger.info(f"Running command: {' '.join(runCmd)}")
914914

915-
except sp.CalledProcessError as e:
916-
remove_dir(buildDir)
917-
logger.opt(exception=e).error("Simulation failed")
915+
result = sp.run(runCmd, check=True)
916+
if result.returncode != 0:
917+
logger.opt(exception=CommandError()).error(
918+
"Simulation failed. Please check the logs for more details."
919+
)
920+
return
918921

919922
# bitstream hex file is used for simulation so it'll be created in the test directory
920923
bitstreamHexPath = (buildDir.parent / bitstreamPath.stem).with_suffix(".hex")
@@ -931,16 +934,18 @@ def do_run_simulation(self, args):
931934
if waveform_format == "fst":
932935
vvpArgs.append("-fst")
933936

934-
try:
935-
runCmd = [f"{vvp}", f"{buildDir}/{vvpFile}"]
936-
runCmd.extend(vvpArgs)
937-
if self.verbose or self.debug:
938-
logger.info(f"Running command: {' '.join(runCmd)}")
939-
sp.run(runCmd, check=True)
940-
remove_dir(buildDir)
941-
except sp.CalledProcessError as e:
942-
remove_dir(buildDir)
943-
logger.opt(exception=e).error("Simulation failed")
937+
runCmd = [f"{vvp}", f"{buildDir}/{vvpFile}"]
938+
runCmd.extend(vvpArgs)
939+
if self.verbose or self.debug:
940+
logger.info(f"Running command: {' '.join(runCmd)}")
941+
942+
result = sp.run(runCmd, check=True)
943+
remove_dir(buildDir)
944+
if result.returncode != 0:
945+
logger.opt(exception=CommandError()).error(
946+
"Simulation failed. Please check the logs for more details."
947+
)
948+
return
944949

945950
logger.info("Simulation finished")
946951

@@ -976,12 +981,14 @@ def do_run_FABulous_bitstream(self, args):
976981
do_synth_args += f" -extra-plib {primsLib}"
977982
else:
978983
logger.info("No external primsLib found.")
984+
979985
self.onecmd_plus_hooks(f"synthesis {do_synth_args}")
980986
if self.exit_code != 0:
981987
logger.opt(exception=CommandError()).error(
982988
"Synthesis failed. Please check the logs for more details."
983989
)
984990
return
991+
985992
self.onecmd_plus_hooks(f"place_and_route {json_file_path}")
986993
if self.exit_code != 0:
987994
logger.opt(exception=CommandError()).error(
@@ -1026,6 +1033,11 @@ def do_run_script(self, args):
10261033
with open(args.file, "r") as f:
10271034
for i in f.readlines():
10281035
self.onecmd_plus_hooks(i.strip())
1036+
if self.exit_code != 0:
1037+
logger.opt(exception=CommandError()).error(
1038+
f"Script execution failed at line: {i.strip()}"
1039+
)
1040+
return
10291041

10301042
logger.info("Script executed")
10311043

‎FABulous/FABulous_CLI/cmd_synthesis.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import subprocess as sp
33
from pathlib import Path
44

5+
from FABulous.custom_exception import CommandError
56
from cmd2 import Cmd, Cmd2ArgumentParser, with_argparser, with_category
67
from loguru import logger
78

@@ -290,8 +291,10 @@ def do_synthesis(self, args):
290291
*[str(i) for i in paths],
291292
]
292293
logger.debug(f"{runCmd}")
293-
try:
294-
sp.run(runCmd, check=True)
295-
logger.info("Synthesis completed")
296-
except sp.CalledProcessError:
297-
logger.error("Synthesis failed")
294+
result = sp.run(runCmd, check=True)
295+
296+
if result.returncode != 0:
297+
logger.opt(exception=CommandError()).error(
298+
"Synthesis failed with non-zero return code."
299+
)
300+
logger.info("Synthesis command executed successfully.")

‎FABulous/FABulous_CLI/helper.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,16 @@ def custom_format_function(record):
5050

5151
# Add logger to write logs to stdout using the custom formatter
5252
if log_file != Path():
53-
logger.add(log_file, format=custom_format_function, level=log_level_to_set)
53+
logger.add(
54+
log_file, format=custom_format_function, level=log_level_to_set, catch=False
55+
)
5456
else:
5557
logger.add(
5658
sys.stdout,
5759
format=custom_format_function,
5860
level=log_level_to_set,
5961
colorize=True,
62+
catch=False,
6063
)
6164

6265

‎tests/CLI_test/test_CLI.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
from pathlib import Path
2-
import subprocess
3-
import pytest
4-
from FABulous.FABulous_CLI.FABulous_CLI import FABulous_CLI
2+
53
from tests.conftest import (
64
TILE,
7-
normalize,
85
normalize_and_check_for_errors,
96
run_cmd,
107
)
@@ -100,7 +97,7 @@ def test_gen_model_npnr(cli, caplog):
10097

10198
def test_run_FABulous_bitstream(cli, caplog, mocker):
10299
"""Test the run_FABulous_bitstream command"""
103-
m = mocker.patch("subprocess.run", return_value=None)
100+
m = mocker.patch("subprocess.run", side_effect=RuntimeError("Mocked error"))
104101
run_cmd(cli, "run_FABulous_fabric")
105102
Path(cli.projectDir / "user_design" / "sequential_16bit_en.json").touch()
106103
Path(cli.projectDir / "user_design" / "sequential_16bit_en.fasm").touch()
@@ -112,7 +109,7 @@ def test_run_FABulous_bitstream(cli, caplog, mocker):
112109

113110
def test_run_simulation(cli, caplog, mocker):
114111
"""Test running simulation"""
115-
m = mocker.patch("subprocess.run", return_value=None)
112+
m = mocker.patch("subprocess.run", side_effect=RuntimeError("Mocked error"))
116113
run_cmd(cli, "run_FABulous_fabric")
117114
Path(cli.projectDir / "user_design" / "sequential_16bit_en.json").touch()
118115
Path(cli.projectDir / "user_design" / "sequential_16bit_en.fasm").touch()
@@ -137,10 +134,8 @@ def test_run_tcl(cli, caplog, tmp_path):
137134
assert "TCL script executed" in log[-1]
138135

139136

140-
def test_multi_command_stop(cli, caplog, monkeypatch):
141-
monkeypatch.setattr(
142-
subprocess, "run", lambda: False, raising=ValueError("Command failed")
143-
)
137+
def test_multi_command_stop(cli, mocker):
138+
m = mocker.patch("subprocess.run", side_effect=RuntimeError("Mocked error"))
144139
run_cmd(cli, "run_FABulous_bitstream ./user_design/sequential_16bit_en.v")
145-
log = normalize(caplog.text)
146-
assert "ERROR" in log[-2]
140+
141+
m.assert_called_once()

0 commit comments

Comments
 (0)
Please sign in to comment.