123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976 |
- import argparse
- from collections import defaultdict
- import logging
- import os
- import pathlib
- import pickle
- import re
- import sys
- sys.path.append(os.path.join(os.path.dirname(__file__), 'python-devicetree',
- 'src'))
- from devicetree import edtlib
- FOREACH_PROP_ELEM_TYPES = set(['string', 'array', 'uint8-array', 'string-array',
- 'phandles', 'phandle-array'])
- class LogFormatter(logging.Formatter):
- '''A log formatter that prints the level name in lower case,
- for compatibility with earlier versions of edtlib.'''
- def __init__(self):
- super().__init__(fmt='%(levelnamelower)s: %(message)s')
- def format(self, record):
- record.levelnamelower = record.levelname.lower()
- return super().format(record)
- def main():
- global header_file
- global flash_area_num
- args = parse_args()
- setup_edtlib_logging()
- vendor_prefixes = {}
- for prefixes_file in args.vendor_prefixes:
- vendor_prefixes.update(edtlib.load_vendor_prefixes_txt(prefixes_file))
- try:
- edt = edtlib.EDT(args.dts, args.bindings_dirs,
-
- warn_reg_unit_address_mismatch=
- "-Wno-simple_bus_reg" not in args.dtc_flags,
- default_prop_types=True,
- infer_binding_for_paths=["/zephyr,user"],
- werror=args.edtlib_Werror,
- vendor_prefixes=vendor_prefixes)
- except edtlib.EDTError as e:
- sys.exit(f"devicetree error: {e}")
- flash_area_num = 0
-
- with open(args.dts_out, "w", encoding="utf-8") as f:
- print(edt.dts_source, file=f)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- for compat, nodes in edt.compat2nodes.items():
- edt.compat2nodes[compat] = sorted(
- nodes, key=lambda node: 0 if node.status == "okay" else 1)
-
- with open(args.header_out, "w", encoding="utf-8") as header_file:
- write_top_comment(edt)
-
-
- for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
- node.z_path_id = node_z_path_id(node)
- for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
- write_node_comment(node)
- out_comment("Node's full path:")
- out_dt_define(f"{node.z_path_id}_PATH", f'"{escape(node.path)}"')
- out_comment("Node's name with unit-address:")
- out_dt_define(f"{node.z_path_id}_FULL_NAME",
- f'"{escape(node.name)}"')
- if node.parent is not None:
- out_comment(f"Node parent ({node.parent.path}) identifier:")
- out_dt_define(f"{node.z_path_id}_PARENT",
- f"DT_{node.parent.z_path_id}")
- write_child_functions(node)
- write_child_functions_status_okay(node)
- write_dep_info(node)
- write_idents_and_existence(node)
- write_bus(node)
- write_special_props(node)
- write_vanilla_props(node)
- write_chosen(edt)
- write_global_compat_info(edt)
- write_device_extern_header(args.device_header_out, edt)
- if args.edt_pickle_out:
- write_pickled_edt(edt, args.edt_pickle_out)
- def write_device_extern_header(device_header_out, edt):
-
- with open(device_header_out, "w", encoding="utf-8") as dev_header_file:
- print("#ifndef DEVICE_EXTERN_GEN_H", file=dev_header_file)
- print("#define DEVICE_EXTERN_GEN_H", file=dev_header_file)
- print("", file=dev_header_file)
- print("#ifdef __cplusplus", file=dev_header_file)
- print('extern "C" {', file=dev_header_file)
- print("#endif", file=dev_header_file)
- print("", file=dev_header_file)
- for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
- print(f"extern const struct device DEVICE_DT_NAME_GET(DT_{node.z_path_id}); /* dts_ord_{node.dep_ordinal} */",
- file=dev_header_file)
- print("", file=dev_header_file)
- print("#ifdef __cplusplus", file=dev_header_file)
- print("}", file=dev_header_file)
- print("#endif", file=dev_header_file)
- print("", file=dev_header_file)
- print("#endif /* DEVICE_EXTERN_GEN_H */", file=dev_header_file)
- def setup_edtlib_logging():
-
-
-
- handler = logging.StreamHandler(sys.stderr)
- handler.setFormatter(LogFormatter())
- logger = logging.getLogger('edtlib')
- logger.setLevel(logging.WARNING)
- logger.addHandler(handler)
- def node_z_path_id(node):
-
-
-
-
-
-
-
-
-
- components = ["N"]
- if node.parent is not None:
- components.extend(f"S_{str2ident(component)}" for component in
- node.path.split("/")[1:])
- return "_".join(components)
- def parse_args():
-
- parser = argparse.ArgumentParser()
- parser.add_argument("--dts", required=True, help="DTS file")
- parser.add_argument("--dtc-flags",
- help="'dtc' devicetree compiler flags, some of which "
- "might be respected here")
- parser.add_argument("--bindings-dirs", nargs='+', required=True,
- help="directory with bindings in YAML format, "
- "we allow multiple")
- parser.add_argument("--header-out", required=True,
- help="path to write header to")
- parser.add_argument("--dts-out", required=True,
- help="path to write merged DTS source code to (e.g. "
- "as a debugging aid)")
- parser.add_argument("--device-header-out", required=True,
- help="path to write device struct extern header to")
- parser.add_argument("--edt-pickle-out",
- help="path to write pickled edtlib.EDT object to")
- parser.add_argument("--vendor-prefixes", action='append', default=[],
- help="vendor-prefixes.txt path; used for validation; "
- "may be given multiple times")
- parser.add_argument("--edtlib-Werror", action="store_true",
- help="if set, edtlib-specific warnings become errors. "
- "(this does not apply to warnings shared "
- "with dtc.)")
- return parser.parse_args()
- def write_top_comment(edt):
-
-
- s = f"""\
- Generated by gen_defines.py
- DTS input file:
- {edt.dts_path}
- Directories with bindings:
- {", ".join(map(relativize, edt.bindings_dirs))}
- Node dependency ordering (ordinal and path):
- """
- for scc in edt.scc_order:
- if len(scc) > 1:
- err("cycle in devicetree involving "
- + ", ".join(node.path for node in scc))
- s += f" {scc[0].dep_ordinal:<3} {scc[0].path}\n"
- s += """
- Definitions derived from these nodes in dependency order are next,
- followed by /chosen nodes.
- """
- out_comment(s, blank_before=False)
- def write_node_comment(node):
-
- s = f"""\
- Devicetree node: {node.path}
- Node identifier: DT_{node.z_path_id}
- """
- if node.matching_compat:
- if node.binding_path:
- s += f"""
- Binding (compatible = {node.matching_compat}):
- {relativize(node.binding_path)}
- """
- else:
- s += f"""
- Binding (compatible = {node.matching_compat}):
- No yaml (bindings inferred from properties)
- """
- if node.description:
-
-
-
-
-
-
-
-
-
-
-
- s += ("\n(Descriptions have moved to the Devicetree Bindings Index\n"
- "in the documentation.)\n")
- out_comment(s)
- def relativize(path):
-
-
-
- zbase = os.getenv("ZEPHYR_BASE")
- if zbase is None:
- return path
- try:
- return str("$ZEPHYR_BASE" / pathlib.Path(path).relative_to(zbase))
- except ValueError:
-
- return path
- def write_idents_and_existence(node):
-
-
-
- idents = [f"N_ALIAS_{str2ident(alias)}" for alias in node.aliases]
-
- for compat in node.compats:
- instance_no = node.edt.compat2nodes[compat].index(node)
- idents.append(f"N_INST_{instance_no}_{str2ident(compat)}")
-
- idents.extend(f"N_NODELABEL_{str2ident(label)}" for label in node.labels)
- out_comment("Existence and alternate IDs:")
- out_dt_define(node.z_path_id + "_EXISTS", 1)
-
- if idents:
- maxlen = max(len("DT_" + ident) for ident in idents)
- for ident in idents:
- out_dt_define(ident, "DT_" + node.z_path_id, width=maxlen)
- def write_bus(node):
-
- bus = node.bus_node
- if not bus:
- return
- if not bus.label:
- err(f"missing 'label' property on bus node {bus!r}")
- out_comment(f"Bus info (controller: '{bus.path}', type: '{node.on_bus}')")
- out_dt_define(f"{node.z_path_id}_BUS_{str2ident(node.on_bus)}", 1)
- out_dt_define(f"{node.z_path_id}_BUS", f"DT_{bus.z_path_id}")
- def write_special_props(node):
-
-
-
-
- out_comment("Macros for properties that are special in the specification:")
- write_regs(node)
- write_interrupts(node)
- write_compatibles(node)
- write_status(node)
-
-
- write_pinctrls(node)
- write_fixed_partitions(node)
- def write_regs(node):
-
-
-
- idx_vals = []
- name_vals = []
- path_id = node.z_path_id
- if node.regs is not None:
- idx_vals.append((f"{path_id}_REG_NUM", len(node.regs)))
- for i, reg in enumerate(node.regs):
- idx_vals.append((f"{path_id}_REG_IDX_{i}_EXISTS", 1))
- if reg.addr is not None:
- idx_macro = f"{path_id}_REG_IDX_{i}_VAL_ADDRESS"
- idx_vals.append((idx_macro,
- f"{reg.addr} /* {hex(reg.addr)} */"))
- if reg.name:
- name_macro = f"{path_id}_REG_NAME_{reg.name}_VAL_ADDRESS"
- name_vals.append((name_macro, f"DT_{idx_macro}"))
- if reg.size is not None:
- idx_macro = f"{path_id}_REG_IDX_{i}_VAL_SIZE"
- idx_vals.append((idx_macro,
- f"{reg.size} /* {hex(reg.size)} */"))
- if reg.name:
- name_macro = f"{path_id}_REG_NAME_{reg.name}_VAL_SIZE"
- name_vals.append((name_macro, f"DT_{idx_macro}"))
- for macro, val in idx_vals:
- out_dt_define(macro, val)
- for macro, val in name_vals:
- out_dt_define(macro, val)
- def write_interrupts(node):
-
-
-
-
-
-
- def map_arm_gic_irq_type(irq, irq_num):
-
- if "type" not in irq.data:
- err(f"Expected binding for {irq.controller!r} to have 'type' in "
- "interrupt-cells")
- irq_type = irq.data["type"]
- if irq_type == 0:
- return irq_num + 32
- if irq_type == 1:
- return irq_num + 16
- err(f"Invalid interrupt type specified for {irq!r}")
- def encode_zephyr_multi_level_irq(irq, irq_num):
-
-
- irq_ctrl = irq.controller
-
- while irq_ctrl.interrupts:
- irq_num = (irq_num + 1) << 8
- if "irq" not in irq_ctrl.interrupts[0].data:
- err(f"Expected binding for {irq_ctrl!r} to have 'irq' in "
- "interrupt-cells")
- irq_num |= irq_ctrl.interrupts[0].data["irq"]
- irq_ctrl = irq_ctrl.interrupts[0].controller
- return irq_num
- idx_vals = []
- name_vals = []
- path_id = node.z_path_id
- if node.interrupts is not None:
- idx_vals.append((f"{path_id}_IRQ_NUM", len(node.interrupts)))
- for i, irq in enumerate(node.interrupts):
- for cell_name, cell_value in irq.data.items():
- name = str2ident(cell_name)
- if cell_name == "irq":
- if "arm,gic" in irq.controller.compats:
- cell_value = map_arm_gic_irq_type(irq, cell_value)
- cell_value = encode_zephyr_multi_level_irq(irq, cell_value)
- idx_vals.append((f"{path_id}_IRQ_IDX_{i}_EXISTS", 1))
- idx_macro = f"{path_id}_IRQ_IDX_{i}_VAL_{name}"
- idx_vals.append((idx_macro, cell_value))
- idx_vals.append((idx_macro + "_EXISTS", 1))
- if irq.name:
- name_macro = \
- f"{path_id}_IRQ_NAME_{str2ident(irq.name)}_VAL_{name}"
- name_vals.append((name_macro, f"DT_{idx_macro}"))
- name_vals.append((name_macro + "_EXISTS", 1))
- for macro, val in idx_vals:
- out_dt_define(macro, val)
- for macro, val in name_vals:
- out_dt_define(macro, val)
- def write_compatibles(node):
-
-
-
- for compat in node.compats:
- out_dt_define(
- f"{node.z_path_id}_COMPAT_MATCHES_{str2ident(compat)}", 1)
- def write_child_functions(node):
-
-
- out_dt_define(f"{node.z_path_id}_FOREACH_CHILD(fn)",
- " ".join(f"fn(DT_{child.z_path_id})" for child in
- node.children.values()))
- out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_VARGS(fn, ...)",
- " ".join(f"fn(DT_{child.z_path_id}, __VA_ARGS__)" for child in
- node.children.values()))
- def write_child_functions_status_okay(node):
-
-
- functions = ''
- functions_args = ''
- for child in node.children.values():
- if child.status == "okay":
- functions = functions + f"fn(DT_{child.z_path_id}) "
- functions_args = functions_args + f"fn(DT_{child.z_path_id}, " \
- "__VA_ARGS__) "
- out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY(fn)", functions)
- out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY_VARGS(fn, ...)",
- functions_args)
- def write_status(node):
- out_dt_define(f"{node.z_path_id}_STATUS_{str2ident(node.status)}", 1)
- def write_pinctrls(node):
-
- out_comment("Pin control (pinctrl-<i>, pinctrl-names) properties:")
- out_dt_define(f"{node.z_path_id}_PINCTRL_NUM", len(node.pinctrls))
- if not node.pinctrls:
- return
- for pc_idx, pinctrl in enumerate(node.pinctrls):
- out_dt_define(f"{node.z_path_id}_PINCTRL_IDX_{pc_idx}_EXISTS", 1)
- if not pinctrl.name:
- continue
- name = pinctrl.name_as_token
-
-
-
- out_dt_define(f"{node.z_path_id}_PINCTRL_IDX_{pc_idx}_TOKEN", name)
- out_dt_define(f"{node.z_path_id}_PINCTRL_IDX_{pc_idx}_UPPER_TOKEN", name.upper())
- out_dt_define(f"{node.z_path_id}_PINCTRL_NAME_{name}_EXISTS", 1)
- out_dt_define(f"{node.z_path_id}_PINCTRL_NAME_{name}_IDX", pc_idx)
- for idx, ph in enumerate(pinctrl.conf_nodes):
- out_dt_define(f"{node.z_path_id}_PINCTRL_NAME_{name}_IDX_{idx}_PH",
- f"DT_{ph.z_path_id}")
- def write_fixed_partitions(node):
-
- if not (node.parent and "fixed-partitions" in node.parent.compats):
- return
- global flash_area_num
- out_comment("fixed-partitions identifier:")
- out_dt_define(f"{node.z_path_id}_PARTITION_ID", flash_area_num)
- flash_area_num += 1
- def write_vanilla_props(node):
-
-
-
-
-
-
-
-
-
- macro2val = {}
- for prop_name, prop in node.props.items():
- prop_id = str2ident(prop_name)
- macro = f"{node.z_path_id}_P_{prop_id}"
- val = prop2value(prop)
- if val is not None:
-
- macro2val[macro] = val
- if prop.spec.type == 'string':
- macro2val[macro + "_STRING_TOKEN"] = prop.val_as_token
- macro2val[macro + "_STRING_UPPER_TOKEN"] = prop.val_as_token.upper()
- if prop.enum_index is not None:
-
- macro2val[macro + "_ENUM_IDX"] = prop.enum_index
- spec = prop.spec
- if spec.enum_tokenizable:
- as_token = prop.val_as_token
-
- macro2val[macro + "_ENUM_TOKEN"] = as_token
- if spec.enum_upper_tokenizable:
-
- macro2val[macro + "_ENUM_UPPER_TOKEN"] = as_token.upper()
- if "phandle" in prop.type:
- macro2val.update(phandle_macros(prop, macro))
- elif "array" in prop.type:
-
-
- for i, subval in enumerate(prop.val):
- if isinstance(subval, str):
- macro2val[macro + f"_IDX_{i}"] = quote_str(subval)
- else:
- macro2val[macro + f"_IDX_{i}"] = subval
- macro2val[macro + f"_IDX_{i}_EXISTS"] = 1
- if prop.type in FOREACH_PROP_ELEM_TYPES:
-
- macro2val[f"{macro}_FOREACH_PROP_ELEM(fn)"] = \
- ' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
- for i in range(len(prop.val)))
- macro2val[f"{macro}_FOREACH_PROP_ELEM_VARGS(fn, ...)"] = \
- ' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {prop_id}, {i},'
- ' __VA_ARGS__)'
- for i in range(len(prop.val)))
- plen = prop_len(prop)
- if plen is not None:
-
- macro2val[macro + "_LEN"] = plen
- macro2val[f"{macro}_EXISTS"] = 1
- if macro2val:
- out_comment("Generic property macros:")
- for macro, val in macro2val.items():
- out_dt_define(macro, val)
- else:
- out_comment("(No generic property macros)")
- def write_dep_info(node):
-
- def fmt_dep_list(dep_list):
- if dep_list:
-
- sorted_list = sorted(dep_list, key=lambda node: node.dep_ordinal)
- return "\\\n\t" + \
- " \\\n\t".join(f"{n.dep_ordinal}, /* {n.path} */"
- for n in sorted_list)
- else:
- return "/* nothing */"
- out_comment("Node's dependency ordinal:")
- out_dt_define(f"{node.z_path_id}_ORD", node.dep_ordinal)
- out_comment("Ordinals for what this node depends on directly:")
- out_dt_define(f"{node.z_path_id}_REQUIRES_ORDS",
- fmt_dep_list(node.depends_on))
- out_comment("Ordinals for what depends directly on this node:")
- out_dt_define(f"{node.z_path_id}_SUPPORTS_ORDS",
- fmt_dep_list(node.required_by))
- def prop2value(prop):
-
-
-
- if prop.type == "string":
- return quote_str(prop.val)
- if prop.type == "int":
- return prop.val
- if prop.type == "boolean":
- return 1 if prop.val else 0
- if prop.type in ["array", "uint8-array"]:
- return list2init(f"{val} /* {hex(val)} */" for val in prop.val)
- if prop.type == "string-array":
- return list2init(quote_str(val) for val in prop.val)
-
- return None
- def prop_len(prop):
-
-
-
-
-
-
-
-
-
-
-
-
-
- if prop.type == "phandle":
- return 1
- if (prop.type in ["array", "uint8-array", "string-array",
- "phandles", "phandle-array"] and
- prop.name not in ["reg", "interrupts"]):
- return len(prop.val)
- return None
- def phandle_macros(prop, macro):
-
-
-
-
-
-
-
-
-
-
-
- ret = {}
- if prop.type == "phandle":
-
- ret[f"{macro}"] = f"DT_{prop.val.z_path_id}"
- ret[f"{macro}_IDX_0"] = f"DT_{prop.val.z_path_id}"
- ret[f"{macro}_IDX_0_PH"] = f"DT_{prop.val.z_path_id}"
- ret[f"{macro}_IDX_0_EXISTS"] = 1
- elif prop.type == "phandles":
- for i, node in enumerate(prop.val):
- ret[f"{macro}_IDX_{i}"] = f"DT_{node.z_path_id}"
- ret[f"{macro}_IDX_{i}_PH"] = f"DT_{node.z_path_id}"
- ret[f"{macro}_IDX_{i}_EXISTS"] = 1
- elif prop.type == "phandle-array":
- for i, entry in enumerate(prop.val):
- if entry is None:
-
-
-
- ret[f"{macro}_IDX_{i}_EXISTS"] = 0
- continue
- ret.update(controller_and_data_macros(entry, i, macro))
- return ret
- def controller_and_data_macros(entry, i, macro):
-
-
-
-
-
- ret = {}
- data = entry.data
-
- ret[f"{macro}_IDX_{i}_EXISTS"] = 1
-
- ret[f"{macro}_IDX_{i}_PH"] = f"DT_{entry.controller.z_path_id}"
-
- for cell, val in data.items():
- ret[f"{macro}_IDX_{i}_VAL_{str2ident(cell)}"] = val
- ret[f"{macro}_IDX_{i}_VAL_{str2ident(cell)}_EXISTS"] = 1
- if not entry.name:
- return ret
- name = str2ident(entry.name)
-
- ret[f"{macro}_IDX_{i}_EXISTS"] = 1
-
- ret[f"{macro}_IDX_{i}_NAME"] = quote_str(entry.name)
-
- ret[f"{macro}_NAME_{name}_PH"] = f"DT_{entry.controller.z_path_id}"
-
- ret[f"{macro}_NAME_{name}_EXISTS"] = 1
-
- for cell, val in data.items():
- cell_ident = str2ident(cell)
- ret[f"{macro}_NAME_{name}_VAL_{cell_ident}"] = \
- f"DT_{macro}_IDX_{i}_VAL_{cell_ident}"
- ret[f"{macro}_NAME_{name}_VAL_{cell_ident}_EXISTS"] = 1
- return ret
- def write_chosen(edt):
-
- out_comment("Chosen nodes\n")
- chosen = {}
- for name, node in edt.chosen_nodes.items():
- chosen[f"DT_CHOSEN_{str2ident(name)}"] = f"DT_{node.z_path_id}"
- chosen[f"DT_CHOSEN_{str2ident(name)}_EXISTS"] = 1
- max_len = max(map(len, chosen), default=0)
- for macro, value in chosen.items():
- out_define(macro, value, width=max_len)
- def write_global_compat_info(edt):
-
-
- n_okay_macros = {}
- for_each_macros = {}
- compat2buses = defaultdict(list)
- for compat, okay_nodes in edt.compat2okay.items():
- for node in okay_nodes:
- bus = node.on_bus
- if bus is not None and bus not in compat2buses[compat]:
- compat2buses[compat].append(bus)
- ident = str2ident(compat)
- n_okay_macros[f"DT_N_INST_{ident}_NUM_OKAY"] = len(okay_nodes)
-
-
- for_each_macros[f"DT_FOREACH_OKAY_{ident}(fn)"] = \
- " ".join(f"fn(DT_{node.z_path_id})"
- for node in okay_nodes)
- for_each_macros[f"DT_FOREACH_OKAY_VARGS_{ident}(fn, ...)"] = \
- " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)"
- for node in okay_nodes)
-
-
-
-
-
- for_each_macros[f"DT_FOREACH_OKAY_INST_{ident}(fn)"] = \
- " ".join(f"fn({edt.compat2nodes[compat].index(node)})"
- for node in okay_nodes)
- for_each_macros[f"DT_FOREACH_OKAY_INST_VARGS_{ident}(fn, ...)"] = \
- " ".join(f"fn({edt.compat2nodes[compat].index(node)}, __VA_ARGS__)"
- for node in okay_nodes)
- for compat, nodes in edt.compat2nodes.items():
- for node in nodes:
- if compat == "fixed-partitions":
- for child in node.children.values():
- if "label" in child.props:
- label = child.props["label"].val
- macro = f"COMPAT_{str2ident(compat)}_LABEL_{str2ident(label)}"
- val = f"DT_{child.z_path_id}"
- out_dt_define(macro, val)
- out_dt_define(macro + "_EXISTS", 1)
- out_comment('Macros for compatibles with status "okay" nodes\n')
- for compat, okay_nodes in edt.compat2okay.items():
- if okay_nodes:
- out_define(f"DT_COMPAT_HAS_OKAY_{str2ident(compat)}", 1)
- out_comment('Macros for status "okay" instances of each compatible\n')
- for macro, value in n_okay_macros.items():
- out_define(macro, value)
- for macro, value in for_each_macros.items():
- out_define(macro, value)
- out_comment('Bus information for status "okay" nodes of each compatible\n')
- for compat, buses in compat2buses.items():
- for bus in buses:
- out_define(
- f"DT_COMPAT_{str2ident(compat)}_BUS_{str2ident(bus)}", 1)
- def str2ident(s):
-
- return re.sub('[-,.@/+]', '_', s.lower())
- def list2init(l):
-
- return "{" + ", ".join(l) + "}"
- def out_dt_define(macro, val, width=None, deprecation_msg=None):
-
-
-
-
-
-
-
-
-
-
-
- ret = "DT_" + macro
- out_define(ret, val, width=width, deprecation_msg=deprecation_msg)
- return ret
- def out_define(macro, val, width=None, deprecation_msg=None):
-
-
-
- warn = fr' __WARN("{deprecation_msg}")' if deprecation_msg else ""
- if width:
- s = f"#define {macro.ljust(width)}{warn} {val}"
- else:
- s = f"#define {macro}{warn} {val}"
- print(s, file=header_file)
- def out_comment(s, blank_before=True):
-
-
-
- if blank_before:
- print(file=header_file)
- if "\n" in s:
-
-
-
-
-
-
-
-
- res = ["/*"]
- for line in s.splitlines():
-
-
- res.append(" *" if not line.strip() else " * " + line)
- res.append(" */")
- print("\n".join(res), file=header_file)
- else:
-
-
-
- print("/* " + s + " */", file=header_file)
- def escape(s):
-
-
- return s.replace("\\", "\\\\").replace('"', '\\"')
- def quote_str(s):
-
-
- return f'"{escape(s)}"'
- def write_pickled_edt(edt, out_file):
-
- with open(out_file, 'wb') as f:
-
-
-
-
-
-
-
-
- pickle.dump(edt, f, protocol=4)
- def err(s):
- raise Exception(s)
- if __name__ == "__main__":
- main()
|