Ejemplo n.º 1
0
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)))
Ejemplo n.º 2
0
def gen_testutils(ips_with_difs: List[Ip]) -> None:
    """Generate testutils libraries that are rendered from Mako templates.

    Args:
        ips_with_difs: List of IP objects that have existing DIF libraries.

    Returns:
        None
    """
    # 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.")

    # Sort input so the templates get rendered in the same order every time.
    ips_with_difs.sort(key=lambda ip: ip.name_snake)

    # Define input/output directories.
    testutils_templates_dir = REPO_TOP / "util/autogen_testutils/templates"
    autogen_testutils_dir = REPO_TOP / "sw/device/lib/testing/autogen"

    # Create output directories if needed.
    autogen_testutils_dir.mkdir(exist_ok=True)

    # Render templates.
    for testutils_template_path in testutils_templates_dir.iterdir():
        if testutils_template_path.suffix == ".tpl":
            comment_syntax = "#" if testutils_template_path.stem.endswith(
                ".build") else "//"
            # Read in template, render it, and write it to the output file.
            testutils_template = Template(testutils_template_path.read_text())
            testutils = 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=comment_syntax)))

            # Format autogenerated file with clang-format.
            # Note: do not format meson build file.
            if testutils.suffix != ".build":
                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(f"testutils successfully written to {str(testutils)}.")
Ejemplo n.º 3
0
def main():
    dif_dir = REPO_TOP / "sw/device/lib/dif"
    autogen_dif_dir = dif_dir / "autogen"

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--mode",
        "-m",
        choices=["new", "regen"],
        default="new",
        required=True,
        help="mode to generate DIF code. Use 'new' if no DIF code exists."
        "Use 'rege' to regenerate all auto-generated DIFs for all IPs.")
    parser.add_argument("--topcfg", "-t", help="path of the top hjson file.")
    parser.add_argument("--ip-name-snake",
                        "-i",
                        help="the short name of the IP, in snake_case.")
    parser.add_argument("--ip-name-long",
                        "-l",
                        help="the documentation-friendly name of the IP.")
    parser.add_argument("--only",
                        choices=ALL_PARTS,
                        default=[],
                        action="append",
                        help="only create some files; defaults to all.")
    args = parser.parse_args()

    # Parse CMD line args.
    ips = []

    # hjson path
    topcfg_path = REPO_TOP / "hw/top_earlgrey/data/top_earlgrey.hjson"
    if args.topcfg:
        topcfg_path = args.topcfg

    try:
        with open(topcfg_path, 'r') as ftop:
            topcfg = hjson.load(ftop, use_decimal=True)
    except FileNotFoundError:
        print(f"hjson {topcfg_path} could not be found")
        sys.exit(1)

    templated_modules = lib.get_templated_modules(topcfg)
    ipgen_modules = lib.get_ipgen_modules(topcfg)
    print(f"modules {templated_modules} {ipgen_modules}")

    # Check for regeneration mode (used in CI check:
    # ci/scripts/check-generated.sh)
    if args.mode == "regen":
        if len(args.only) != 1 or args.only[0] != "autogen":
            raise RuntimeError(
                "can only regenerate DIF code that is auto-generated.")
        # Create list of IPs to re-generate DIF code for.
        for autogen_src_filename in glob.iglob(
                str(REPO_TOP / "sw/device/lib/dif/autogen/*.c")):
            # 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_src_filename).stem[4:-8]
            # NOTE: ip.name_long_* not needed for auto-generated files which
            # are the only files (re-)generated in regen mode.
            ips.append(
                Ip(ip_name_snake, "AUTOGEN", templated_modules, ipgen_modules))
    else:
        assert args.ip_name_snake and args.ip_name_long, \
            "ERROR: pass --ip-name-snake and --ip-name-long when --mode=new."
        ips.append(
            Ip(args.ip_name_snake, args.ip_name_long, templated_modules,
               ipgen_modules))

    # Default to generating all parts.
    if len(args.only) == 0:
        args.only += ALL_PARTS

    # Create output directories if needed.
    if len(args.only) > 0:
        dif_dir.mkdir(exist_ok=True)
        autogen_dif_dir.mkdir(exist_ok=True)

    for ip in ips:
        if "header" in args.only:
            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.")
            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(
                str(header_out_file)))

        if "autogen" in args.only:
            # Render all templates
            for filetype in [".h", ".c", "_unittest.cc"]:
                # Build input/output file names.
                template_file = (
                    REPO_TOP /
                    f"util/make_new_dif/templates/dif_autogen{filetype}.tpl")
                out_file = (autogen_dif_dir /
                            f"dif_{ip.name_snake}_autogen{filetype}")

                # Read in template.
                template = Template(template_file.read_text(),
                                    strict_undefined=True)

                # Generate output file.
                out_file.write_text(
                    template.render(
                        ip=ip,
                        autogen_banner=get_autogen_banner(
                            "util/make_new_dif.py --mode=regen --only=autogen",
                            "//")))

                # Format autogenerated file with clang-format.
                assert (shutil.which("clang-format")
                        and "ERROR: clang-format must be installed to format "
                        " autogenerated code to pass OpenTitan CI checks.")
                try:
                    subprocess.check_call(["clang-format", "-i", out_file])
                except subprocess.CalledProcessError:
                    logging.error(
                        f"failed to format {out_file} with clang-format.")
                    sys.exit(1)

                print("Autogenerated DIF successfully written to {}.".format(
                    out_file))

        if "checklist" in args.only:
            checklist_template_file = REPO_TOP / "doc/project/sw_checklist.md.tpl"
            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.")
            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(
                str(checklist_out_file)))