f4pga: make_flow_config procedure for simplifying creating FlowConfig (#571)

This commit is contained in:
Unai Martinez-Corral 2022-06-14 10:14:09 +02:00 committed by GitHub
commit 3f1e719aa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 43 deletions

View File

@ -46,6 +46,7 @@ from typing import Iterable
from colorama import Fore, Style
from f4pga.common import (
F4PGAException,
ResolutionEnv,
fatal,
scan_modules,
@ -74,17 +75,15 @@ mypath = str(Path(__file__).resolve().parent)
share_dir_path = str(Path(f"{environ.get('F4PGA_INSTALL_DIR', '/usr/local')}/xc7/install/share/symbiflow").resolve())
class DependencyNotProducedException(Exception):
class DependencyNotProducedException(F4PGAException):
dep_name: str
provider: str
def __init__(self, dep_name: str, provider: str):
self.dep_name = dep_name
self.provider = provider
def __str__(self) -> str:
return f'Stage `{self.provider}` did not produce promised ' \
f'dependency `{self.dep_name}`'
self.message = f'Stage `{self.provider}` did not produce promised ' \
f'dependency `{self.dep_name}`'
def dep_value_str(dep: str):
return ':' + dep
@ -270,7 +269,7 @@ class Flow:
skip_dep_warnings: 'set[str]' = None):
if skip_dep_warnings is None:
skip_dep_warnings = set()
# Initialize the dependency status if necessary
if self.deps_rebuilds.get(dep) is None:
self.deps_rebuilds[dep] = 0
@ -297,7 +296,7 @@ class Flow:
if not take_paths and take.spec == 'req':
_print_unreachable_stage_message(provider, take)
return
will_differ = False
if take_paths is None:
# TODO: This won't trigger rebuild if an optional dependency got removed
@ -507,7 +506,7 @@ def sfbuild_done():
exit(0)
def setup_resolution_env():
""" Sets up a ResolutionEnv with sfbuild's default built-ins. """
""" Sets up a ResolutionEnv with default built-ins. """
r_env = ResolutionEnv({
'shareDir': share_dir_path,
@ -563,33 +562,24 @@ def get_platform_name_for_part(part_name: str):
with (Path(mypath) / 'part_db.json').open('r') as rfptr:
return json_load(rfptr).get(part_name.upper())
def cmd_build(args: Namespace):
""" sfbuild's `build` command implementation """
def make_flow_config(project_flow_cfg: ProjectFlowConfig, part_name: str) -> FlowConfig:
""" Create `FlowConfig` from given project flow configuration and part name """
project_flow_cfg: ProjectFlowConfig = None
platform: 'str | None' = None
part_name = args.part
if args.part:
platform = get_platform_name_for_part(args.part)
if args.flow:
project_flow_cfg = open_project_flow_config(args.flow)
elif part_name is not None:
project_flow_cfg = ProjectFlowConfig('.temp.flow.json')
project_flow_cfg.flow_cfg = get_cli_flow_config(args, platform)
if part_name is None and project_flow_cfg is not None:
part_name = project_flow_cfg.get_default_part()
platform = get_platform_name_for_part(part_name)
if platform is None:
fatal(-1, 'You have to specify a part name or configure a default part.')
if project_flow_cfg is None:
fatal(-1, 'No configuration was provided. Use `--flow`, and/or '
'`--part` to configure flow.')
raise F4PGAException(
message='You have to specify a part name or configure a default part.'
)
if part_name not in project_flow_cfg.parts():
fatal('Project flow configuration does not support requested part.')
raise F4PGAException(
message='Project flow configuration does not support requested part.'
)
r_env = setup_resolution_env()
r_env.add_values({'part_name': part_name.lower()})
scan_modules(mypath)
platform_path = str(Path(mypath) / f'platforms/{platform}.json')
platform_def = None
@ -597,23 +587,41 @@ def cmd_build(args: Namespace):
with open(platform_path) as platform_file:
platform_def = platform_file.read()
except FileNotFoundError as _:
fatal(-1, f'The platform flow definition file {platform_path} for the platform '
f'{platform} referenced in flow definition file {args.flow} '
'cannot be found.')
r_env = setup_resolution_env()
r_env.add_values({'part_name': part_name.lower()})
sfprint(2, 'Scanning modules...')
scan_modules(mypath)
raise F4PGAException(
message=f'The platform flow definition file {platform_path} for the platform ' \
f'{platform} cannot be found.'
)
flow_definition_dict = json_loads(platform_def)
flow_def = FlowDefinition(flow_definition_dict, r_env)
flow_cfg = FlowConfig(project_flow_cfg, flow_def, part_name)
if len(flow_cfg.stages) == 0:
fatal(-1, 'Platform flow does not define any stage')
raise F4PGAException(message = 'Platform flow does not define any stage')
return flow_cfg
def cmd_build(args: Namespace):
""" `build` command implementation """
project_flow_cfg: ProjectFlowConfig = None
part_name = args.part
if args.flow:
project_flow_cfg = open_project_flow_config(args.flow)
elif part_name is not None:
project_flow_cfg = ProjectFlowConfig('.temp.flow.json')
project_flow_cfg.flow_cfg = get_cli_flow_config(args, part_name)
if part_name is None and project_flow_cfg is not None:
part_name = project_flow_cfg.get_default_part()
if project_flow_cfg is None:
fatal(-1, 'No configuration was provided. Use `--flow`, and/or '
'`--part` to configure flow.')
flow_cfg = make_flow_config(project_flow_cfg, part_name)
if args.info:
display_dep_info(flow_cfg.stages.values())
@ -656,7 +664,7 @@ def cmd_build(args: Namespace):
flow.f4cache.save()
def cmd_show_dependencies(args: Namespace):
""" sfbuild's `showd` command implementation """
""" `showd` command implementation """
flow_cfg = open_project_flow_config(args.flow)

View File

@ -25,6 +25,16 @@ from shutil import move as sh_mv
from subprocess import run
from re import match as re_match, finditer as re_finditer
class F4PGAException(Exception):
def __init__(self, message = 'unknown exception'):
self.message = message
def __repr__(self):
return f'F4PGAException(message = \'{self.message}\')'
def __str__(self):
return self.message
def decompose_depname(name: str):
spec = 'req'