Skip to content

feat: Add force mode, improve exception handling, correct debug log and direct command input with testing #365

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

KelvinChung2000
Copy link
Collaborator

@KelvinChung2000 KelvinChung2000 commented May 28, 2025

Introduce a force mode to allow commands to run despite errors, and enhance exception handling by overriding the onecmd method to catch exceptions properly.

Adjust the debug log level to only display debug logs when the debug flag is set.

add the -p option for pass cmd directly into the CLI.

Add tests for the start-up script.

Make the existing test pytest discoverable.

@EverythingElseWasAlreadyTaken
Copy link
Collaborator

Looks good, but there is one issue that is still persistent:
When I run the FABulous.tcl and there is an error, the script still continues, I would expect it to end directly

@KelvinChung2000
Copy link
Collaborator Author

Are you calling by parameter or calling it from inside the CLI? Because if it is called by parameter, the fix will need to be in another PR, since this will be linking to #319

@EverythingElseWasAlreadyTaken
Copy link
Collaborator

By param -fs/-ts act the same.

@KelvinChung2000
Copy link
Collaborator Author

Yes, this is because the command execution happens at the CLI initialisation, which cmd2 geraintne the application will start up successfully, despite having an error. As a result, I will need to change how this should behave.

@KelvinChung2000 KelvinChung2000 changed the title feat: Add force mode, improve exception handling and correct debug log feat: Add force mode, improve exception handling, correct debug log and direct command input May 28, 2025
@KelvinChung2000
Copy link
Collaborator Author

Halting of the shell is depends on the return value of the command. If it rturn true, then the shell will be closed. We might want to unify how we handle error in the shell. Do we always return true (exit) on error, or raise an exception?

@EverythingElseWasAlreadyTaken
Copy link
Collaborator

Halting of the shell is depends on the return value of the command. If it rturn true, then the shell will be closed. We might want to unify how we handle error in the shell. Do we always return true (exit) on error, or raise an exception?

We should raise an exception, returning true in case of an error just feels wrong.
And also if people start using FABulous as dependency, or it is somehow automated externally, it would cause serious headaches if it always returns true. ^^

As a simplification, we could automatically call the load_fabric command on entering the shell.
This would reduce the needed interaction for the user.

@KelvinChung2000
Copy link
Collaborator Author

I have updated the logic to add an interactive mode. Now, when the user is in interactive mode, it will always stay in the shell no matter what error is raised. When it is not in interactive mode, it will always set the exit code to 1, and it depends on whether the user wants to force execution. If force is enabled, it will keep running even if there is an error; otherwise, it will terminate the shell.

I have added the load_fabric command on start up.

@KelvinChung2000
Copy link
Collaborator Author

I like to know what the expected behaviour is for the global environment. The current implementation is that the env variable overrides the user-supplied path, which seems a bit odd to me.

@EverythingElseWasAlreadyTaken
Copy link
Collaborator

EverythingElseWasAlreadyTaken commented Jun 10, 2025

I like to know what the expected behaviour is for the global environment. The current implementation is that the env variable overrides the user-supplied path, which seems a bit odd to me.

You are right, this is a bug then.
Is it for all environment variables?
The user provided information should always override the global env.
The hierarchy should be like the following (from highest to lowest priority):
user provided information > shell environment (e.g. export FAB_ROOT ...) > project .env > global .env > default values.

@EverythingElseWasAlreadyTaken
Copy link
Collaborator

EverythingElseWasAlreadyTaken commented Jun 10, 2025

I have updated the logic to add an interactive mode. Now, when the user is in interactive mode, it will always stay in the shell no matter what error is raised. When it is not in interactive mode, it will always set the exit code to 1, and it depends on whether the user wants to force execution. If force is enabled, it will keep running even if there is an error; otherwise, it will terminate the shell.

I have added the load_fabric command on start up.

Is the interactive mode the default for the tcl and FABulous script execution?
How do I use the interactive mode?

If I add an error, it still tries to run the whole flow afterwards.

As an example, I added a new primitive to the fabric, which I didn't add to yosys prims lib.
When I run run_FABulous_bitstream, I get the followning output:

INFO | No external primsLib found.
INFO | Running synthesis targeting Nextpnr with design ['user_design/sequential_16bit_en.v']

 /----------------------------------------------------------------------------\
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |  Copyright (C) 2012 - 2025  Claire Xenia Wolf <[email protected]>         |
 |  Distributed under an ISC-like license, type "license" to see terms        |
 \----------------------------------------------------------------------------/
 Yosys 0.53+15 (git sha1 690081810, clang++ 18.1.8 -fPIC -O3)

-- Parsing `/home/jart/work/uni/FABulous/demo/user_design/top_wrapper.v' using frontend ` -vlog2k' --

1. Executing Verilog-2005 frontend: /home/jart/work/uni/FABulous/demo/user_design/top_wrapper.v
Parsing Verilog input from `/home/jart/work/uni/FABulous/demo/user_design/top_wrapper.v' to AST representation.
Storing AST representation for module `$abstract\top_wrapper'.
Successfully finished Verilog frontend.

-- Parsing `/home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.v' using frontend ` -vlog2k' --

2. Executing Verilog-2005 frontend: /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.v
Parsing Verilog input from `/home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.v' to AST representation.
Storing AST representation for module `$abstract\top'.
Successfully finished Verilog frontend.

-- Running command `synth_fabulous -top top_wrapper -json /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.json -lut 4 -carry none' --

3. Executing SYNTH_FABULOUS pass.

3.1. Executing Verilog-2005 frontend: /opt/oss-cad-suite/lib/../share/yosys/fabulous/prims.v
Parsing Verilog input from `/opt/oss-cad-suite/lib/../share/yosys/fabulous/prims.v' to AST representation.
Generating RTLIL representation for module `\LUT1'.
Generating RTLIL representation for module `\LUT2'.
Generating RTLIL representation for module `\LUT3'.
Generating RTLIL representation for module `\LUT4'.
Generating RTLIL representation for module `\LUT4_HA'.
Generating RTLIL representation for module `\LUT5'.
Generating RTLIL representation for module `\LUT6'.
Generating RTLIL representation for module `\LUT55_FCY'.
Generating RTLIL representation for module `\LUTFF'.
Generating RTLIL representation for module `\FABULOUS_MUX2'.
Generating RTLIL representation for module `\FABULOUS_MUX4'.
Generating RTLIL representation for module `\FABULOUS_MUX8'.
Generating RTLIL representation for module `\FABULOUS_LC'.
Generating RTLIL representation for module `\Global_Clock'.
Generating RTLIL representation for module `\InPass4_frame_config'.
Generating RTLIL representation for module `\OutPass4_frame_config'.
Generating RTLIL representation for module `\IO_1_bidirectional_frame_config_pass'.
Generating RTLIL representation for module `\MULADD'.
Generating RTLIL representation for module `\RegFile_32x4'.
Successfully finished Verilog frontend.

3.2. Executing HIERARCHY pass (managing design hierarchy).

3.3. Executing AST frontend in derive mode using pre-parsed AST for module `\top_wrapper'.
Generating RTLIL representation for module `\top_wrapper'.

3.3.1. Analyzing design hierarchy..
Top module:  \top_wrapper

3.3.2. Executing AST frontend in derive mode using pre-parsed AST for module `\top'.
Generating RTLIL representation for module `\top'.
ERROR: Module `\IO_2_bidirectional_frame_config_pass' referenced in module `\top_wrapper' in cell `\io1_i' is not part of the design.
ERROR | Synthesis failed
INFO | Running Placement and Routing with Nextpnr for design user_design/sequential_16bit_en.json
Info: Detected FABulous 2.0 format project.

ERROR: Top-level port 'io_out[24]' driven by illegal port $PACKER_GND_DRV.O
ERROR: Packing design failed.
0 warnings, 2 errors
ERROR | CalledProcessError | Placement and Routing failed.
INFO | Placement and Routing completed
INFO | Generating Bitstream for design /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.fasm
INFO | Outputting to /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.bin
/home/jart/work/uni/FABulous/venv/FABulous-apck/lib/python3.13/site-packages/fasm/parser/__init__.py:30: RuntimeWarning: Unable to import fast Antlr4 parser implementation.
  ImportError: cannot import name 'antlr_to_tuple' from partially initialized module 'fasm.parser' (most likely due to a circular import) (/home/jart/work/uni/FABulous/venv/FABulous-apck/lib/python3.13/site-packages/fasm/parser/__init__.py)

  Falling back to the much slower pure Python textX based parser
  implementation.

  Getting the faster antlr parser can normally be done by installing the
  required dependencies and then reinstalling the fasm package with:
    pip uninstall
    pip install -v fasm

  warn(
INFO | Bitstream generated

I would expect that after a failed synthesis, the execution stops, but it still tires PnR, which also fails, but still adds the message Place and Route completed, even after the failed PnR.
Then it runs bit_gen, which does not seem to fail, but this could be because of old fragments of previous PnR runs lying around.

This behavior is the same for the manual shell execution, as well as FABulous Script and TCL script.

@KelvinChung2000
Copy link
Collaborator Author

Is it for all environment variables?

At least for project_dir. I am not sure about the rest. I only notice this when we are running the tests back to back.

How do I use the interactive mode?

This is what we usually have; the CLI is the interactive mode. This basically enables force mode, so the user will never exit the shell when they encounter an error running any command.

I will update those "super command" behaviours.

@KelvinChung2000 KelvinChung2000 changed the title feat: Add force mode, improve exception handling, correct debug log and direct command input feat: Add force mode, improve exception handling, correct debug log and direct command input with testing Jun 10, 2025
@EverythingElseWasAlreadyTaken
Copy link
Collaborator

At least for project_dir. I am not sure about the rest. I only notice this when we are running the tests back to back.

I'll open an issue for that.

How do I use the interactive mode?

This is what we usually have; the CLI is the interactive mode. This basically enables force mode, so the user will never exit the shell when they encounter an error running any command.

We should add some documentation about this.

I will update those "super command" behaviours.

Ok, I'll convert the PR to draft, until it's done.

@EverythingElseWasAlreadyTaken
Copy link
Collaborator

I have updated the logic to add an interactive mode. Now, when the user is in interactive mode, it will always stay in the shell no matter what error is raised. When it is not in interactive mode, it will always set the exit code to 1, and it depends on whether the user wants to force execution. If force is enabled, it will keep running even if there is an error; otherwise, it will terminate the shell.
I have added the load_fabric command on start up.

Is the interactive mode the default for the tcl and FABulous script execution? How do I use the interactive mode?

If I add an error, it still tries to run the whole flow afterwards.

As an example, I added a new primitive to the fabric, which I didn't add to yosys prims lib. When I run run_FABulous_bitstream, I get the followning output:

INFO | No external primsLib found.
INFO | Running synthesis targeting Nextpnr with design ['user_design/sequential_16bit_en.v']

 /----------------------------------------------------------------------------\
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |  Copyright (C) 2012 - 2025  Claire Xenia Wolf <[email protected]>         |
 |  Distributed under an ISC-like license, type "license" to see terms        |
 \----------------------------------------------------------------------------/
 Yosys 0.53+15 (git sha1 690081810, clang++ 18.1.8 -fPIC -O3)

-- Parsing `/home/jart/work/uni/FABulous/demo/user_design/top_wrapper.v' using frontend ` -vlog2k' --

1. Executing Verilog-2005 frontend: /home/jart/work/uni/FABulous/demo/user_design/top_wrapper.v
Parsing Verilog input from `/home/jart/work/uni/FABulous/demo/user_design/top_wrapper.v' to AST representation.
Storing AST representation for module `$abstract\top_wrapper'.
Successfully finished Verilog frontend.

-- Parsing `/home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.v' using frontend ` -vlog2k' --

2. Executing Verilog-2005 frontend: /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.v
Parsing Verilog input from `/home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.v' to AST representation.
Storing AST representation for module `$abstract\top'.
Successfully finished Verilog frontend.

-- Running command `synth_fabulous -top top_wrapper -json /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.json -lut 4 -carry none' --

3. Executing SYNTH_FABULOUS pass.

3.1. Executing Verilog-2005 frontend: /opt/oss-cad-suite/lib/../share/yosys/fabulous/prims.v
Parsing Verilog input from `/opt/oss-cad-suite/lib/../share/yosys/fabulous/prims.v' to AST representation.
Generating RTLIL representation for module `\LUT1'.
Generating RTLIL representation for module `\LUT2'.
Generating RTLIL representation for module `\LUT3'.
Generating RTLIL representation for module `\LUT4'.
Generating RTLIL representation for module `\LUT4_HA'.
Generating RTLIL representation for module `\LUT5'.
Generating RTLIL representation for module `\LUT6'.
Generating RTLIL representation for module `\LUT55_FCY'.
Generating RTLIL representation for module `\LUTFF'.
Generating RTLIL representation for module `\FABULOUS_MUX2'.
Generating RTLIL representation for module `\FABULOUS_MUX4'.
Generating RTLIL representation for module `\FABULOUS_MUX8'.
Generating RTLIL representation for module `\FABULOUS_LC'.
Generating RTLIL representation for module `\Global_Clock'.
Generating RTLIL representation for module `\InPass4_frame_config'.
Generating RTLIL representation for module `\OutPass4_frame_config'.
Generating RTLIL representation for module `\IO_1_bidirectional_frame_config_pass'.
Generating RTLIL representation for module `\MULADD'.
Generating RTLIL representation for module `\RegFile_32x4'.
Successfully finished Verilog frontend.

3.2. Executing HIERARCHY pass (managing design hierarchy).

3.3. Executing AST frontend in derive mode using pre-parsed AST for module `\top_wrapper'.
Generating RTLIL representation for module `\top_wrapper'.

3.3.1. Analyzing design hierarchy..
Top module:  \top_wrapper

3.3.2. Executing AST frontend in derive mode using pre-parsed AST for module `\top'.
Generating RTLIL representation for module `\top'.
ERROR: Module `\IO_2_bidirectional_frame_config_pass' referenced in module `\top_wrapper' in cell `\io1_i' is not part of the design.
ERROR | Synthesis failed
INFO | Running Placement and Routing with Nextpnr for design user_design/sequential_16bit_en.json
Info: Detected FABulous 2.0 format project.

ERROR: Top-level port 'io_out[24]' driven by illegal port $PACKER_GND_DRV.O
ERROR: Packing design failed.
0 warnings, 2 errors
ERROR | CalledProcessError | Placement and Routing failed.
INFO | Placement and Routing completed
INFO | Generating Bitstream for design /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.fasm
INFO | Outputting to /home/jart/work/uni/FABulous/demo/user_design/sequential_16bit_en.bin
/home/jart/work/uni/FABulous/venv/FABulous-apck/lib/python3.13/site-packages/fasm/parser/__init__.py:30: RuntimeWarning: Unable to import fast Antlr4 parser implementation.
  ImportError: cannot import name 'antlr_to_tuple' from partially initialized module 'fasm.parser' (most likely due to a circular import) (/home/jart/work/uni/FABulous/venv/FABulous-apck/lib/python3.13/site-packages/fasm/parser/__init__.py)

  Falling back to the much slower pure Python textX based parser
  implementation.

  Getting the faster antlr parser can normally be done by installing the
  required dependencies and then reinstalling the fasm package with:
    pip uninstall
    pip install -v fasm

  warn(
INFO | Bitstream generated

I would expect that after a failed synthesis, the execution stops, but it still tires PnR, which also fails, but still adds the message Place and Route completed, even after the failed PnR. Then it runs bit_gen, which does not seem to fail, but this could be because of old fragments of previous PnR runs lying around.

This behavior is the same for the manual shell execution, as well as FABulous Script and TCL script.

It's still the same for the run_FABulous_bitstream command. Each CLI, TCL or FS does not break execution properly in case of an Error.

@EverythingElseWasAlreadyTaken
Copy link
Collaborator

The error handling seems to work now!

But it seems, that broke the force mode, which now seems to also exits on errors.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great PR!
Looks like everything is working fine now.

I've added a few minor comments, if these are fixed, we can merge that PR. :)

@EverythingElseWasAlreadyTaken EverythingElseWasAlreadyTaken merged commit ca4ee2a into FPGA-Research:FABulous2.0-development Jun 13, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants