diff --git a/sw/device/tests/autogen/alert_test.c b/sw/device/tests/autogen/alert_test.c index 65e73472fdc526..e4b7f241c831ef 100644 --- a/sw/device/tests/autogen/alert_test.c +++ b/sw/device/tests/autogen/alert_test.c @@ -3,11 +3,9 @@ // SPDX-License-Identifier: Apache-2.0 // clang-format off -// -// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------// -// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND: -// util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson -// -o hw/top_earlgrey +// THIS FILE HAS BEEN GENERATED, DO NOT EDIT MANUALLY. COMMAND: +// util/autogen_tests.py + #include "sw/device/lib/arch/boot_stage.h" #include "sw/device/lib/base/mmio.h" #include "sw/device/lib/dif/dif_adc_ctrl.h" diff --git a/sw/device/tests/autogen/plic_all_irqs_test.c b/sw/device/tests/autogen/plic_all_irqs_test.c index 69e1c48b439e2a..7de053376b479e 100644 --- a/sw/device/tests/autogen/plic_all_irqs_test.c +++ b/sw/device/tests/autogen/plic_all_irqs_test.c @@ -2,11 +2,9 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // clang-format off -// -// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------// -// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND: -// util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson -// -o hw/top_earlgrey +// THIS FILE HAS BEEN GENERATED, DO NOT EDIT MANUALLY. COMMAND: +// util/autogen_tests.py + #include // This test should avoid otp_ctrl interrupts in rom_ext, since the rom diff --git a/util/autogen_tests.py b/util/autogen_tests.py new file mode 100755 index 00000000000000..41fb78bc3f069c --- /dev/null +++ b/util/autogen_tests.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +"""autogen_tests.py is a script for auto-generating a portion of the +`tests` from Mako templates. +""" + +import argparse +import logging +from pathlib import Path + +import topgen.lib as topgen_lib +from topgen.topcfg import CompleteTopCfg +from autogen_tests.gen import gen_tests +from reggen.ip_block import IpBlock + +# 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(): + # Parse command line args. + parser = argparse.ArgumentParser() + parser.add_argument( + "--topcfg_path", + "-t", + type=Path, + required=True, + help="path of the top hjson file.", + ) + parser.add_argument( + "--ipcfg", + "-i", + type=Path, + action="append", + default=[], + help="path of an IP hjson file (if not specified, will be guessed by the tool).", + ) + parser.add_argument( + "--outdir", + "-o", + type=Path, + required=True, + help="Output directory" + ) + args = parser.parse_args() + + logging.getLogger().setLevel(logging.INFO) + # Parse toplevel Hjson to get IPs that are generated with IPgen. + topcfg = CompleteTopCfg.from_path(args.topcfg_path) + ipgen_modules = topgen_lib.get_ipgen_modules(topcfg) + reggen_top_modules = topgen_lib.get_top_reggen_modules(topcfg) + + # Define autogen DIF directory. + outdir = args.outdir + + # First load provided IPs. + ip_hjson = {} + for ipcfg in args.ipcfg: + # Assume that the file name is ".hjson" + ipname = ipcfg.stem + ip_hjson[ipname] = ipcfg + + # 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. Note, the + # templates will take care of only generating ISR testutil functions for IPs + # that can actually generate interrupts. + name_to_block = {} + for ipname in list({m['type'] for m in topcfg['module']}): + # If the IP's hjson path was not provided on the command line, guess + # its location based on the type and top name. + if ipname in ip_hjson: + hjson_file = ip_hjson[ipname] + else: + # Load HJSON data. + if ipname in ipgen_modules: + data_dir = REPO_TOP / "hw/top_{}/ip_autogen/{}/data".format( + topcfg["name"], ipname) + elif ipname in reggen_top_modules: + data_dir = REPO_TOP / "hw/top_{}/ip/{}/data/".format( + topcfg["name"], ipname) + else: + data_dir = REPO_TOP / "hw/ip/{}/data".format(ipname) + hjson_file = data_dir / "{}.hjson".format(ipname) + logging.info("IP hjson path for {} was not provided, ".format(ipname) + + "guessing its location to be {}".format(hjson_file.relative_to(REPO_TOP))) + + # NOTE: ip.name_long_* not needed for auto-generated files which + # are the only files (re-)generated in batch mode. + name_to_block[ipname] = IpBlock.from_path(hjson_file, []) + + # Auto-generate testutils files. + gen_tests(outdir, topcfg, name_to_block) + + +if __name__ == "__main__": + main() diff --git a/util/autogen_tests/__init__.py b/util/autogen_tests/__init__.py new file mode 100644 index 00000000000000..f6564e9f1ab639 --- /dev/null +++ b/util/autogen_tests/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 diff --git a/util/autogen_tests/gen.py b/util/autogen_tests/gen.py new file mode 100644 index 00000000000000..8d2b9b3999b49f --- /dev/null +++ b/util/autogen_tests/gen.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +from pathlib import Path +from typing import Dict, List + +from topgen.c_test import TopGenCTest +from reggen.ip_block import IpBlock +from autogen_banner import get_autogen_banner +from mako.template import Template + +# 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.parent + + +def gen_tests(outdir: Path, completecfg: Dict[str, object], name_to_block: List[IpBlock]) -> None: + """Generate testutils libraries that are rendered from Mako templates. + + Args: + completecfg: Top-level description generated by topgen. + name_to_block: Mapping from IP names to IP block description. + + Returns: + None + """ + + # Define input/output directories. + tests_templates_dir = REPO_TOP / "util/autogen_tests/templates" + + # Create output directories if needed. + outdir.mkdir(exist_ok=True) + + tests = [] + c_helper = TopGenCTest(completecfg, name_to_block) + + # Render templates. + gencmd = get_autogen_banner("util/autogen_tests.py", comment='//') + for tests_template_path in tests_templates_dir.iterdir(): + if tests_template_path.suffix == ".tpl": + # Read in template, render it, and write it to the output file. + testutils_template = Template(tests_template_path.read_text()) + testutils = outdir / tests_template_path.stem + testutils.write_text( + testutils_template.render( + top=completecfg, + name_to_block=name_to_block, + helper=c_helper, + gencmd=gencmd + ) + ) + tests += [testutils] + + print(f"tests successfully written to {str(tests)}.") diff --git a/util/topgen/templates/alert_test.c.tpl b/util/autogen_tests/templates/alert_test.c.tpl similarity index 100% rename from util/topgen/templates/alert_test.c.tpl rename to util/autogen_tests/templates/alert_test.c.tpl diff --git a/util/topgen/templates/plic_all_irqs_test.c.tpl b/util/autogen_tests/templates/plic_all_irqs_test.c.tpl similarity index 100% rename from util/topgen/templates/plic_all_irqs_test.c.tpl rename to util/autogen_tests/templates/plic_all_irqs_test.c.tpl diff --git a/util/autogen_testutils.py b/util/autogen_testutils.py index 781f1bb19eb28f..b39b23eb4118c7 100755 --- a/util/autogen_testutils.py +++ b/util/autogen_testutils.py @@ -91,16 +91,13 @@ def main(): if ipname in ipgen_modules: data_dir = REPO_TOP / "hw/top_{}/ip_autogen/{}/data".format( topcfg["name"], ipname) - elif ipname in templated_modules: - data_dir = REPO_TOP / "hw/top_{}/ip/{}/data/autogen".format( - topcfg["name"], ipname) elif ipname in reggen_top_modules: data_dir = REPO_TOP / "hw/top_{}/ip/{}/data/".format( topcfg["name"], ipname) else: data_dir = REPO_TOP / "hw/ip/{}/data".format(ipname) hjson_file = data_dir / "{}.hjson".format(ipname) - logging.info("IP hjson path for {} was not provided".format(ipname) + + logging.info("IP hjson path for {} was not provided, ".format(ipname) + "guessing its location to be {}".format(hjson_file.relative_to(REPO_TOP))) # NOTE: ip.name_long_* not needed for auto-generated files which diff --git a/util/topgen.py b/util/topgen.py index 820164cbedadc5..541390070c6689 100755 --- a/util/topgen.py +++ b/util/topgen.py @@ -41,6 +41,8 @@ from topgen.top import Top from topgen.topcfg import CompleteTopCfg +import autogen_tests.gen as autogen_tests + # Common header for generated files warnhdr = """// // ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------// @@ -1294,13 +1296,11 @@ def render_template(template_path: str, rendered_path: Path, gen_top_docs(completecfg, c_helper, out_path) # Auto-generate tests in "sw/device/tests/autogen" area. - gencmd = warnhdr + GENCMD.format(top_name=top_name) - for fname in ["plic_all_irqs_test.c", "alert_test.c"]: - outfile = SRCTREE_TOP / "sw/device/tests/autogen" / fname - render_template(TOPGEN_TEMPLATE_PATH / ".." / ".." / "autogen_tests" / "templates" / f"{fname}.tpl", - outfile, - helper=c_helper, - gencmd=gencmd) + autogen_tests.gen_tests( + SRCTREE_TOP / "sw/device/tests/autogen", + completecfg, + name_to_block + ) if __name__ == "__main__":