|
3 | 3 | # This source code is licensed under the BSD-style license found in the |
4 | 4 | # LICENSE file in the root directory of this source tree. |
5 | 5 |
|
| 6 | +import operator |
6 | 7 | from abc import ABC, abstractmethod |
7 | 8 |
|
8 | 9 | import torch |
|
14 | 15 | from executorch.backends.nxp.backend.ir.converter.builder.aten_model_builder_director import ( |
15 | 16 | AtenModelBuilderDirector, |
16 | 17 | ) |
| 18 | + |
| 19 | +from executorch.backends.nxp.backend.ir.converter.tensor_utils import ( |
| 20 | + get_name_of_node_output, |
| 21 | +) |
17 | 22 | from executorch.backends.nxp.backend.ir.tflite_generator import tflite_model |
18 | 23 | from executorch.backends.nxp.backend.neutron_target_spec import NeutronTargetSpec |
19 | 24 | from executorch.exir.dialects._ops import ops as exir_ops |
@@ -231,25 +236,45 @@ def _create_tflite_op_with_io_tensors(self, node: Node) -> tflite_model.Operator |
231 | 236 | # Initialize node's inputs |
232 | 237 | t_operator.inputs = tflite_model.OperatorInputs() |
233 | 238 |
|
234 | | - input_nodes = [] |
235 | | - for arg in node.args: |
236 | | - match arg: |
237 | | - case Node(): |
238 | | - input_nodes.append(arg) |
239 | | - case list() if all(isinstance(node_, Node) for node_ in arg): |
240 | | - input_nodes.extend(arg) |
241 | | - |
242 | | - for ancestor_node in input_nodes: |
243 | | - assert self.context.tflite_builder.tensor_exists(ancestor_node.name) |
244 | | - t_operator.tmp_inputs.append( |
245 | | - self.context.tflite_builder.tensor_for_name(ancestor_node.name) |
246 | | - ) |
247 | | - |
248 | | - # Add node's output as a new tensor |
249 | | - assert self.context.tflite_builder.tensor_exists(node.name) |
250 | | - t_operator.outputs = tflite_model.OperatorOutputs() |
251 | | - t_operator.tmp_outputs.append( |
252 | | - self.context.tflite_builder.tensor_for_name(node.name) |
| 239 | + if node.target == operator.getitem: |
| 240 | + # Special case of a builtin function, which can extract a specific output tensor from the previous node. |
| 241 | + previous_node = node.args[0] |
| 242 | + output_index = node.args[1] |
| 243 | + input_name = get_name_of_node_output(previous_node, output_index) |
| 244 | + assert self.builder.tensor_exists(input_name) |
| 245 | + t_operator.tmp_inputs.append(self.builder.tensor_for_name(input_name)) |
| 246 | + |
| 247 | + else: |
| 248 | + # Regular operator. |
| 249 | + input_nodes = [] |
| 250 | + for arg in node.args: |
| 251 | + match arg: |
| 252 | + case Node(): |
| 253 | + input_nodes.append(arg) |
| 254 | + case list() if all(isinstance(node_, Node) for node_ in arg): |
| 255 | + input_nodes.extend(arg) |
| 256 | + |
| 257 | + for ancestor_node in input_nodes: |
| 258 | + assert self.builder.tensor_exists(ancestor_node.name) |
| 259 | + t_operator.tmp_inputs.append( |
| 260 | + self.builder.tensor_for_name(ancestor_node.name) |
| 261 | + ) |
| 262 | + |
| 263 | + # Add node's outputs as a new tensors |
| 264 | + num_outputs = ( |
| 265 | + len(node.meta["val"]) if isinstance(node.meta["val"], tuple) else 1 |
253 | 266 | ) |
| 267 | + if num_outputs == 1: |
| 268 | + # Single output node. |
| 269 | + assert self.builder.tensor_exists(node.name) |
| 270 | + t_operator.outputs = tflite_model.OperatorOutputs() |
| 271 | + t_operator.tmp_outputs.append(self.builder.tensor_for_name(node.name)) |
| 272 | + else: |
| 273 | + # The node has multiple outputs. |
| 274 | + t_operator.outputs = tflite_model.OperatorOutputs() |
| 275 | + for output_index in range(num_outputs): |
| 276 | + tensor_name = get_name_of_node_output(node, output_index) |
| 277 | + assert self.builder.tensor_exists(tensor_name) |
| 278 | + t_operator.tmp_outputs.append(self.builder.tensor_for_name(tensor_name)) |
254 | 279 |
|
255 | 280 | return t_operator |
0 commit comments