Skip to content
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

Add support for using yowasp when yosys is not available. #283

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions luna/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from amaranth import Elaboratable
from amaranth._unused import MustUse

from luna.gateware.platform import configure_toolchain

# Log formatting strings.
LOG_FORMAT_COLOR = "\u001b[37;1m%(levelname)-8s| \u001b[0m\u001b[1m%(module)-12s|\u001b[0m %(message)s"
LOG_FORMAT_PLAIN = "%(levelname)-8s:n%(module)-12s>%(message)s"
Expand Down Expand Up @@ -108,8 +110,15 @@ def top_level_cli(fragment, *pos_args, **kwargs):
join_text = "and uploading gateware to attached" if args.upload else "for"
logging.info(f"Building {join_text} {platform.name}...")

# Configure toolchain.
if not configure_toolchain(platform):
logging.info(f"Failed to configure the toolchain for: {platform.toolchain}")
logging.info(f"Continuing anyway.")

# Now that we're actually building, re-enable Unused warnings.
MustUse._MustUse__silence = False

# Perform the build.
products = platform.build(fragment,
do_program=args.upload,
build_dir=build_dir
Expand Down
5 changes: 3 additions & 2 deletions luna/gateware/platform/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from amaranth import Record

from .core import NullPin, LUNAPlatform
from .toolchain import configure_toolchain


def _get_platform_from_string(platform):
Expand Down Expand Up @@ -63,11 +64,11 @@ def get_appropriate_platform() -> LUNAPlatform:
"Unable to autodetect a supported platform. "
"The LUNA_PLATFORM environment variable must be set.")
platform = _get_platform_from_string(platform_string)

# If possible, override the platform's device type with the detected FPGA.
if fpga_device is not None:
platform.device = fpga_device

return platform


Expand Down
72 changes: 72 additions & 0 deletions luna/gateware/platform/toolchain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#
# This file is part of LUNA.
#
# Copyright (c) 2020-2024 Great Scott Gadgets <[email protected]>
# SPDX-License-Identifier: BSD-3-Clause

""" Utilities for managing LUNA gateware toolchains. """

import importlib
import logging
import os
import shutil

def configure_toolchain(platform):
""" Checks if all the required tools for the Yosys toolchain are available.

If there are missing tools it will attempt to fall back to YoWASP instead.

Returns:
True if a valid toolchain has been configured. Otherwise False.
"""

if platform.has_required_tools():
# All good, no further hanky-panky required.
return True

# Do we have yowasp available to us?
logging.info(f"Failed to locate {platform.toolchain} toolchain, trying YoWASP.")
logging.debug("Checking for required tools:")
for tool in platform.required_tools:
logging.debug(f" {tool}")

problems = 0

# Check whether yowasp-yosys is installed:
try:
import yowasp_yosys
logging.debug(f"Found module: {yowasp_yosys.__name__}")
except Exception as e:
problems += 1
logging.warning(e)

# Check whether yowasp-nextpnr-<target> is installed:
try:
nextpnr = next(filter(lambda x: x.startswith("nextpnr-"), platform.required_tools))
yowasp_nextpnr = importlib.import_module("yowasp_" + nextpnr.replace('-', '_'))
logging.debug(f"Found module: {yowasp_nextpnr.__name__}")
except Exception as e:
problems += 1
logging.warning(e)

# Check whether the YoWASP binaries are on the system PATH:
for tool in platform.required_tools:
env_var = tool.replace('-', '_').upper()
yowasp_tool = "yowasp-" + tool
path = shutil.which(yowasp_tool)
if not path:
problems += 1
logging.warning(f"'{yowasp_tool}' is not on the system PATH.")
else:
logging.debug(f'Setting {env_var}="{yowasp_tool}"')
os.environ[env_var] = yowasp_tool

if problems == 0:
logging.info("YoWASP configured successfully.")
else:
logging.info(f"{problems} problems encountered while configuring YoWASP.")
logging.info(f"You can install it with:")
logging.info(f" pip install yowasp-yosys yowasp-{nextpnr}")
return False

return True
Loading