[util] Organize and package `make_new_dif.py` classes.
IP HJSON file are parsed by the `util/make_new_dif.py` tool to load
IP metadata needed for auto-generating DIFs. This python code was
originally all contained in the `util/make_new_dif.py` script. By
repackaging it, we can reuse this code in the
`util/check_dif_statuses.py` script.
Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/util/make_new_dif.py b/util/make_new_dif.py
index 295c7f1..d626c85 100755
--- a/util/make_new_dif.py
+++ b/util/make_new_dif.py
@@ -32,156 +32,18 @@
import shutil
import subprocess
import sys
-from collections import OrderedDict
from pathlib import Path
-import hjson
from mako.template import Template
+from make_new_dif.ip import Ip
+
# This file is $REPO_TOP/util/make_new_dif.py, so it takes two parent()
# calls to get back to the top.
REPO_TOP = Path(__file__).resolve().parent.parent
ALL_PARTS = ["header", "checklist", "autogen"]
-IPS_USING_IPGEN = [
- 'rv_plic',
- 'alert_handler',
-]
-
-
-class Alert:
- """Holds alert information for populating DIF code templates.
-
- Attributes:
- name_snake (str): Alert short name in lower snake case.
- name_upper (str): Alert short name in upper snake case.
- name_camel (str): Alert short name in camel case.
- description (str): Full description of the alert.
-
- """
- def __init__(self, alert: OrderedDict) -> None:
- self.name_snake = alert["name"]
- self.name_upper = self.name_snake.upper()
- self.name_camel = "".join(
- [word.capitalize() for word in self.name_snake.split("_")])
- _multiline_description = alert["desc"][0].upper() + alert["desc"][1:]
- self.description = _multiline_description.replace("\n", " ")
-
-
-class Irq:
- """Holds IRQ information for populating DIF code templates.
-
- Attributes:
- name_snake (str): IRQ short name in lower snake case.
- name_upper (str): IRQ short name in upper snake case.
- name_camel (str): IRQ short name in camel case.
- description (str): full description of the IRQ.
-
- """
- def __init__(self, irq: OrderedDict) -> None:
- self.name_snake = irq["name"]
- self.name_upper = self.name_snake.upper()
- self.name_camel = "".join(
- [word.capitalize() for word in self.name_snake.split("_")])
- _multiline_description = irq["desc"][0].upper() + irq["desc"][1:]
- self.description = _multiline_description.replace("\n", " ")
- self.width = irq["width"] if "width" in irq else 1
-
-
-class Parameter:
- """Holds IP Parameter information for populating DIF code templates.
-
- Attributes:
- name (str): Parameter name.
- description (str): Parameter description.
- default (int): Default parameter value.
-
- """
- def __init__(self, parameter: OrderedDict) -> None:
- self.name = parameter["name"]
- self.description = parameter["desc"]
- self.default = None
- if "default" in parameter:
- self.default = parameter["default"]
-
-
-class Ip:
- """Holds all IP metadata mined from an IP's name and HJSON file.
-
- Attributes:
- name_snake (str): IP short name in lower snake case.
- name_upper (str): IP short name in upper snake case.
- name_camel (str): IP short name in camel case.
- name_long_lower (str): IP full name in lower case.
- name_long_upper (str): IP full name with first letter capitalized.
- alerts (List[alerts]): List of Alert objs constructed from HSJON data.
- irqs (List[Irq]): List of Irq objs constructed from HJSON data.
-
- """
- def __init__(self, name_snake: str, name_long_lower: str) -> None:
- """Mines metadata to populate this Ip object.
-
- Args:
- name_snake: IP short name in lower snake case (e.g., pwrmgr).
- name_long_lower: IP full name in lower case (e.g., power manager).
- """
- # Generate various IP name formats.
- self.name_snake = name_snake
- self.name_upper = self.name_snake.upper()
- self.name_camel = "".join(
- [word.capitalize() for word in self.name_snake.split("_")])
- self.name_long_lower = name_long_lower
- # We just want to set the first character to title case. In particular,
- # .capitalize() does not do the right thing, since it would convert
- # UART to Uart.
- self.name_long_upper = (self.name_long_lower[0].upper() +
- self.name_long_lower[1:])
- # Load HJSON data.
- if self.name_snake in IPS_USING_IPGEN:
- ip_dir = REPO_TOP / "hw/top_earlgrey/ip_autogen/{0}".format(
- self.name_snake)
- else:
- ip_dir = REPO_TOP / "hw/ip/{0}".format(self.name_snake)
- _hjson_file = ip_dir / "data" / "{0}.hjson".format(self.name_snake)
- with _hjson_file.open("r") as f:
- _hjson_str = f.read()
- self._hjson_data = hjson.loads(_hjson_str)
- # Load Alert data from HJSON.
- self.alerts = self._load_alerts()
- # Load IRQ data from HJSON.
- self.irqs = self._load_irqs()
- # Load Parameters from HJSON
- self.parameters = self._load_parameters()
-
- def _load_alerts(self):
- assert (self._hjson_data and
- "ERROR: must load IP HJSON before loading Alerts")
- alerts = []
- if "alert_list" in self._hjson_data:
- for alert in self._hjson_data["alert_list"]:
- alerts.append(Alert(alert))
- return alerts
-
- def _load_irqs(self):
- assert (self._hjson_data and
- "ERROR: must load IP HJSON before loading IRQs")
- irqs = []
- if "interrupt_list" in self._hjson_data:
- for irq in self._hjson_data["interrupt_list"]:
- irqs.append(Irq(irq))
- return irqs
-
- def _load_parameters(self):
- assert (self._hjson_data and
- "ERROR: must load IP HJSON before loarding Parameters")
- parameters = {}
- if "param_list" in self._hjson_data:
- for parameter in self._hjson_data["param_list"]:
- p = Parameter(parameter)
- parameters[p.name] = p
- return parameters
-
def main():
dif_dir = REPO_TOP / "sw/device/lib/dif"
@@ -244,13 +106,13 @@
for ip in ips:
if "header" in args.only:
- header_template_file = (REPO_TOP /
- "util/make_new_dif/dif_template.h.tpl")
+ header_template_file = (
+ REPO_TOP / "util/make_new_dif/templates/dif_template.h.tpl")
header_out_file = dif_dir / "dif_{}.h".format(ip.name_snake)
if header_out_file.is_file():
raise FileExistsError(
- """DIF header already exists for the IP. To overwrite, """
- """delete existing header and try again.""")
+ "DIF header already exists for the IP. To overwrite, "
+ "delete existing header and try again.")
header_template = Template(header_template_file.read_text())
header_out_file.write_text(header_template.render(ip=ip))
print("DIF header successfully written to {}.".format(
@@ -261,7 +123,8 @@
for filetype in [".h", ".c", "_unittest.cc"]:
# Build input/output file names.
template_file = (
- REPO_TOP / f"util/make_new_dif/dif_autogen{filetype}.tpl")
+ REPO_TOP /
+ f"util/make_new_dif/templates/dif_autogen{filetype}.tpl")
out_file = (autogen_dif_dir /
f"dif_{ip.name_snake}_autogen{filetype}")
@@ -291,8 +154,8 @@
checklist_out_file = dif_dir / "dif_{}.md".format(ip.name_snake)
if checklist_out_file.is_file():
raise FileExistsError(
- """DIF checklist already exists for the IP. To """
- """overwrite, delete existing checklist and try again.""")
+ "DIF checklist already exists for the IP. To "
+ "overwrite, delete existing checklist and try again.")
markdown_template = Template(checklist_template_file.read_text())
checklist_out_file.write_text(markdown_template.render(ip=ip))
print("DIF Checklist successfully written to {}.".format(