blob: 6c5c8031421bd67f68be6e03521f4fbc422dee48 [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):
Jacob Bohlin68a04b12020-07-13 11:39:36 +020030 if op.type == "DMA" or not op.run_on_npu:
31 return op
32
Tim Hall79d07d22020-04-27 18:20:16 +010033 for idx, tens in enumerate(op.inputs):
34
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020035 if tens.mem_type not in (MemType.Scratch, MemType.Scratch_fast):
36 # Tensor is in permanent storage
37 # Only when permanent storage differs from fast storage, there is a point moving the data
Fredrik Svedberga0c36242020-06-03 15:43:31 +020038 if (
39 tens.mem_area in (MemArea.Dram, MemArea.OffChipFlash)
40 and arch.permanent_storage_mem_area != arch.fast_storage_mem_area
41 ) or tens.purpose == TensorPurpose.LUT:
42 if tens.purpose in (TensorPurpose.Weights, TensorPurpose.LUT) or (
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020043 tens.purpose == TensorPurpose.FeatureMap and op.type in binary_elementwise_op and tens.shape != []
44 ):
45 only_vector_product_consumers = True
46 for oper in tens.consumers():
47 if oper is None or oper.attrs.get("npu_block_type") != NpuBlockType.VectorProduct:
48 only_vector_product_consumers = False
49 break
Tim Hall79d07d22020-04-27 18:20:16 +010050
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020051 # Tensor products has no need for DMA, tensors are only read once and can be in flash.
52 # Other operations re-reads tensors, this is better done from SRAM.
Fredrik Svedberga0c36242020-06-03 15:43:31 +020053 # LUTs must be placed in the last 2 blocks of SHRAM.
54 if not only_vector_product_consumers or tens.purpose == TensorPurpose.LUT:
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020055 # Insert a DMA command here, as well as a new tensor situated in SRAM of the same size.
56 new_tens = tens.clone_into_fast_storage(arch)
57 dma_cmd = Operation("DMA", tens.ops[0].name + "_dma")
58 dma_cmd.inputs = [tens]
Michael McGeaghc5b549b2020-08-07 11:54:28 +010059 dma_cmd.set_output_tensor(new_tens)
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020060 dma_cmd.attrs["source"] = tens.mem_area
61 dma_cmd.attrs["destination"] = new_tens.mem_area
62 dma_cmd.run_on_npu = True
Fredrik Svedberga0c36242020-06-03 15:43:31 +020063 if tens.purpose == TensorPurpose.LUT:
64 # TODO: Add support more than one LUT at a time
65 # Reserve last 2 blocks for LUT
66 if arch.shram_reserved_unused_banks == 0:
67 arch.shram_reserved_unused_banks = 2
68 arch.shram_total_banks -= arch.shram_reserved_unused_banks
69 # Place the LUT in the last 2 blocks of SHRAM
70 new_tens.address = arch.shram_bank_size * arch.shram_total_banks
Patrik Gustavssoneca2e952020-05-27 09:15:11 +020071 op.inputs[idx] = new_tens
Tim Hall79d07d22020-04-27 18:20:16 +010072 return op
73
74
75def insert_dma_commands(nng, arch, verbose_graph=False):
76
77 for idx, sg in enumerate(nng.subgraphs):
78 nng.subgraphs[idx] = rewrite_graph.rewrite_graph_pre_order(sg, arch, [], [insert_dma_cmd])
79 if verbose_graph:
80 nng.print_graph()
81 return nng