|  | #!/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()) |