blob: 462ade14420bd120660edbb19eca30b1430faa5e [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()
Rupert Swarbrickf7562c72021-11-12 09:57:24 +000034 ip_config = IpConfig.from_text(ip_template.params,
35 config_text, "the file passed to --config")
Philipp Wagnerdcc5f9f2021-03-10 22:21:39 +000036
37 # Render the IP template into an IP block.
38 renderer = IpBlockRenderer(ip_template, ip_config)
39 renderer.render(output_path, overwrite_output_dir)
40
Philipp Wagner90b438a2021-10-05 10:29:10 +010041 print(f"Wrote IP block {ip_config.instance_name!r} "
42 f"from template {ip_template.name!r} to '{output_path}'.")
Philipp Wagnerdcc5f9f2021-03-10 22:21:39 +000043
44
45def action_describe(ip_template: IpTemplate, args: argparse.Namespace) -> None:
46 """ Handle the 'describe' action/subcommand. """
47 headline = f"IP template {ip_template.name!r}"
48 print(headline)
49 print('=' * len(headline))
50 print()
51 print(f"The template is stored in '{ip_template.template_path}'.")
52 print()
53 print("Template parameters")
54 print("-------------------")
55 print()
56 for param in ip_template.params.values():
57 print(f"{param.name}:")
58 print(f" Description: {param.desc}")
59 print(f" Type: {param.param_type}")
60 print(f" Default value: {param.default}")
61 print()
62
63
64def main() -> int:
65 parser = argparse.ArgumentParser()
66
67 # Shared arguments across all actions
68 parent_parser = argparse.ArgumentParser(add_help=False)
69 parent_parser.add_argument(
70 "--verbose",
71 help="More info messages",
72 action="store_true",
73 )
74 parent_parser.add_argument(
75 '-C',
76 '--template-dir',
77 type=Path,
78 required=True,
79 help='IP template directory',
80 )
81
82 subparsers = parser.add_subparsers(
83 metavar='ACTION',
84 title="actions",
85 description=("Use 'ipgen.py ACTION --help' to learn more about the "
86 "individual actions."))
87 subparsers.required = True
88
89 # 'describe' subparser
90 parser_generate = subparsers.add_parser(
91 "describe",
92 description="Show all information available for the IP template.",
93 help="Show details about an IP template",
94 parents=[parent_parser],
95 )
96 parser_generate.set_defaults(func=action_describe)
97
98 # 'generate' subparser
99 parser_generate = subparsers.add_parser(
100 "generate",
101 description="Generate an IP block from an IP template",
102 help="Generate an IP block from an IP template",
103 parents=[parent_parser],
104 )
105 parser_generate.add_argument(
106 "-o",
107 "--outdir",
108 required=True,
109 type=Path,
110 help="output directory for the resulting IP block",
111 )
112 parser_generate.add_argument(
113 "--force",
114 "-f",
115 required=False,
116 default=False,
117 action="store_true",
118 help="overwrite the output directory, if it exists",
119 )
120 parser_generate.add_argument(
121 "--config-file",
122 "-c",
Rupert Swarbrick30204702022-03-04 11:10:23 +0000123 required=True,
Philipp Wagnerdcc5f9f2021-03-10 22:21:39 +0000124 type=argparse.FileType('r'),
125 help="path to a configuration file",
126 )
127 parser_generate.set_defaults(func=action_generate)
128
129 # Parse command line arguments, parse IP template, and invoke subparsers
130 args = parser.parse_args()
131 init_logging(args.verbose)
132
133 try:
134 ip_template = IpTemplate.from_template_path(args.template_dir)
135 args.func(ip_template, args)
136 except (TemplateParseError, TemplateRenderError) as e:
137 if args.verbose:
138 # Show the full backtrace if operating in verbose mode.
139 logging.exception(e)
140 else:
141 # Otherwise just log the problem itself in a more user-friendly way.
142 logging.error(str(e))
143 return 1
144
145 return 0
146
147
148if __name__ == "__main__":
149 sys.exit(main())