Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 1 | #!/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 |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 5 | """make_new_dif.py is a script for instantiating templates needed to begin |
| 6 | development on a new DIF. |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 7 | |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 8 | To instantiate the files for a new IP named ip_ctrl, run the command: |
| 9 | |
| 10 | $ util/make_new_dif.py --ip-name-snake "ip_ctrl" --ip-name-long "IP Controller" |
| 11 | |
| 12 | where "IP Controller" is a documentation-friendly name for the IP. |
| 13 | For example, compare "pwrmgr" and "Power Manager". |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 14 | |
| 15 | It will instantiate: |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 16 | - `sw/device/lib/dif/dif_template.h.tpl` as the DIF Header boilerplate |
| 17 | (into `dif_<ip>.h`), which should be manually edited/enhanced. |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 18 | - `sw/device/lib/dif/templates/dif_autogen.h.tpl` as the autogenerated DIF |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 19 | Header (into `dif_<ip>_autogen.h`). |
| 20 | - `sw/device/lib/dif/templates/dif_autogen.c.tpl` as the autogenerated DIF |
| 21 | implementation (into `dif_<ip>_autogen.c`). |
| 22 | - `sw/device/lib/dif/templates/dif_autogen_unittest.cc.tpl` as the |
| 23 | autogenerated DIF unit tests (into `dif_<ip>_autogen_unittest.cc`). |
| 24 | - `doc/project/sw_checklist.md.tpl` as the DIF Checklist (into dif_<ip>.md), |
| 25 | which should be manually edited. |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 26 | |
| 27 | See both templates for more information. |
| 28 | |
| 29 | You can also use the `--only=header`, `--only=autogen`, `--only=checklist` to |
| 30 | instantiate a subset of the templates. This can be passed multiple times, and |
| 31 | including `--only=all` will instantiate every template. |
| 32 | |
| 33 | Note: the non-autogenerated files will still need some cleaning up before they |
| 34 | can be used. |
| 35 | """ |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 36 | |
| 37 | import argparse |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 38 | import glob |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 39 | import logging |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 40 | import subprocess |
| 41 | import sys |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 42 | from pathlib import Path |
| 43 | |
Timothy Trippel | 48a9fb7 | 2022-02-10 22:36:40 -0800 | [diff] [blame] | 44 | import hjson |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 45 | from mako.template import Template |
| 46 | |
Timothy Trippel | 48a9fb7 | 2022-02-10 22:36:40 -0800 | [diff] [blame] | 47 | import topgen.lib as lib |
Timothy Trippel | 2f94598 | 2021-11-03 22:31:07 +0000 | [diff] [blame] | 48 | from autogen_banner import get_autogen_banner |
Timothy Trippel | 553475e | 2022-02-22 18:05:28 -0800 | [diff] [blame] | 49 | from autogen_testutils.gen import gen_testutils |
Timothy Trippel | 1c4f7c2 | 2021-10-27 21:46:38 +0000 | [diff] [blame] | 50 | from make_new_dif.ip import Ip |
| 51 | |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 52 | # This file is $REPO_TOP/util/make_new_dif.py, so it takes two parent() |
| 53 | # calls to get back to the top. |
| 54 | REPO_TOP = Path(__file__).resolve().parent.parent |
| 55 | |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 56 | ALL_PARTS = ["header", "checklist", "autogen"] |
| 57 | |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 58 | |
| 59 | def main(): |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 60 | dif_dir = REPO_TOP / "sw/device/lib/dif" |
| 61 | autogen_dif_dir = dif_dir / "autogen" |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 62 | |
| 63 | parser = argparse.ArgumentParser() |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 64 | parser.add_argument( |
| 65 | "--mode", |
| 66 | "-m", |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 67 | choices=["new", "regen"], |
| 68 | default="new", |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 69 | required=True, |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 70 | help="mode to generate DIF code. Use 'new' if no DIF code exists." |
Timothy Trippel | 553475e | 2022-02-22 18:05:28 -0800 | [diff] [blame] | 71 | "Use 'regen' to regenerate all auto-generated DIFs for all IPs.") |
Timothy Trippel | 48a9fb7 | 2022-02-10 22:36:40 -0800 | [diff] [blame] | 72 | parser.add_argument("--topcfg", "-t", help="path of the top hjson file.") |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 73 | parser.add_argument("--ip-name-snake", |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 74 | "-i", |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 75 | help="the short name of the IP, in snake_case.") |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 76 | parser.add_argument("--ip-name-long", |
| 77 | "-l", |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 78 | help="the documentation-friendly name of the IP.") |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 79 | parser.add_argument("--only", |
| 80 | choices=ALL_PARTS, |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 81 | default=[], |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 82 | action="append", |
| 83 | help="only create some files; defaults to all.") |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 84 | args = parser.parse_args() |
| 85 | |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 86 | # Parse CMD line args. |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 87 | ips = [] |
| 88 | |
Timothy Trippel | 553475e | 2022-02-22 18:05:28 -0800 | [diff] [blame] | 89 | # Parse toplevel Hjson to get IPs that are templated / generated with IPgen. |
Timothy Chen | 65ff510 | 2022-01-20 18:42:09 -0800 | [diff] [blame] | 90 | topcfg_path = REPO_TOP / "hw/top_earlgrey/data/top_earlgrey.hjson" |
| 91 | if args.topcfg: |
| 92 | topcfg_path = args.topcfg |
Timothy Chen | 65ff510 | 2022-01-20 18:42:09 -0800 | [diff] [blame] | 93 | try: |
| 94 | with open(topcfg_path, 'r') as ftop: |
Timothy Trippel | 48a9fb7 | 2022-02-10 22:36:40 -0800 | [diff] [blame] | 95 | topcfg = hjson.load(ftop, use_decimal=True) |
Timothy Chen | 65ff510 | 2022-01-20 18:42:09 -0800 | [diff] [blame] | 96 | except FileNotFoundError: |
| 97 | print(f"hjson {topcfg_path} could not be found") |
| 98 | sys.exit(1) |
Timothy Chen | 65ff510 | 2022-01-20 18:42:09 -0800 | [diff] [blame] | 99 | templated_modules = lib.get_templated_modules(topcfg) |
| 100 | ipgen_modules = lib.get_ipgen_modules(topcfg) |
Timothy Trippel | a229825 | 2022-04-12 10:59:39 -0700 | [diff] [blame] | 101 | reggen_top_modules = lib.get_top_reggen_modules(topcfg) |
Timothy Chen | 65ff510 | 2022-01-20 18:42:09 -0800 | [diff] [blame] | 102 | |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 103 | # Check for regeneration mode (used in CI check: |
| 104 | # ci/scripts/check-generated.sh) |
| 105 | if args.mode == "regen": |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 106 | if len(args.only) != 1 or args.only[0] != "autogen": |
| 107 | raise RuntimeError( |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 108 | "can only regenerate DIF code that is auto-generated.") |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 109 | # Create list of IPs to re-generate DIF code for. |
| 110 | for autogen_src_filename in glob.iglob( |
| 111 | str(REPO_TOP / "sw/device/lib/dif/autogen/*.c")): |
| 112 | # NOTE: the line below takes as input a file path |
| 113 | # (/path/to/dif_uart_autogen.c) and returns the IP name in lower |
| 114 | # case snake mode (i.e., uart). |
| 115 | ip_name_snake = Path(autogen_src_filename).stem[4:-8] |
| 116 | # NOTE: ip.name_long_* not needed for auto-generated files which |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 117 | # are the only files (re-)generated in regen mode. |
Timothy Trippel | 48a9fb7 | 2022-02-10 22:36:40 -0800 | [diff] [blame] | 118 | ips.append( |
Timothy Trippel | a229825 | 2022-04-12 10:59:39 -0700 | [diff] [blame] | 119 | Ip(ip_name_snake, "AUTOGEN", templated_modules, ipgen_modules, |
| 120 | reggen_top_modules)) |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 121 | else: |
Timothy Trippel | ed24b15 | 2021-11-03 03:05:04 +0000 | [diff] [blame] | 122 | assert args.ip_name_snake and args.ip_name_long, \ |
| 123 | "ERROR: pass --ip-name-snake and --ip-name-long when --mode=new." |
Timothy Trippel | 48a9fb7 | 2022-02-10 22:36:40 -0800 | [diff] [blame] | 124 | ips.append( |
| 125 | Ip(args.ip_name_snake, args.ip_name_long, templated_modules, |
Timothy Trippel | a229825 | 2022-04-12 10:59:39 -0700 | [diff] [blame] | 126 | ipgen_modules, reggen_top_modules)) |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 127 | |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 128 | # Default to generating all parts. |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 129 | if len(args.only) == 0: |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 130 | args.only += ALL_PARTS |
| 131 | |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 132 | # Create output directories if needed. |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 133 | if len(args.only) > 0: |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 134 | dif_dir.mkdir(exist_ok=True) |
| 135 | autogen_dif_dir.mkdir(exist_ok=True) |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 136 | |
Timothy Trippel | 553475e | 2022-02-22 18:05:28 -0800 | [diff] [blame] | 137 | # Render DIF templates. |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 138 | for ip in ips: |
| 139 | if "header" in args.only: |
Timothy Trippel | 1c4f7c2 | 2021-10-27 21:46:38 +0000 | [diff] [blame] | 140 | header_template_file = ( |
| 141 | REPO_TOP / "util/make_new_dif/templates/dif_template.h.tpl") |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 142 | header_out_file = dif_dir / "dif_{}.h".format(ip.name_snake) |
Timothy Trippel | ed0abd2 | 2021-10-26 03:24:23 +0000 | [diff] [blame] | 143 | if header_out_file.is_file(): |
| 144 | raise FileExistsError( |
Timothy Trippel | 1c4f7c2 | 2021-10-27 21:46:38 +0000 | [diff] [blame] | 145 | "DIF header already exists for the IP. To overwrite, " |
| 146 | "delete existing header and try again.") |
Timothy Trippel | ed0abd2 | 2021-10-26 03:24:23 +0000 | [diff] [blame] | 147 | header_template = Template(header_template_file.read_text()) |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 148 | header_out_file.write_text(header_template.render(ip=ip)) |
| 149 | print("DIF header successfully written to {}.".format( |
| 150 | str(header_out_file))) |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 151 | |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 152 | if "autogen" in args.only: |
Drew Macrae | f2396eb | 2022-06-30 14:28:08 -0400 | [diff] [blame] | 153 | out_files = [] |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 154 | # Render all templates |
Timothy Trippel | 440f960 | 2021-09-22 00:34:29 +0000 | [diff] [blame] | 155 | for filetype in [".h", ".c", "_unittest.cc"]: |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 156 | # Build input/output file names. |
Timothy Trippel | 7b6113d | 2021-09-15 21:51:11 +0000 | [diff] [blame] | 157 | template_file = ( |
Timothy Trippel | 1c4f7c2 | 2021-10-27 21:46:38 +0000 | [diff] [blame] | 158 | REPO_TOP / |
| 159 | f"util/make_new_dif/templates/dif_autogen{filetype}.tpl") |
Timothy Trippel | 7b6113d | 2021-09-15 21:51:11 +0000 | [diff] [blame] | 160 | out_file = (autogen_dif_dir / |
| 161 | f"dif_{ip.name_snake}_autogen{filetype}") |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 162 | |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 163 | # Read in template. |
Timothy Trippel | 6713749 | 2021-09-24 22:54:13 +0000 | [diff] [blame] | 164 | template = Template(template_file.read_text(), |
| 165 | strict_undefined=True) |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 166 | |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 167 | # Generate output file. |
Timothy Trippel | 2f94598 | 2021-11-03 22:31:07 +0000 | [diff] [blame] | 168 | out_file.write_text( |
| 169 | template.render( |
| 170 | ip=ip, |
| 171 | autogen_banner=get_autogen_banner( |
| 172 | "util/make_new_dif.py --mode=regen --only=autogen", |
| 173 | "//"))) |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 174 | |
Drew Macrae | f2396eb | 2022-06-30 14:28:08 -0400 | [diff] [blame] | 175 | # Assemble a list of files to format all at once |
| 176 | out_files += [out_file] |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 177 | |
Drew Macrae | f2396eb | 2022-06-30 14:28:08 -0400 | [diff] [blame] | 178 | # Format autogenerated file with clang-format. |
| 179 | try: |
| 180 | subprocess.check_call( |
Chris Frantz | a0bceb2 | 2022-09-20 15:35:10 -0700 | [diff] [blame] | 181 | ["./ci/bazelisk.sh", "run", "//quality:clang_format_fix", "--"] + out_files |
Drew Macrae | f2396eb | 2022-06-30 14:28:08 -0400 | [diff] [blame] | 182 | ) |
| 183 | except subprocess.CalledProcessError: |
| 184 | logging.error( |
| 185 | f"failed to format {out_file} with clang-format.") |
| 186 | sys.exit(1) |
| 187 | |
| 188 | print("Autogenerated DIF successfully written to {}.".format( |
| 189 | out_files)) |
Sam Elliott | f18219f | 2020-09-23 17:46:10 +0100 | [diff] [blame] | 190 | |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 191 | if "checklist" in args.only: |
| 192 | checklist_template_file = REPO_TOP / "doc/project/sw_checklist.md.tpl" |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 193 | checklist_out_file = dif_dir / "dif_{}.md".format(ip.name_snake) |
Timothy Trippel | ed0abd2 | 2021-10-26 03:24:23 +0000 | [diff] [blame] | 194 | if checklist_out_file.is_file(): |
| 195 | raise FileExistsError( |
Timothy Trippel | 1c4f7c2 | 2021-10-27 21:46:38 +0000 | [diff] [blame] | 196 | "DIF checklist already exists for the IP. To " |
| 197 | "overwrite, delete existing checklist and try again.") |
Timothy Trippel | ed0abd2 | 2021-10-26 03:24:23 +0000 | [diff] [blame] | 198 | markdown_template = Template(checklist_template_file.read_text()) |
Timothy Trippel | d7cb3ae | 2021-09-20 21:28:38 +0000 | [diff] [blame] | 199 | checklist_out_file.write_text(markdown_template.render(ip=ip)) |
| 200 | print("DIF Checklist successfully written to {}.".format( |
| 201 | str(checklist_out_file))) |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 202 | |
Timothy Trippel | 553475e | 2022-02-22 18:05:28 -0800 | [diff] [blame] | 203 | # Render testutils templates. |
| 204 | if args.mode == "regen" or "autogen" in args.only: |
| 205 | gen_testutils(ips) |
| 206 | |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 207 | |
Timothy Trippel | ce9232e | 2021-09-13 22:48:18 +0000 | [diff] [blame] | 208 | if __name__ == "__main__": |
Miguel Young de la Sota | ff15b05 | 2020-09-09 11:26:17 -0400 | [diff] [blame] | 209 | main() |