scripts: gen_handles: output dependency graph
Output the final dependency graph as a `.dot` file, which when rendered by graphviz can be easier to comprehend than the text descriptions. This output is optional in that it will not be generated if `graphviz` is not installed. Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
parent
8d17e857a1
commit
29942475c5
|
@ -872,6 +872,7 @@ if(CONFIG_HAS_DTS)
|
|||
${PYTHON_EXECUTABLE}
|
||||
${ZEPHYR_BASE}/scripts/build/gen_handles.py
|
||||
--output-source dev_handles.c
|
||||
--output-graphviz dev_graph.dot
|
||||
--num-dynamic-devices ${number_of_dynamic_devices}
|
||||
--kernel $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}>
|
||||
--zephyr-base ${ZEPHYR_BASE}
|
||||
|
|
|
@ -254,3 +254,25 @@ class ZephyrElf:
|
|||
|
||||
# Link injected devices to each other
|
||||
self._link_injected(devices_by_ord)
|
||||
|
||||
def device_dependency_graph(self, title, comment):
|
||||
"""
|
||||
Construct a graphviz Digraph of the relationships between devices.
|
||||
"""
|
||||
import graphviz
|
||||
dot = graphviz.Digraph(title, comment=comment)
|
||||
# Split iteration so nodes and edges are grouped in source
|
||||
for dev in self.devices:
|
||||
if dev.ordinal == DeviceOrdinals.DEVICE_HANDLE_NULL:
|
||||
text = '{:s}\\nHandle: {:d}'.format(dev.sym.name, dev.handle)
|
||||
else:
|
||||
n = self.edt.dep_ord2node[dev.ordinal]
|
||||
label = n.labels[0] if n.labels else n.label
|
||||
text = '{:s}\\nOrdinal: {:d} | Handle: {:d}\\n{:s}'.format(
|
||||
label, dev.ordinal, dev.handle, n.path
|
||||
)
|
||||
dot.node(str(dev.ordinal), text)
|
||||
for dev in self.devices:
|
||||
for sup in dev.devs_supports:
|
||||
dot.edge(str(dev.ordinal), str(sup.ordinal))
|
||||
return dot
|
||||
|
|
|
@ -51,6 +51,8 @@ def parse_args():
|
|||
type=int, help="Input number of dynamic devices allowed")
|
||||
parser.add_argument("-o", "--output-source", required=True,
|
||||
help="Output source file")
|
||||
parser.add_argument("-g", "--output-graphviz",
|
||||
help="Output file for graphviz dependency graph")
|
||||
parser.add_argument("-z", "--zephyr-base",
|
||||
help="Path to current Zephyr base. If this argument \
|
||||
is not provided the environment will be checked for \
|
||||
|
@ -116,6 +118,15 @@ def main():
|
|||
|
||||
parsed_elf = ZephyrElf(args.kernel, edt, args.start_symbol)
|
||||
|
||||
if args.output_graphviz:
|
||||
# Try and output the dependency tree
|
||||
try:
|
||||
dot = parsed_elf.device_dependency_graph('Device dependency graph', args.kernel)
|
||||
with open(args.output_graphviz, 'w') as f:
|
||||
f.write(dot.source)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
with open(args.output_source, "w") as fp:
|
||||
fp.write('#include <zephyr/device.h>\n')
|
||||
fp.write('#include <zephyr/toolchain.h>\n')
|
||||
|
|
|
@ -26,3 +26,6 @@ grpcio-tools
|
|||
|
||||
# used by scripts/release/bug_bash.py for generating top ten bug squashers
|
||||
PyGithub
|
||||
|
||||
# used to generate devicetree dependency graphs
|
||||
graphviz
|
||||
|
|
Loading…
Reference in a new issue