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)))
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)}.")
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)))