blob: 3f573e30625005fd815a87128b91d11fde31b0d3 [file] [log] [blame]
Philipp Wagnerdcc5f9f2021-03-10 22:21:39 +00001#!/usr/bin/env python3
2# Copyright lowRISC contributors.
3# Licensed under the Apache License, Version 2.0, see LICENSE for details.
4# SPDX-License-Identifier: Apache-2.0
5r"""IP Generator: Produce IP blocks from IP templates
6"""
7import argparse
8import logging
9import sys
10from pathlib import Path
11
12from ipgen import (IpBlockRenderer, IpConfig, IpTemplate, TemplateParseError,
13 TemplateRenderError)
14
15
16def init_logging(verbose: bool) -> None:
17 """ Initialize the logging system """
18 if verbose:
19 logging.basicConfig(format="%(levelname)s: %(message)s",
20 level=logging.DEBUG)
21 else:
22 logging.basicConfig(format="%(levelname)s: %(message)s")
23
24
25def action_generate(ip_template: IpTemplate, args: argparse.Namespace) -> None:
26 """ Handle the 'generate' action/subcommand. """
27 overwrite_output_dir = args.force
28 output_path = args.outdir
29
30 # Read the IP configuration file.
31 config_fp = args.config_file
32 config_text = config_fp.read()
33 config_fp.close()
34 ip_config = IpConfig.from_text(config_text, "the file passed to --config")
35
36 # Render the IP template into an IP block.
37 renderer = IpBlockRenderer(ip_template, ip_config)
38 renderer.render(output_path, overwrite_output_dir)
39
Philipp Wagner90b438a2021-10-05 10:29:10 +010040 print(f"Wrote IP block {ip_config.instance_name!r} "
41 f"from template {ip_template.name!r} to '{output_path}'.")
Philipp Wagnerdcc5f9f2021-03-10 22:21:39 +000042
43
44def action_describe(ip_template: IpTemplate, args: argparse.Namespace) -> None:
45 """ Handle the 'describe' action/subcommand. """
46 headline = f"IP template {ip_template.name!r}"
47 print(headline)
48 print('=' * len(headline))
49 print()
50 print(f"The template is stored in '{ip_template.template_path}'.")
51 print()
52 print("Template parameters")
53 print("-------------------")
54 print()
55 for param in ip_template.params.values():
56 print(f"{param.name}:")
57 print(f" Description: {param.desc}")
58 print(f" Type: {param.param_type}")
59 print(f" Default value: {param.default}")
60 print()
61
62
63def main() -> int:
64 parser = argparse.ArgumentParser()
65
66 # Shared arguments across all actions
67 parent_parser = argparse.ArgumentParser(add_help=False)
68 parent_parser.add_argument(
69 "--verbose",
70 help="More info messages",
71 action="store_true",
72 )
73 parent_parser.add_argument(
74 '-C',
75 '--template-dir',
76 type=Path,
77 required=True,
78 help='IP template directory',
79 )
80
81 subparsers = parser.add_subparsers(
82 metavar='ACTION',
83 title="actions",
84 description=("Use 'ipgen.py ACTION --help' to learn more about the "
85 "individual actions."))
86 subparsers.required = True
87
88 # 'describe' subparser
89 parser_generate = subparsers.add_parser(
90 "describe",
91 description="Show all information available for the IP template.",
92 help="Show details about an IP template",
93 parents=[parent_parser],
94 )
95 parser_generate.set_defaults(func=action_describe)
96
97 # 'generate' subparser
98 parser_generate = subparsers.add_parser(
99 "generate",
100 description="Generate an IP block from an IP template",
101 help="Generate an IP block from an IP template",
102 parents=[parent_parser],
103 )
104 parser_generate.add_argument(
105 "-o",
106 "--outdir",
107 required=True,
108 type=Path,
109 help="output directory for the resulting IP block",
110 )
111 parser_generate.add_argument(
112 "--force",
113 "-f",
114 required=False,
115 default=False,
116 action="store_true",
117 help="overwrite the output directory, if it exists",
118 )
119 parser_generate.add_argument(
120 "--config-file",
121 "-c",
122 required=False,
123 type=argparse.FileType('r'),
124 help="path to a configuration file",
125 )
126 parser_generate.set_defaults(func=action_generate)
127
128 # Parse command line arguments, parse IP template, and invoke subparsers
129 args = parser.parse_args()
130 init_logging(args.verbose)
131
132 try:
133 ip_template = IpTemplate.from_template_path(args.template_dir)
134 args.func(ip_template, args)
135 except (TemplateParseError, TemplateRenderError) as e:
136 if args.verbose:
137 # Show the full backtrace if operating in verbose mode.
138 logging.exception(e)
139 else:
140 # Otherwise just log the problem itself in a more user-friendly way.
141 logging.error(str(e))
142 return 1
143
144 return 0
145
146
147if __name__ == "__main__":
148 sys.exit(main())