Skip to content

Commit

Permalink
Merge pull request #516 from zapta/develop
Browse files Browse the repository at this point in the history
Assorted changes
  • Loading branch information
cavearr authored Jan 5, 2025
2 parents 86fac3d + 7348f78 commit 48007bf
Show file tree
Hide file tree
Showing 62 changed files with 968 additions and 749 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"justMyCode": false,
},
{
"name": "Run an apio test",
"name": "Apio test",
"type": "debugpy",
"request": "launch",
"module": "pytest",
Expand Down
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.testing.pytestArgs": [
"test"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
43 changes: 21 additions & 22 deletions COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -620,17 +620,14 @@ Subcommands:
```
Usage: apio packages fix [OPTIONS]
The command ‘apio packages fix’ resolves partially installed or leftover
Apio packages that are listed as broken by the command ‘apio packages list’.
If there are no broken packages, the command does nothing and exits.
The command ‘apio packages fix’ removes broken or obsolete packages that are
listed as broken by the command ‘apio packages list’.
Examples:
apio packages fix # Fix package errors.
apio packages fix -v # Same but with verbose output.
apio packages fix # Fix package errors, if any.
Options:
-v, --verbose Show detailed output.
-h, --help Show this message and exit.
-h, --help Show this message and exit.
```

<br>
Expand Down Expand Up @@ -687,12 +684,11 @@ Usage: apio packages uninstall [OPTIONS] [PACKAGES]...
your system. The command does not uninstall the Apio tool itself.
Examples:
apio packages uninstall # Uninstall all packages.
apio packages uninstall --sayyes # Same but does not ask yes/no.
apio packages uninstall oss-cad-suite # Uninstall only given package(s).
apio packages uninstall # Uninstall all packages
apio packages uninstall oss-cad-suite # Uninstall a package
apio packages uninstall oss-cad-suite examples # Uninstall two packages
Options:
-y, --sayyes Automatically answer YES to all the questions.
-v, --verbose Show detailed output.
-h, --help Show this message and exit.
```
Expand All @@ -710,23 +706,22 @@ Usage: apio raw [OPTIONS] COMMAND
Before running the command, Apio temporarily modifies system environment
variables such as $PATH to provide access to its packages. To view these
environment changes, run the command `apio raw --env`.
environment changes, run the command with the -v option.
Examples:
apio raw -- yosys --version # Yosys version
apio raw -v -- yosys --version # Same but with verbose apio info.
apio raw -- yosys # Run Yosys in interactive mode.
apio raw -- icepll -i 12 -o 30 # Calc ICE PLL
apio raw --env # Show apio env setting.
apio raw -h # Print this help info.
apio raw -v # Show apio env setting.
apio raw -h # Show this help info.
The -- token is used to separate Apio commands and their arguments from the
underlying tools and their arguments. It can be omitted in some cases, but
it’s a good practice to always use it. As a rule of thumb, always prefix the
raw command you want to run with 'apio raw -- '.
Options:
-e, --env Show the apio env changes.
-v, --verbose Show detailed output.
-h, --help Show this message and exit.
```
Expand Down Expand Up @@ -757,15 +752,19 @@ Options:
### apio sim

```
Usage: apio sim [OPTIONS] TESTBENCH
Usage: apio sim [OPTIONS] [TESTBENCH]
The command ‘apio sim’ simulates a testbench file and displays the
simulation results in a GTKWave graphical window. The testbench is expected
to have a name ending with _tb (e.g., my_module_tb.v).
The command ‘apio sim’ simulates the default or the specified testbench file
and displays its simulation results in a graphical GTKWave window. The
testbench is expected to have a name ending with _tb, such as main_tb.v or
main_tb.sv. The default testbench file can be specified using the apio.ini
option ‘default-testbench’. If 'default-testbench' is not specified and the
project has exactly one testbench file, that file will be used as the
default testbench.
Example:
apio sim my_module_tb.v
apio sim my_module_tb.v --force
apio sim # Simulate the default testbench file.
apio sim my_module_tb.v # Simulate the specified testbench file.
[Important] Avoid using the Verilog $dumpfile() function in your
testbenches, as this may override the default name and location Apio sets
Expand All @@ -780,7 +779,7 @@ Usage: apio sim [OPTIONS] TESTBENCH
https://github.com/FPGAwars/apio-examples/tree/master/upduino31/testbench
[Hint] When configuring the signals in GTKWave, save the configuration so
you don’t need to repeat it for each simulation.
you don’t need to repeat it each time you run the simulation.
Options:
-f, --force Force simulation.
Expand Down
96 changes: 57 additions & 39 deletions apio/apio_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# -- Licence GPLv2

import sys
import os.path
import json
import re
import platform
from enum import Enum
from collections import OrderedDict
Expand Down Expand Up @@ -141,16 +141,8 @@ def __init__(
project_dir_arg is None
), "project_dir_arg specified for scope None"

# -- Determine apio home dir. Some tools get confused if the home
# -- dir contains spaces so we prohibit it.
# -- Determine apio home dir.
self.home_dir: Path = ApioContext._get_home_dir()
if re.search("\\s", str(self.home_dir)):
secho(
"Error: The apio home dir path should not contain spaces.",
fg="red",
)
secho(f"Home dir: '{str(self.home_dir)}'", fg="yellow")
sys.exit(1)

# -- Profile information, from ~/.apio/profile.json
self.profile = Profile(self.home_dir)
Expand Down Expand Up @@ -408,12 +400,10 @@ def _resolve_package_envs(
given packages dictionary. For example, %p is replaced with
the package's absolute path."""

for _, package_config in packages.items():
for package_name, package_config in packages.items():

# -- Get the package root dir.
package_path = (
packages_dir / package_config["release"]["folder_name"]
)
package_path = packages_dir / package_name

# -- Get the json 'env' section. We require it, even if empty,
# -- for clarity reasons.
Expand Down Expand Up @@ -446,32 +436,10 @@ def get_package_info(self, package_name: str) -> str:

return package_info

def get_package_folder_name(self, package_name: str) -> str:
"""Returns name of the package folder, within the packages dir.
Exits with an error message if not found."""

package_info = self.get_package_info(package_name)

release = package_info.get("release", {})
folder_name = release.get("folder_name", None)
if not folder_name:
# -- This is a programming error, not a user error
secho(
f"Error: package '{package_name}' definition has an "
"empty or missing 'folder_name' field.",
fg="red",
)
sys.exit(1)

return folder_name

def get_package_dir(self, package_name: str) -> Path:
"""Returns the root path of a package with given name."""

package_folder = self.get_package_folder_name(package_name)
package_dir = self.packages_dir / package_folder

return package_dir
return self.packages_dir / package_name

@staticmethod
def _determine_platform_id(platforms: Dict[str, Dict]) -> str:
Expand Down Expand Up @@ -589,6 +557,51 @@ def is_windows(self) -> bool:
"""Returns True iff platform_id indicates windows."""
return "windows" in self.platform_id

@staticmethod
def _check_home_dir(home_dir: Path):
"""Check the path that was specified in APIO_HOME_DIR. Exit with an
error message if it doesn't comply with apio's requirements.
"""

# Sanity check. If this fails, it's a programming error.
assert isinstance(
home_dir, Path
), f"Error: home_dir is no a Path: {type(home_dir)}, {home_dir}"

# -- The path should be abosolute, see discussion here:
# -- https://github.com/FPGAwars/apio/issues/522
if not home_dir.is_absolute():
secho(
"Error: apio home dir should be an absolute path "
f"[{str(home_dir)}].",
fg="red",
)
secho(
"You can use the system env var APIO_HOME_DIR to set "
"a different apio home dir.",
fg="yellow",
)
sys.exit(1)

# -- We have problem with spaces and non ascii character above value
# -- 127, so we allow only ascii characters in the range [33, 127].
# -- See here https://github.com/FPGAwars/apio/issues/515
for ch in str(home_dir):
if ord(ch) < 33 or ord(ch) > 127:
secho(
f"Error: Unsupported character [{ch}] in apio home dir: "
f"[{str(home_dir)}].",
fg="red",
)
secho(
"Only the ASCII characters in the range 33 to 127 are "
"allowed. You can use the\n"
"system env var 'APIO_HOME_DIR' to set a different apio"
"home dir.",
fg="yellow",
)
sys.exit(1)

@staticmethod
def _get_home_dir() -> Path:
"""Get the absolute apio home dir. This is the apio folder where the
Expand All @@ -609,12 +622,17 @@ def _get_home_dir() -> Path:
# -- Get the home dir. It is what the APIO_HOME_DIR env variable
# -- says, or the default folder if None
if apio_home_dir_env:
# -- Expand user home '~' marker, if exists.
apio_home_dir_env = os.path.expanduser(apio_home_dir_env)
# -- Expand varas such as $HOME or %HOME% on windows.
apio_home_dir_env = os.path.expandvars(apio_home_dir_env)
# -- Convert string to path.
home_dir = Path(apio_home_dir_env)
else:
home_dir = Path.home() / ".apio"

# -- Make it absolute
home_dir = home_dir.absolute()
# -- Verify that the home dir meets apio's requirments.
ApioContext._check_home_dir(home_dir)

# -- Create the folder if it does not exist
try:
Expand Down
4 changes: 2 additions & 2 deletions apio/commands/apio.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def context_settings():
# -- Top click command node.
# ---------------------------

HELP = """
APIO_HELP = """
Work with FPGAs with ease.
Apio is an easy to use and open-source command-line suite designed to
Expand Down Expand Up @@ -121,7 +121,7 @@ def context_settings():
name="apio",
cls=ApioGroup,
subgroups=SUBGROUPS,
help=HELP,
help=APIO_HELP,
short_help="Work with FPGAs with ease",
context_settings=context_settings(),
)
Expand Down
4 changes: 2 additions & 2 deletions apio/commands/apio_boards.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def list_boards(apio_ctx: ApioContext):
# ---------------------------
# R0801: Similar lines in 2 files
# pylint: disable = R0801
HELP = """
APIO_BOARDS_HELP = """
The command 'apio boards' lists the FPGA boards recognized by Apio.
Custom boards can be defined by placing a custom 'boards.json' file in the
project directory, which will override Apio’s default 'boards.json' file.
Expand All @@ -115,7 +115,7 @@ def list_boards(apio_ctx: ApioContext):
@click.command(
name="boards",
short_help="List available board definitions.",
help=HELP,
help=APIO_BOARDS_HELP,
)
@click.pass_context
@options.project_dir_option
Expand Down
4 changes: 2 additions & 2 deletions apio/commands/apio_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# -- COMMAND
# ---------------------------

HELP = """
APIO_BUILD_HELP = """
The command 'apio build' processes the project’s source files and generates a
bitstream file, which can then be uploaded to your FPGA.
Expand All @@ -39,7 +39,7 @@
@click.command(
name="build",
short_help="Synthesize the bitstream.",
help=HELP,
help=APIO_BUILD_HELP,
)
@click.pass_context
@options.project_dir_option
Expand Down
4 changes: 2 additions & 2 deletions apio/commands/apio_clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# ---------------------------
# -- COMMAND
# ---------------------------
HELP = """
APIO_CLEAN_HELP = """
The command 'apio clean' removes temporary files generated in the project
directory by previous Apio commands.
Expand All @@ -32,7 +32,7 @@
@click.command(
name="clean",
short_help="Delete the apio generated files.",
help=HELP,
help=APIO_CLEAN_HELP,
)
@click.pass_context
@options.project_dir_option
Expand Down
4 changes: 2 additions & 2 deletions apio/commands/apio_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
# ---------------------------
# -- COMMAND
# ---------------------------
HELP = """
APIO_CREATE_HELP = """
The command 'apio create' creates a new `apio.ini` project file and is
typically used when setting up a new Apio project.
Expand All @@ -54,7 +54,7 @@
@click.command(
name="create",
short_help="Create an apio.ini project file.",
help=HELP,
help=APIO_CREATE_HELP,
)
@click.pass_context
@board_option
Expand Down
8 changes: 4 additions & 4 deletions apio/commands/apio_drivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# --- apio drivers lsusb

LSUSB_HELP = """
APIO_DRIVERS_LSUSB_HELP = """
The command ‘apio drivers lsusb’ runs the lsusb utility to list the USB
devices connected to your computer. It is typically used for diagnosing
connectivity issues with FPGA boards.
Expand All @@ -33,7 +33,7 @@
@click.command(
name="lsusb",
short_help="List connected USB devices.",
help=LSUSB_HELP,
help=APIO_DRIVERS_LSUSB_HELP,
)
def _lsusb_cli():
"""Implements the 'apio driverss lsusb' command."""
Expand All @@ -51,7 +51,7 @@ def _lsusb_cli():

# --- apio drivers

DRIVERS_HELP = """
APIO_DRIVERS_HELP = """
The command group ‘apio drivers’ contains subcommands used to manage the
drivers on your system.
"""
Expand All @@ -74,7 +74,7 @@ def _lsusb_cli():
cls=ApioGroup,
subgroups=SUBGROUPS,
short_help="Manage the operating system drivers.",
help=DRIVERS_HELP,
help=APIO_DRIVERS_HELP,
)
def cli():
"""Implements the drivers command."""
Expand Down
Loading

0 comments on commit 48007bf

Please sign in to comment.