[util] Add script and first template to autogen (some) testutils. This partially addresses #9038 by auto-generating a higher-level testutils library to service ISRs. Specifically this commit: 1. adds a Python script, `util/autogen_testutils.py`, that renders any testutils templates that live in util/autogen_testutils/, and 2. adds a `isr_testutils.h.tpl` header template. Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/util/autogen_testutils.py b/util/autogen_testutils.py new file mode 100755 index 0000000..5284a9d --- /dev/null +++ b/util/autogen_testutils.py
@@ -0,0 +1,89 @@ +#!/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 +"""autogen_testutils.py is a script for auto-generating a portion of the +`testutils` libraries from Mako templates. + +`testutils` libraries are testing libraries that sit a layer above the DIFs +that aid in writing chip-level tests by enabling test developers to re-use +code that calls a specific collection of DIFs. + +To render all testutil templates, run the script with: +$ util/autogen_testutils.py +""" + +import glob +import logging +import shutil +import subprocess +import sys +from pathlib import Path + +from mako.template import Template + +from autogen_banner import get_autogen_banner +from make_new_dif.ip import Ip + +# This file is $REPO_TOP/util/autogen_testutils.py, so it takes two parent() +# calls to get back to the top. +REPO_TOP = Path(__file__).resolve().parent.parent + + +def main(): + # Check clang-format is installed. + assert (shutil.which("clang-format") and + "ERROR: clang-format must be installed to format " + " autogenerated code to pass OpenTitan CI checks.") + + # Define input/output directories. + autogen_dif_directory = REPO_TOP / "sw/device/lib/dif/autogen" + testutils_templates_dir = REPO_TOP / "util/autogen_testutils" + autogen_testutils_dir = REPO_TOP / "sw/device/lib/testing/autogen" + + # Create list of IPs to generate shared testutils code for. This is all IPs + # that have a DIF library, that the testutils functions can use. + ips_with_difs = [] + for autogen_dif_filename in glob.iglob(str(autogen_dif_directory / "*.h")): + # NOTE: the line below takes as input a file path + # (/path/to/dif_uart_autogen.c) and returns the IP name in lower + # case snake mode (i.e., uart). + ip_name_snake = Path(autogen_dif_filename).stem[4:-8] + # NOTE: ip.name_long_* not needed for auto-generated files which + # are the only files (re-)generated in batch mode. + ips_with_difs.append(Ip(ip_name_snake, "AUTOGEN")) + ips_with_difs.sort(key=lambda ip: ip.name_snake) + + # Create output directories if needed. + autogen_testutils_dir.mkdir(exist_ok=True) + + # Auto-generate testutils files. + for suffix in [".h", ".c"]: + for testutils_template_path_str in glob.iglob( + str(testutils_templates_dir / f"*{suffix}.tpl")): + testutils_template_path = Path(testutils_template_path_str) + + # Read in template, render it, and write it to the output file. + testutils_template = Template(testutils_template_path.read_text()) + testutils = Path(autogen_testutils_dir / + testutils_template_path.stem) + testutils.write_text( + testutils_template.render(ips_with_difs=ips_with_difs, + autogen_banner=get_autogen_banner( + "util/autogen_testutils.py", + comment="//"))) + + # Format autogenerated file with clang-format. + try: + subprocess.check_call(["clang-format", "-i", testutils]) + except subprocess.CalledProcessError: + logging.error( + f"failed to format {testutils} with clang-format.") + sys.exit(1) + + print("testutils \"{}\" successfully written to {}.".format( + suffix, str(testutils))) + + +if __name__ == "__main__": + main()
diff --git a/util/autogen_testutils/isr_testutils.h.tpl b/util/autogen_testutils/isr_testutils.h.tpl new file mode 100644 index 0000000..9e54895 --- /dev/null +++ b/util/autogen_testutils/isr_testutils.h.tpl
@@ -0,0 +1,31 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +${autogen_banner} + +#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_AUTOGEN_ISR_TESTUTILS_H_ +#define OPENTITAN_SW_DEVICE_LIB_TESTING_AUTOGEN_ISR_TESTUTILS_H_ + +% for ip in ips_with_difs: + % if ip.irqs: + /* + * Services an ${ip.name_snake} IRQ at the IP that raised it, and verifies this + * matches the IRQ that was raised at the PLIC. + * + * @param ${ip.name_snake} A(n) ${ip.name_snake} DIF handle. + * @param plic_irq_id The triggered PLIC IRQ ID. + * @param plic_${ip.name_snake}_start_irq_id The PLIC IRQ ID where ${ip.name_snake} starts. + * @param expected_${ip.name_snake}_irq The expected ${ip.name_snake} IRQ. + * @param is_only_irq This is the only IRQ expected to be raised. + */ + void isr_testutils_${ip.name_snake}(dif_${ip.name_snake}_t *${ip.name_snake}, + dif_rv_plic_irq_id_t plic_irq_id, + dif_rv_plic_irq_id_t plic_${ip.name_snake}_start_irq_id, + dif_${ip.name_snake}_irq_id_t expected_${ip.name_snake}_irq, + bool is_only_irq); + + % endif +% endfor + +#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_AUTOGEN_ISR_TESTUTILS_H_