Skip to content

Commit db813fa

Browse files
Arm backend: Move debug functions (#13223)
* Move debug functions to backends/arm/common/debug.py. * Rename functions from dbg to debug. Signed-off-by: Sebastian Larsson <[email protected]>
1 parent c671b92 commit db813fa

File tree

6 files changed

+97
-79
lines changed

6 files changed

+97
-79
lines changed

backends/arm/_passes/arm_pass_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import torch
1515
import torch.fx
16-
from executorch.backends.arm.tosa_utils import get_node_debug_info
16+
from executorch.backends.arm.common.debug import get_node_debug_info
1717
from executorch.exir import ExportedProgram
1818
from executorch.exir.dialects._ops import ops as exir_ops
1919

backends/arm/common/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2025 Arm Limited and/or its affiliates.
2+
#
3+
# This source code is licensed under the BSD-style license found in the
4+
# LICENSE file in the root directory of this source tree.

backends/arm/common/debug.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Copyright 2025 Arm Limited and/or its affiliates.
2+
#
3+
# This source code is licensed under the BSD-style license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
6+
import logging
7+
import os
8+
from typing import Optional
9+
10+
import serializer.tosa_serializer as ts # type: ignore
11+
import torch
12+
from executorch.exir.print_program import inspect_node
13+
14+
logger = logging.getLogger(__name__)
15+
16+
17+
def debug_node(node: torch.fx.Node, graph_module: torch.fx.GraphModule):
18+
# Debug output of node information
19+
logger.info(get_node_debug_info(node, graph_module))
20+
21+
22+
def get_node_debug_info(
23+
node: torch.fx.Node, graph_module: torch.fx.GraphModule | None = None
24+
) -> str:
25+
output = (
26+
f" {inspect_node(graph=graph_module.graph, node=node)}\n"
27+
if graph_module
28+
else ""
29+
"-- NODE DEBUG INFO --\n"
30+
f" Op is {node.op}\n"
31+
f" Name is {node.name}\n"
32+
f" Node target is {node.target}\n"
33+
f" Node args is {node.args}\n"
34+
f" Node kwargs is {node.kwargs}\n"
35+
f" Node users is {node.users}\n"
36+
" Node.meta = \n"
37+
)
38+
for k, v in node.meta.items():
39+
if k == "stack_trace":
40+
matches = v.split("\n")
41+
output += " 'stack_trace =\n"
42+
for m in matches:
43+
output += f" {m}\n"
44+
else:
45+
output += f" '{k}' = {v}\n"
46+
47+
if isinstance(v, list):
48+
for i in v:
49+
output += f" {i}\n"
50+
return output
51+
52+
53+
# Output TOSA flatbuffer and test harness file
54+
def debug_tosa_dump(tosa_graph: ts.TosaSerializer, path: str, suffix: str = ""):
55+
filename = f"output{suffix}.tosa"
56+
57+
logger.info(f"Emitting debug output to: {path=}, {suffix=}")
58+
59+
os.makedirs(path, exist_ok=True)
60+
61+
fb = tosa_graph.serialize()
62+
js = tosa_graph.writeJson(filename)
63+
64+
filepath_tosa_fb = os.path.join(path, filename)
65+
with open(filepath_tosa_fb, "wb") as f:
66+
f.write(fb)
67+
if not os.path.exists(filepath_tosa_fb):
68+
raise IOError("Failed to write TOSA flatbuffer")
69+
70+
filepath_desc_json = os.path.join(path, f"desc{suffix}.json")
71+
with open(filepath_desc_json, "w") as f:
72+
f.write(js)
73+
if not os.path.exists(filepath_desc_json):
74+
raise IOError("Failed to write TOSA JSON")
75+
76+
77+
def debug_fail(
78+
node,
79+
graph_module,
80+
tosa_graph: Optional[ts.TosaSerializer] = None,
81+
path: Optional[str] = None,
82+
):
83+
logger.warning("Internal error due to poorly handled node:")
84+
if tosa_graph is not None and path is not None:
85+
debug_tosa_dump(tosa_graph, path)
86+
logger.warning(f"Debug output captured in '{path}'.")
87+
debug_node(node, graph_module)

backends/arm/quantizer/quantization_annotator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
import torch
1212
import torch.fx
1313
import torch.nn.functional as F
14+
from executorch.backends.arm.common.debug import get_node_debug_info
1415
from executorch.backends.arm.quantizer import QuantizationConfig
15-
from executorch.backends.arm.tosa_utils import get_node_debug_info
1616
from torch._subclasses import FakeTensor
1717

1818
from torch.fx import Node

backends/arm/tosa_backend.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
from executorch.backends.arm._passes import (
2020
ArmPassManager,
2121
) # usort: skip
22+
from executorch.backends.arm.common.debug import debug_fail, debug_tosa_dump
2223
from executorch.backends.arm.process_node import (
2324
process_call_function,
2425
process_output,
2526
process_placeholder,
2627
)
27-
from executorch.backends.arm.tosa_utils import dbg_fail, dbg_tosa_dump
2828
from executorch.exir.backend.backend_details import BackendDetails, PreprocessResult
2929
from executorch.exir.backend.compile_spec_schema import CompileSpec
3030
from torch.export.exported_program import ExportedProgram
@@ -115,12 +115,12 @@ def preprocess( # noqa: C901
115115
# any checking of compatibility.
116116
raise RuntimeError(f"{node.name} is unsupported op {node.op}")
117117
except Exception:
118-
dbg_fail(node, graph_module, tosa_graph, artifact_path)
118+
debug_fail(node, graph_module, tosa_graph, artifact_path)
119119
raise
120120

121121
if artifact_path:
122122
tag = arm_get_first_delegation_tag(graph_module)
123-
dbg_tosa_dump(
123+
debug_tosa_dump(
124124
tosa_graph,
125125
artifact_path,
126126
suffix="{}".format(f"_{tag}" if tag else "") + (f"_{tosa_spec}"),

backends/arm/tosa_utils.py

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
# pyre-unsafe
77

88
import logging
9-
import os
10-
from typing import Any, Optional
9+
from typing import Any
1110

1211
import numpy as np
1312
import serializer.tosa_serializer as ts # type: ignore
@@ -20,85 +19,13 @@
2019

2120
from executorch.backends.arm.tosa_specification import TosaSpecification
2221
from executorch.exir.dialects._ops import ops as exir_ops
23-
from executorch.exir.print_program import inspect_node
2422

2523
from torch._subclasses.fake_tensor import FakeTensor
2624
from torch.fx import Node
2725

2826
logger = logging.getLogger(__name__)
2927

3028

31-
def dbg_node(node: torch.fx.Node, graph_module: torch.fx.GraphModule):
32-
# Debug output of node information
33-
logger.info(get_node_debug_info(node, graph_module))
34-
35-
36-
def get_node_debug_info(
37-
node: torch.fx.Node, graph_module: torch.fx.GraphModule | None = None
38-
) -> str:
39-
output = (
40-
f" {inspect_node(graph=graph_module.graph, node=node)}\n"
41-
if graph_module
42-
else ""
43-
"-- NODE DEBUG INFO --\n"
44-
f" Op is {node.op}\n"
45-
f" Name is {node.name}\n"
46-
f" Node target is {node.target}\n"
47-
f" Node args is {node.args}\n"
48-
f" Node kwargs is {node.kwargs}\n"
49-
f" Node users is {node.users}\n"
50-
" Node.meta = \n"
51-
)
52-
for k, v in node.meta.items():
53-
if k == "stack_trace":
54-
matches = v.split("\n")
55-
output += " 'stack_trace =\n"
56-
for m in matches:
57-
output += f" {m}\n"
58-
else:
59-
output += f" '{k}' = {v}\n"
60-
61-
if isinstance(v, list):
62-
for i in v:
63-
output += f" {i}\n"
64-
return output
65-
66-
67-
# Output TOSA flatbuffer and test harness file
68-
def dbg_tosa_dump(tosa_graph: ts.TosaSerializer, path: str, suffix: str = ""):
69-
filename = f"output{suffix}.tosa"
70-
71-
logger.info(f"Emitting debug output to: {path=}, {suffix=}")
72-
73-
os.makedirs(path, exist_ok=True)
74-
75-
fb = tosa_graph.serialize()
76-
js = tosa_graph.writeJson(filename)
77-
78-
filepath_tosa_fb = os.path.join(path, filename)
79-
with open(filepath_tosa_fb, "wb") as f:
80-
f.write(fb)
81-
assert os.path.exists(filepath_tosa_fb), "Failed to write TOSA flatbuffer"
82-
83-
filepath_desc_json = os.path.join(path, f"desc{suffix}.json")
84-
with open(filepath_desc_json, "w") as f:
85-
f.write(js)
86-
assert os.path.exists(filepath_desc_json), "Failed to write TOSA JSON"
87-
88-
89-
def dbg_fail(
90-
node,
91-
graph_module,
92-
tosa_graph: Optional[ts.TosaSerializer] = None,
93-
path: Optional[str] = None,
94-
):
95-
logger.warning("Internal error due to poorly handled node:")
96-
if tosa_graph is not None and path is not None:
97-
dbg_tosa_dump(tosa_graph, path)
98-
logger.warning(f"Debug output captured in '{path}'.")
99-
dbg_node(node, graph_module)
100-
101-
10229
def getNodeArgs(node: Node, tosa_spec: TosaSpecification) -> list[TosaArg]:
10330
try:
10431
return [TosaArg(arg, tosa_spec) for arg in node.args]

0 commit comments

Comments
 (0)