blob: 462ade14420bd120660edbb19eca30b1430faa5e [file] [log] [blame]
#!/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())