dts: gen_defines.py: Convert to use f-strings

Use f-strings instead of .format() to makes all the macro identifier and
multiline comment building easier to read.

f-strings were added in Python 3.6, which is required by Zephyr now.

Convert some

    ... + "_" + ...

string building to f-strings as well.

f-strings are a bit faster too (because they avoid format()/str()
lookups), though it's not likely to be noticeable here.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
Ulf Magnusson 2020-01-24 05:15:33 +01:00 committed by Anas Nashif
commit 08484d0ac4

View file

@ -35,7 +35,7 @@ def main():
try: try:
edt = edtlib.EDT(args.dts, args.bindings_dirs) edt = edtlib.EDT(args.dts, args.bindings_dirs)
except edtlib.EDTError as e: except edtlib.EDTError as e:
sys.exit("devicetree error: " + str(e)) sys.exit(f"devicetree error: {e}")
conf_file = open(args.conf_out, "w", encoding="utf-8") conf_file = open(args.conf_out, "w", encoding="utf-8")
header_file = open(args.header_out, "w", encoding="utf-8") header_file = open(args.header_out, "w", encoding="utf-8")
@ -65,7 +65,7 @@ def main():
out_comment("Active compatibles (mentioned in DTS + binding found)") out_comment("Active compatibles (mentioned in DTS + binding found)")
for compat in sorted(active_compats): for compat in sorted(active_compats):
#define DT_COMPAT_<COMPAT> 1 #define DT_COMPAT_<COMPAT> 1
out("COMPAT_{}".format(str2ident(compat)), 1) out(f"COMPAT_{str2ident(compat)}", 1)
# Derived from /chosen # Derived from /chosen
write_addr_size(edt, "zephyr,ccm", "CCM") write_addr_size(edt, "zephyr,ccm", "CCM")
@ -99,23 +99,23 @@ def write_top_comment(edt):
# Writes an overview comment with misc. info at the top of the header and # Writes an overview comment with misc. info at the top of the header and
# configuration file # configuration file
s = """\ s = f"""\
Generated by gen_defines.py Generated by gen_defines.py
DTS input file: DTS input file:
{} {edt.dts_path}
Directories with bindings: Directories with bindings:
{} {", ".join(map(relativize, edt.bindings_dirs))}
Nodes in dependency order (ordinal and path): Nodes in dependency order (ordinal and path):
""".format(edt.dts_path, ", ".join(map(relativize, edt.bindings_dirs))) """
for scc in edt.scc_order(): for scc in edt.scc_order():
if len(scc) > 1: if len(scc) > 1:
err("cycle in devicetree involving " err("cycle in devicetree involving "
+ ", ".join(node.path for node in scc)) + ", ".join(node.path for node in scc))
s += " {0.dep_ordinal:<3} {0.path}\n".format(scc[0]) s += f" {scc[0].dep_ordinal:<3} {scc[0].path}\n"
out_comment(s, blank_before=False) out_comment(s, blank_before=False)
@ -123,26 +123,25 @@ Nodes in dependency order (ordinal and path):
def write_node_comment(node): def write_node_comment(node):
# Writes a comment describing 'node' to the header and configuration file # Writes a comment describing 'node' to the header and configuration file
s = """\ s = f"""\
Devicetree node: Devicetree node:
{} {node.path}
Binding (compatible = {}): Binding (compatible = {node.matching_compat}):
{} {relativize(node.binding_path)}
Dependency Ordinal: {} Dependency Ordinal: {node.dep_ordinal}
""".format(node.path, node.matching_compat, relativize(node.binding_path), """
node.dep_ordinal)
if node.depends_on: if node.depends_on:
s += "\nRequires:\n" s += "\nRequires:\n"
for dep in node.depends_on: for dep in node.depends_on:
s += " {:<3} {}\n".format(dep.dep_ordinal, dep.path) s += f" {dep.dep_ordinal:<3} {dep.path}\n"
if node.required_by: if node.required_by:
s += "\nSupports:\n" s += "\nSupports:\n"
for req in node.required_by: for req in node.required_by:
s += " {:<3} {}\n".format(req.dep_ordinal, req.path) s += f" {req.dep_ordinal:<3} {req.path}\n"
# Indent description by two spaces # Indent description by two spaces
s += "\nDescription:\n" + \ s += "\nDescription:\n" + \
@ -174,13 +173,13 @@ def write_regs(node):
# Drop '_0' from the identifier if there's a single register, for # Drop '_0' from the identifier if there's a single register, for
# backwards compatibility # backwards compatibility
if len(reg.node.regs) > 1: if len(reg.node.regs) > 1:
ident = "{}_{}".format(base_ident, reg.node.regs.index(reg)) ident = f"{base_ident}_{reg.node.regs.index(reg)}"
else: else:
ident = base_ident ident = base_ident
out_node(node, ident, val, out_node(node, ident, val,
# Name alias from 'reg-names = ...' # Name alias from 'reg-names = ...'
str2ident(reg.name) + "_" + base_ident if reg.name else None) f"{str2ident(reg.name)}_{base_ident}" if reg.name else None)
for reg in node.regs: for reg in node.regs:
write_reg(reg, "BASE_ADDRESS", hex(reg.addr)) write_reg(reg, "BASE_ADDRESS", hex(reg.addr))
@ -209,14 +208,14 @@ def write_props(node):
out_node(node, ident, prop.val) out_node(node, ident, prop.val)
elif prop.type == "array": elif prop.type == "array":
for i, val in enumerate(prop.val): for i, val in enumerate(prop.val):
out_node(node, "{}_{}".format(ident, i), val) out_node(node, f"{ident}_{i}", val)
out_node_init(node, ident, prop.val) out_node_init(node, ident, prop.val)
elif prop.type == "string-array": elif prop.type == "string-array":
for i, val in enumerate(prop.val): for i, val in enumerate(prop.val):
out_node_s(node, "{}_{}".format(ident, i), val) out_node_s(node, f"{ident}_{i}", val)
elif prop.type == "uint8-array": elif prop.type == "uint8-array":
out_node_init(node, ident, out_node_init(node, ident,
["0x{:02x}".format(b) for b in prop.val]) [f"0x{b:02x}" for b in prop.val])
else: # prop.type == "phandle-array" else: # prop.type == "phandle-array"
write_phandle_val_list(prop) write_phandle_val_list(prop)
@ -260,14 +259,14 @@ def write_bus(node):
return return
if node.bus_node.label is None: if node.bus_node.label is None:
err("missing 'label' property on bus node {!r}".format(node.bus_node)) err(f"missing 'label' property on bus node {node.bus_node!r}")
# #define DT_<DEV-IDENT>_BUS_NAME <BUS-LABEL> # #define DT_<DEV-IDENT>_BUS_NAME <BUS-LABEL>
out_node_s(node, "BUS_NAME", str2ident(node.bus_node.label)) out_node_s(node, "BUS_NAME", str2ident(node.bus_node.label))
for compat in node.compats: for compat in node.compats:
# #define DT_<COMPAT>_BUS_<BUS-TYPE> 1 # #define DT_<COMPAT>_BUS_<BUS-TYPE> 1
out("{}_BUS_{}".format(str2ident(compat), str2ident(node.on_bus)), 1) out(f"{str2ident(compat)}_BUS_{str2ident(node.on_bus)}", 1)
def write_existence_flags(node): def write_existence_flags(node):
@ -278,8 +277,7 @@ def write_existence_flags(node):
# These are flags for which devices exist. # These are flags for which devices exist.
for compat in node.compats: for compat in node.compats:
out("INST_{}_{}".format(node.instance_no[compat], out(f"INST_{node.instance_no[compat]}_{str2ident(compat)}", 1)
str2ident(compat)), 1)
def node_ident(node): def node_ident(node):
@ -294,15 +292,15 @@ def node_ident(node):
ident += "{}_{:X}_".format( ident += "{}_{:X}_".format(
str2ident(node.bus_node.matching_compat), node.bus_node.unit_addr) str2ident(node.bus_node.matching_compat), node.bus_node.unit_addr)
ident += "{}_".format(str2ident(node.matching_compat)) ident += f"{str2ident(node.matching_compat)}_"
if node.unit_addr is not None: if node.unit_addr is not None:
ident += "{:X}".format(node.unit_addr) ident += f"{node.unit_addr:X}"
elif node.parent.unit_addr is not None: elif node.parent.unit_addr is not None:
ident += "{:X}_{}".format(node.parent.unit_addr, str2ident(node.name)) ident += f"{node.parent.unit_addr:X}_{str2ident(node.name)}"
else: else:
# This is a bit of a hack # This is a bit of a hack
ident += "{}".format(str2ident(node.name)) ident += str2ident(node.name)
return ident return ident
@ -324,9 +322,9 @@ def node_path_aliases(node):
aliases = [] aliases = []
for alias in node.aliases: for alias in node.aliases:
aliases.append("ALIAS_{}".format(str2ident(alias))) aliases.append(f"ALIAS_{str2ident(alias)}")
# TODO: See if we can remove or deprecate this form # TODO: See if we can remove or deprecate this form
aliases.append("{}_{}".format(compat_s, str2ident(alias))) aliases.append(f"{compat_s}_{str2ident(alias)}")
return aliases return aliases
@ -339,7 +337,7 @@ def node_instance_aliases(node):
# This is a list since a node can have multiple 'compatible' strings, each # This is a list since a node can have multiple 'compatible' strings, each
# with their own instance number. # with their own instance number.
return ["INST_{}_{}".format(node.instance_no[compat], str2ident(compat)) return [f"INST_{node.instance_no[compat]}_{str2ident(compat)}"
for compat in node.compats] for compat in node.compats]
@ -352,12 +350,12 @@ def write_addr_size(edt, prop_name, prefix):
return return
if not node.regs: if not node.regs:
err("missing 'reg' property in node pointed at by /chosen/{} ({!r})" err("missing 'reg' property in node pointed at by "
.format(prop_name, node)) f"/chosen/{prop_name} ({node!r})")
out_comment("/chosen/{} ({})".format(prop_name, node.path)) out_comment(f"/chosen/{prop_name} ({node.path})")
out("{}_BASE_ADDRESS".format(prefix), hex(node.regs[0].addr)) out(f"{prefix}_BASE_ADDRESS", hex(node.regs[0].addr))
out("{}_SIZE".format(prefix), node.regs[0].size//1024) out(f"{prefix}_SIZE", node.regs[0].size//1024)
def write_flash(edt): def write_flash(edt):
@ -383,8 +381,7 @@ def write_flash_node(edt):
node = edt.chosen_node("zephyr,flash") node = edt.chosen_node("zephyr,flash")
out_comment("/chosen/zephyr,flash ({})" out_comment(f"/chosen/zephyr,flash ({node.path if node else 'missing'})")
.format(node.path if node else "missing"))
if not node: if not node:
# No flash node. Write dummy values. # No flash node. Write dummy values.
@ -393,8 +390,8 @@ def write_flash_node(edt):
return return
if len(node.regs) != 1: if len(node.regs) != 1:
err("expected zephyr,flash to have a single register, has {}" err("expected zephyr,flash to have a single register, has "
.format(len(node.regs))) f"{len(node.regs)}")
if node.on_bus == "spi" and len(node.bus_node.regs) == 2: if node.on_bus == "spi" and len(node.bus_node.regs) == 2:
reg = node.bus_node.regs[1] # QSPI flash reg = node.bus_node.regs[1] # QSPI flash
@ -417,8 +414,8 @@ def write_code_partition(edt):
node = edt.chosen_node("zephyr,code-partition") node = edt.chosen_node("zephyr,code-partition")
out_comment("/chosen/zephyr,code-partition ({})" out_comment("/chosen/zephyr,code-partition "
.format(node.path if node else "missing")) f"({node.path if node else 'missing'})")
if not node: if not node:
# No code partition. Write dummy values. # No code partition. Write dummy values.
@ -427,7 +424,7 @@ def write_code_partition(edt):
return return
if not node.regs: if not node.regs:
err("missing 'regs' property on {!r}".format(node)) err(f"missing 'regs' property on {node!r}")
out("CODE_PARTITION_OFFSET", node.regs[0].addr) out("CODE_PARTITION_OFFSET", node.regs[0].addr)
out("CODE_PARTITION_SIZE", node.regs[0].size) out("CODE_PARTITION_SIZE", node.regs[0].size)
@ -437,36 +434,35 @@ def write_flash_partition(partition_node, index):
out_comment("Flash partition at " + partition_node.path) out_comment("Flash partition at " + partition_node.path)
if partition_node.label is None: if partition_node.label is None:
err("missing 'label' property on {!r}".format(partition_node)) err(f"missing 'label' property on {partition_node!r}")
# Generate label-based identifiers # Generate label-based identifiers
write_flash_partition_prefix( write_flash_partition_prefix(
"FLASH_AREA_" + str2ident(partition_node.label), partition_node, index) "FLASH_AREA_" + str2ident(partition_node.label), partition_node, index)
# Generate index-based identifiers # Generate index-based identifiers
write_flash_partition_prefix( write_flash_partition_prefix(f"FLASH_AREA_{index}", partition_node, index)
"FLASH_AREA_{}".format(index), partition_node, index)
def write_flash_partition_prefix(prefix, partition_node, index): def write_flash_partition_prefix(prefix, partition_node, index):
# write_flash_partition() helper. Generates identifiers starting with # write_flash_partition() helper. Generates identifiers starting with
# 'prefix'. # 'prefix'.
out("{}_ID".format(prefix), index) out(f"{prefix}_ID", index)
out("{}_READ_ONLY".format(prefix), 1 if partition_node.read_only else 0) out(f"{prefix}_READ_ONLY", 1 if partition_node.read_only else 0)
for i, reg in enumerate(partition_node.regs): for i, reg in enumerate(partition_node.regs):
# Also add aliases that point to the first sector (TODO: get rid of the # Also add aliases that point to the first sector (TODO: get rid of the
# aliases?) # aliases?)
out("{}_OFFSET_{}".format(prefix, i), reg.addr, out(f"{prefix}_OFFSET_{i}", reg.addr,
aliases=["{}_OFFSET".format(prefix)] if i == 0 else []) aliases=[f"{prefix}_OFFSET"] if i == 0 else [])
out("{}_SIZE_{}".format(prefix, i), reg.size, out(f"{prefix}_SIZE_{i}", reg.size,
aliases=["{}_SIZE".format(prefix)] if i == 0 else []) aliases=[f"{prefix}_SIZE"] if i == 0 else [])
controller = partition_node.flash_controller controller = partition_node.flash_controller
if controller.label is not None: if controller.label is not None:
out_s("{}_DEV".format(prefix), controller.label) out_s(f"{prefix}_DEV", controller.label)
def write_irqs(node): def write_irqs(node):
@ -477,24 +473,23 @@ def write_irqs(node):
if not irq.name: if not irq.name:
return None return None
alias = "IRQ_{}".format(str2ident(irq.name)) alias = f"IRQ_{str2ident(irq.name)}"
if cell_name != "irq": if cell_name != "irq":
alias += "_" + str2ident(cell_name) alias += f"_{str2ident(cell_name)}"
return alias return alias
def map_arm_gic_irq_type(irq, irq_num): def map_arm_gic_irq_type(irq, irq_num):
# Maps ARM GIC IRQ (type)+(index) combo to linear IRQ number # Maps ARM GIC IRQ (type)+(index) combo to linear IRQ number
if "type" not in irq.data: if "type" not in irq.data:
err("Expected binding for {!r} to have 'type' in interrupt-cells" err(f"Expected binding for {irq.controller!r} to have 'type' in "
.format(irq.controller)) "interrupt-cells")
irq_type = irq.data["type"] irq_type = irq.data["type"]
if irq_type == 0: # GIC_SPI if irq_type == 0: # GIC_SPI
return irq_num + 32 return irq_num + 32
if irq_type == 1: # GIC_PPI if irq_type == 1: # GIC_PPI
return irq_num + 16 return irq_num + 16
err("Invalid interrupt type specified for {!r}" err(f"Invalid interrupt type specified for {irq!r}")
.format(irq))
def encode_zephyr_multi_level_irq(irq, irq_num): def encode_zephyr_multi_level_irq(irq, irq_num):
# See doc/reference/kernel/other/interrupts.rst for details # See doc/reference/kernel/other/interrupts.rst for details
@ -505,21 +500,21 @@ def write_irqs(node):
while irq_ctrl.interrupts: while irq_ctrl.interrupts:
irq_num = (irq_num + 1) << 8 irq_num = (irq_num + 1) << 8
if "irq" not in irq_ctrl.interrupts[0].data: if "irq" not in irq_ctrl.interrupts[0].data:
err("Expected binding for {!r} to have 'irq' in interrupt-cells" err(f"Expected binding for {irq_ctrl!r} to have 'irq' in "
.format(irq_ctrl)) "interrupt-cells")
irq_num |= irq_ctrl.interrupts[0].data["irq"] irq_num |= irq_ctrl.interrupts[0].data["irq"]
irq_ctrl = irq_ctrl.interrupts[0].controller irq_ctrl = irq_ctrl.interrupts[0].controller
return irq_num return irq_num
for irq_i, irq in enumerate(node.interrupts): for irq_i, irq in enumerate(node.interrupts):
for cell_name, cell_value in irq.data.items(): for cell_name, cell_value in irq.data.items():
ident = "IRQ_{}".format(irq_i) ident = f"IRQ_{irq_i}"
if cell_name == "irq": if cell_name == "irq":
if "arm,gic" in irq.controller.compats: if "arm,gic" in irq.controller.compats:
cell_value = map_arm_gic_irq_type(irq, cell_value) cell_value = map_arm_gic_irq_type(irq, cell_value)
cell_value = encode_zephyr_multi_level_irq(irq, cell_value) cell_value = encode_zephyr_multi_level_irq(irq, cell_value)
else: else:
ident += "_" + str2ident(cell_name) ident += f"_{str2ident(cell_name)}"
out_node(node, ident, cell_value, out_node(node, ident, cell_value,
name_alias=irq_name_alias(irq, cell_name)) name_alias=irq_name_alias(irq, cell_name))
@ -586,37 +581,37 @@ def write_phandle_val_list_entry(node, entry, i, ident):
if entry.controller.label is not None: if entry.controller.label is not None:
ctrl_ident = ident + "_CONTROLLER" # e.g. PWMS_CONTROLLER ctrl_ident = ident + "_CONTROLLER" # e.g. PWMS_CONTROLLER
if entry.name: if entry.name:
name_alias = str2ident(entry.name) + "_" + ctrl_ident name_alias = f"{str2ident(entry.name)}_{ctrl_ident}"
else: else:
name_alias = None name_alias = None
# Ugly backwards compatibility hack. Only add the index if there's # Ugly backwards compatibility hack. Only add the index if there's
# more than one entry. # more than one entry.
if i is not None: if i is not None:
ctrl_ident += "_{}".format(i) ctrl_ident += f"_{i}"
initializer_vals.append(quote_str(entry.controller.label)) initializer_vals.append(quote_str(entry.controller.label))
out_node_s(node, ctrl_ident, entry.controller.label, name_alias) out_node_s(node, ctrl_ident, entry.controller.label, name_alias)
for cell, val in entry.data.items(): for cell, val in entry.data.items():
cell_ident = ident + "_" + str2ident(cell) # e.g. PWMS_CHANNEL cell_ident = f"{ident}_{str2ident(cell)}" # e.g. PWMS_CHANNEL
if entry.name: if entry.name:
# From e.g. 'pwm-names = ...' # From e.g. 'pwm-names = ...'
name_alias = str2ident(entry.name) + "_" + cell_ident name_alias = f"{str2ident(entry.name)}_{cell_ident}"
else: else:
name_alias = None name_alias = None
# Backwards compatibility (see above) # Backwards compatibility (see above)
if i is not None: if i is not None:
cell_ident += "_{}".format(i) cell_ident += f"_{i}"
out_node(node, cell_ident, val, name_alias) out_node(node, cell_ident, val, name_alias)
initializer_vals += entry.data.values() initializer_vals += entry.data.values()
initializer_ident = ident initializer_ident = ident
if entry.name: if entry.name:
name_alias = initializer_ident + "_" + str2ident(entry.name) name_alias = f"{initializer_ident}_{str2ident(entry.name)}"
else: else:
name_alias = None name_alias = None
if i is not None: if i is not None:
initializer_ident += "_{}".format(i) initializer_ident += f"_{i}"
return out_node_init(node, initializer_ident, initializer_vals, name_alias) return out_node_init(node, initializer_ident, initializer_vals, name_alias)
@ -644,15 +639,15 @@ def write_clocks(node):
else: else:
clk_name_alias = None clk_name_alias = None
out_node(node, "CLOCK_{}_{}".format(str2ident(name), clock_i), val, out_node(node, f"CLOCK_{str2ident(name)}_{clock_i}", val,
name_alias=clk_name_alias) name_alias=clk_name_alias)
if "fixed-clock" not in controller.compats: if "fixed-clock" not in controller.compats:
continue continue
if "clock-frequency" not in controller.props: if "clock-frequency" not in controller.props:
err("{!r} is a 'fixed-clock' but lacks a 'clock-frequency' " err(f"{controller!r} is a 'fixed-clock' but lacks a "
"property".format(controller)) "'clock-frequency' property")
out_node(node, "CLOCKS_CLOCK_FREQUENCY", out_node(node, "CLOCKS_CLOCK_FREQUENCY",
controller.props["clock-frequency"].val) controller.props["clock-frequency"].val)
@ -692,12 +687,12 @@ def out_node(node, ident, val, name_alias=None):
node_prefix = node_ident(node) node_prefix = node_ident(node)
aliases = [alias + "_" + ident for alias in node_aliases(node)] aliases = [f"{alias}_{ident}" for alias in node_aliases(node)]
if name_alias is not None: if name_alias is not None:
aliases.append(node_prefix + "_" + name_alias) aliases.append(f"{node_prefix}_{name_alias}")
aliases += [alias + "_" + name_alias for alias in node_aliases(node)] aliases += [f"{alias}_{name_alias}" for alias in node_aliases(node)]
return out(node_prefix + "_" + ident, val, aliases) return out(f"{node_prefix}_{ident}", val, aliases)
def out_node_s(node, ident, s, name_alias=None): def out_node_s(node, ident, s, name_alias=None):
@ -737,8 +732,8 @@ def out(ident, val, aliases=()):
# #
# Returns the generated macro name for 'ident'. # Returns the generated macro name for 'ident'.
print("#define DT_{:40} {}".format(ident, val), file=header_file) print(f"#define DT_{ident:40} {val}", file=header_file)
primary_ident = "DT_{}".format(ident) primary_ident = f"DT_{ident}"
# Exclude things that aren't single token values from .conf. At # Exclude things that aren't single token values from .conf. At
# the moment the only such items are unquoted string # the moment the only such items are unquoted string
@ -746,16 +741,15 @@ def out(ident, val, aliases=()):
# brace. # brace.
output_to_conf = not (isinstance(val, str) and val.startswith("{")) output_to_conf = not (isinstance(val, str) and val.startswith("{"))
if output_to_conf: if output_to_conf:
print("{}={}".format(primary_ident, val), file=conf_file) print(f"{primary_ident}={val}", file=conf_file)
for alias in aliases: for alias in aliases:
if alias != ident: if alias != ident:
print("#define DT_{:40} DT_{}".format(alias, ident), print(f"#define DT_{alias:40} DT_{ident}", file=header_file)
file=header_file)
if output_to_conf: if output_to_conf:
# For the configuration file, the value is just repeated for all # For the configuration file, the value is just repeated for all
# the aliases # the aliases
print("DT_{}={}".format(alias, val), file=conf_file) print(f"DT_{alias}={val}", file=conf_file)
return primary_ident return primary_ident
@ -805,7 +799,7 @@ def quote_str(s):
# Puts quotes around 's' and escapes any double quotes and # Puts quotes around 's' and escapes any double quotes and
# backslashes within it # backslashes within it
return '"{}"'.format(escape(s)) return f'"{escape(s)}"'
def err(s): def err(s):