blob: 5c05fc8f9cba2189c1e5d528f3869412a4b8ccdc [file] [log] [blame]
Tim Hall79d07d22020-04-27 18:20:16 +01001# Copyright (C) 2020 Arm Limited or its affiliates. All rights reserved.
2#
3# SPDX-License-Identifier: Apache-2.0
4#
5# Licensed under the Apache License, Version 2.0 (the License); you may
6# not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an AS IS BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Tim Hall79d07d22020-04-27 18:20:16 +010016# Description:
17# Insert DMA operations into the graph for transfering weights.
Tim Hall79d07d22020-04-27 18:20:16 +010018from . import rewrite_graph
Diego Russoe8a10452020-04-21 17:39:10 +010019from .operation import NpuBlockType
20from .operation import Operation
21from .tensor import MemArea
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020022from .tensor import MemType
Diego Russoe8a10452020-04-21 17:39:10 +010023from .tensor import TensorPurpose
Tim Hall79d07d22020-04-27 18:20:16 +010024
Tim Hallc30f4952020-06-15 20:47:35 +010025
Charles Xu78792222020-05-13 10:15:26 +020026binary_elementwise_op = set(("AddAct", "MulAct", "SubAct", "Maximum", "Minimum"))
Tim Hall79d07d22020-04-27 18:20:16 +010027
Tim Hallc30f4952020-06-15 20:47:35 +010028
Tim Hall79d07d22020-04-27 18:20:16 +010029def insert_dma_cmd(op, arch):
30 if op.type == "DMA":
Diego Russoea6111a2020-04-14 18:41:58 +010031 return op # Already rewritten
Tim Hall79d07d22020-04-27 18:20:16 +010032 for idx, tens in enumerate(op.inputs):
33
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020034 if tens.mem_type not in (MemType.Scratch, MemType.Scratch_fast):
35 # Tensor is in permanent storage
36 # Only when permanent storage differs from fast storage, there is a point moving the data
37 if tens.mem_area in (MemArea.Dram, MemArea.OffChipFlash) and (
38 arch.permanent_storage_mem_area != arch.fast_storage_mem_area
Tim Hallc30f4952020-06-15 20:47:35 +010039 ):
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020040 if tens.purpose == TensorPurpose.Weights or (
41 tens.purpose == TensorPurpose.FeatureMap and op.type in binary_elementwise_op and tens.shape != []
42 ):
43 only_vector_product_consumers = True
44 for oper in tens.consumers():
45 if oper is None or oper.attrs.get("npu_block_type") != NpuBlockType.VectorProduct:
46 only_vector_product_consumers = False
47 break
Tim Hall79d07d22020-04-27 18:20:16 +010048
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020049 # Tensor products has no need for DMA, tensors are only read once and can be in flash.
50 # Other operations re-reads tensors, this is better done from SRAM.
51 if not only_vector_product_consumers:
52 # Insert a DMA command here, as well as a new tensor situated in SRAM of the same size.
53 new_tens = tens.clone_into_fast_storage(arch)
54 dma_cmd = Operation("DMA", tens.ops[0].name + "_dma")
55 dma_cmd.inputs = [tens]
56 dma_cmd.outputs = [new_tens]
57 dma_cmd.attrs["source"] = tens.mem_area
58 dma_cmd.attrs["destination"] = new_tens.mem_area
59 dma_cmd.run_on_npu = True
60 new_tens.ops = [dma_cmd]
61 op.inputs[idx] = new_tens
Tim Hall79d07d22020-04-27 18:20:16 +010062 return op
63
64
65def insert_dma_commands(nng, arch, verbose_graph=False):
66
67 for idx, sg in enumerate(nng.subgraphs):
68 nng.subgraphs[idx] = rewrite_graph.rewrite_graph_pre_order(sg, arch, [], [insert_dma_cmd])
69 if verbose_graph:
70 nng.print_graph()
71 return nng