Skip to content

Commit

Permalink
[autogen,tests] Move the autogen tests functionality to a new binary
Browse files Browse the repository at this point in the history
This functionality was previously implemented in topgen. This commit
splits this functinality out of it so that it can be implemented by
calling another binary. This will enable running this from bazel
instead of generating it with topgen.

Signed-off-by: Amaury Pouly <[email protected]>
  • Loading branch information
pamaury committed Dec 4, 2024
1 parent 0bbd2f4 commit c66b5ba
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 21 deletions.
8 changes: 3 additions & 5 deletions sw/device/tests/autogen/alert_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 3 additions & 5 deletions sw/device/tests/autogen/plic_all_irqs_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <limits.h>

// This test should avoid otp_ctrl interrupts in rom_ext, since the rom
Expand Down
99 changes: 99 additions & 0 deletions util/autogen_tests.py
Original file line number Diff line number Diff line change
@@ -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 "<ip>.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()
Empty file added util/autogen_tests/__init__.py
Empty file.
56 changes: 56 additions & 0 deletions util/autogen_tests/gen.py
Original file line number Diff line number Diff line change
@@ -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)}.")
File renamed without changes.
5 changes: 1 addition & 4 deletions util/autogen_testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions util/topgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 !! -------------------//
Expand Down Expand Up @@ -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__":
Expand Down

0 comments on commit c66b5ba

Please sign in to comment.