| #!/usr/bin/env python3 |
| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| r"""IP Generator: Produce IP blocks from IP templates |
| """ |
| import argparse |
| import logging |
| import sys |
| from pathlib import Path |
| |
| from ipgen import (IpBlockRenderer, IpConfig, IpTemplate, TemplateParseError, |
| TemplateRenderError) |
| |
| |
| def init_logging(verbose: bool) -> None: |
| """ Initialize the logging system """ |
| if verbose: |
| logging.basicConfig(format="%(levelname)s: %(message)s", |
| level=logging.DEBUG) |
| else: |
| logging.basicConfig(format="%(levelname)s: %(message)s") |
| |
| |
| def action_generate(ip_template: IpTemplate, args: argparse.Namespace) -> None: |
| """ Handle the 'generate' action/subcommand. """ |
| overwrite_output_dir = args.force |
| output_path = args.outdir |
| |
| # Read the IP configuration file. |
| config_fp = args.config_file |
| config_text = config_fp.read() |
| config_fp.close() |
| ip_config = IpConfig.from_text(ip_template.params, |
| config_text, "the file passed to --config") |
| |
| # Render the IP template into an IP block. |
| renderer = IpBlockRenderer(ip_template, ip_config) |
| renderer.render(output_path, overwrite_output_dir) |
| |
| print(f"Wrote IP block {ip_config.instance_name!r} " |
| f"from template {ip_template.name!r} to '{output_path}'.") |
| |
| |
| def action_describe(ip_template: IpTemplate, args: argparse.Namespace) -> None: |
| """ Handle the 'describe' action/subcommand. """ |
| headline = f"IP template {ip_template.name!r}" |
| print(headline) |
| print('=' * len(headline)) |
| print() |
| print(f"The template is stored in '{ip_template.template_path}'.") |
| print() |
| print("Template parameters") |
| print("-------------------") |
| print() |
| for param in ip_template.params.values(): |
| print(f"{param.name}:") |
| print(f" Description: {param.desc}") |
| print(f" Type: {param.param_type}") |
| print(f" Default value: {param.default}") |
| print() |
| |
| |
| def main() -> int: |
| parser = argparse.ArgumentParser() |
| |
| # Shared arguments across all actions |
| parent_parser = argparse.ArgumentParser(add_help=False) |
| parent_parser.add_argument( |
| "--verbose", |
| help="More info messages", |
| action="store_true", |
| ) |
| parent_parser.add_argument( |
| '-C', |
| '--template-dir', |
| type=Path, |
| required=True, |
| help='IP template directory', |
| ) |
| |
| subparsers = parser.add_subparsers( |
| metavar='ACTION', |
| title="actions", |
| description=("Use 'ipgen.py ACTION --help' to learn more about the " |
| "individual actions.")) |
| subparsers.required = True |
| |
| # 'describe' subparser |
| parser_generate = subparsers.add_parser( |
| "describe", |
| description="Show all information available for the IP template.", |
| help="Show details about an IP template", |
| parents=[parent_parser], |
| ) |
| parser_generate.set_defaults(func=action_describe) |
| |
| # 'generate' subparser |
| parser_generate = subparsers.add_parser( |
| "generate", |
| description="Generate an IP block from an IP template", |
| help="Generate an IP block from an IP template", |
| parents=[parent_parser], |
| ) |
| parser_generate.add_argument( |
| "-o", |
| "--outdir", |
| required=True, |
| type=Path, |
| help="output directory for the resulting IP block", |
| ) |
| parser_generate.add_argument( |
| "--force", |
| "-f", |
| required=False, |
| default=False, |
| action="store_true", |
| help="overwrite the output directory, if it exists", |
| ) |
| parser_generate.add_argument( |
| "--config-file", |
| "-c", |
| required=True, |
| type=argparse.FileType('r'), |
| help="path to a configuration file", |
| ) |
| parser_generate.set_defaults(func=action_generate) |
| |
| # Parse command line arguments, parse IP template, and invoke subparsers |
| args = parser.parse_args() |
| init_logging(args.verbose) |
| |
| try: |
| ip_template = IpTemplate.from_template_path(args.template_dir) |
| args.func(ip_template, args) |
| except (TemplateParseError, TemplateRenderError) as e: |
| if args.verbose: |
| # Show the full backtrace if operating in verbose mode. |
| logging.exception(e) |
| else: |
| # Otherwise just log the problem itself in a more user-friendly way. |
| logging.error(str(e)) |
| return 1 |
| |
| return 0 |
| |
| |
| if __name__ == "__main__": |
| sys.exit(main()) |