blob: 2e4412c8f6de083ac7d7cd652e75d69c631577c6 [file] [log] [blame]
Rickard Bolinbc6ee582022-11-04 08:24:29 +00001# SPDX-FileCopyrightText: Copyright 2020-2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
Tim Hall79d07d22020-04-27 18:20:16 +01002#
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.
Rickard Bolinbc6ee582022-11-04 08:24:29 +000016#
Tim Hall79d07d22020-04-27 18:20:16 +010017# Description:
18# Creates driver actions that are embedded in the custom operator payload.
Louis Verhaard52078302020-11-18 13:35:06 +010019import struct
Tim Hall79d07d22020-04-27 18:20:16 +010020from typing import List
Diego Russoea6111a2020-04-14 18:41:58 +010021
22import numpy as np
23
Louis Verhaard52078302020-11-18 13:35:06 +010024from .api import NpuAccelerator
25from .architecture_features import Accelerator
26from .architecture_features import ArchitectureFeatures
27from .architecture_features import create_default_arch
erik.andersson@arm.com1878dab2021-03-16 09:40:24 +010028from .errors import VelaError
Diego Russoe8a10452020-04-21 17:39:10 +010029from .ethos_u55_regs.ethos_u55_regs import ARCH_VER
30from .ethos_u55_regs.ethos_u55_regs import config_r
31from .ethos_u55_regs.ethos_u55_regs import id_r
Tim Hall79d07d22020-04-27 18:20:16 +010032
33
34class DACommands:
35 Reserved = 0x00
36 Config = 0x01
37 Config_PatchShift = 4
38 CmdStream = 0x02
39 ReadAPB = 0x03
40 ReadAPB_CountShift = 12
41 ReadAPB_IndexMask = (1 << ReadAPB_CountShift) - 1
42 DumpSHRAM = 0x04
43 NOP = 0x05
44
45
46def make_da_tag(id: int, reserved: int, param: int) -> int:
47 tag: int = id
48 tag |= reserved << 8
49 tag |= param << 16
50 return tag
51
52
53def emit_fourcc(data: List[int], fourcc: str):
Diego Russoea6111a2020-04-14 18:41:58 +010054 assert data is not None
55 assert fourcc is not None
Tim Hall79d07d22020-04-27 18:20:16 +010056 assert len(fourcc) == 4
57 value: int = 0
58 value = fourcc[0].encode()[0]
59 value |= fourcc[1].encode()[0] << 8
60 value |= fourcc[2].encode()[0] << 16
61 value |= fourcc[3].encode()[0] << 24
62 data.append(value)
63
64
65def build_id_word():
66 arch_major_rev, arch_minor_rev, arch_patch_rev = (int(x) for x in ARCH_VER.split("."))
67 n = id_r()
68 n.set_arch_major_rev(arch_major_rev)
69 n.set_arch_minor_rev(arch_minor_rev)
70 n.set_arch_patch_rev(arch_patch_rev)
71 return n.word
72
73
74def build_config_word(arch):
Tim Hallf7e810a2020-06-25 15:04:31 +010075 macs_cc = arch.ncores * arch.config.macs
Tim Hall79d07d22020-04-27 18:20:16 +010076 log2_macs_cc = int(np.log2(macs_cc) + 0.5)
Tim Hallf7e810a2020-06-25 15:04:31 +010077 shram_size = arch.ncores * int(arch.shram_size_bytes / 1024)
Tim Hall79d07d22020-04-27 18:20:16 +010078 n = config_r()
Jonny Svärdbdb1d6e2022-01-04 12:38:29 +010079 if arch.is_ethos_u65_system:
80 n.set_product(1)
81 else:
82 n.set_product(0) # U55
Tim Hall79d07d22020-04-27 18:20:16 +010083 n.set_shram_size(shram_size)
84 n.set_cmd_stream_version(0) # may be incremented in the future
85 n.set_macs_per_cc(log2_macs_cc)
86 return n.word
87
88
89def emit_config(data: List[int], rel: int, patch: int, arch):
Diego Russoea6111a2020-04-14 18:41:58 +010090 assert data is not None
Tim Hall79d07d22020-04-27 18:20:16 +010091 data.append(make_da_tag(DACommands.Config, 0, (patch << DACommands.Config_PatchShift) | rel))
92 data.append(build_config_word(arch))
93 data.append(build_id_word())
94
95
96def emit_cmd_stream_header(data: List[int], length: int):
Diego Russoea6111a2020-04-14 18:41:58 +010097 assert data is not None
Tim Hall79d07d22020-04-27 18:20:16 +010098 # Insert NOPs to align start of command stream to 16 bytes
99 num_nops = 4 - ((len(data) + 1) % 4)
100 for _ in range(num_nops):
101 data.append(make_da_tag(DACommands.NOP, 0, 0))
102
103 # Use the reserved 8 bit as the length high
104 length_high = (length & 0x00FF0000) >> 16
105 length_low = length & 0x0000FFFF
106 data.append(make_da_tag(DACommands.CmdStream, length_high, length_low))
107
108
109def emit_reg_read(data: List[int], reg_index: int, reg_count: int = 1):
Diego Russoea6111a2020-04-14 18:41:58 +0100110 assert data is not None
Tim Hall79d07d22020-04-27 18:20:16 +0100111 assert reg_index >= 0
112 assert reg_count >= 1
113 payload: int = (reg_index & DACommands.ReadAPB_IndexMask) | ((reg_count << DACommands.ReadAPB_CountShift) - 1)
114 data.append(make_da_tag(DACommands.ReadAPB, 0, payload))
115
116
117def emit_dump_shram(data: List[int]):
Diego Russoea6111a2020-04-14 18:41:58 +0100118 assert data is not None
Tim Hall79d07d22020-04-27 18:20:16 +0100119 data.append(make_da_tag(DACommands.DumpSHRAM, 0, 0))
Louis Verhaard52078302020-11-18 13:35:06 +0100120
121
122def create_driver_payload(register_command_stream: List[int], arch: ArchitectureFeatures) -> bytes:
Jonas Ohlssond8575072022-03-30 10:30:25 +0200123 """Creates driver header and includes the given command"""
Louis Verhaard52078302020-11-18 13:35:06 +0100124 # Prepare driver actions for this command tensor
Dwight Lidman9b43f842020-12-08 17:56:44 +0100125 da_list: List[int] = []
Louis Verhaard52078302020-11-18 13:35:06 +0100126 emit_fourcc(da_list, "COP1")
127 emit_config(da_list, 0, 1, arch)
erik.andersson@arm.com1878dab2021-03-16 09:40:24 +0100128 if len(register_command_stream) >= 1 << 24:
129 raise VelaError(
130 "The command stream exceeds the driver size limit of 64 MiB. "
131 f"The current stream size is {4*len(register_command_stream)/2**20:.2F} MiB"
132 )
133
Louis Verhaard52078302020-11-18 13:35:06 +0100134 emit_cmd_stream_header(da_list, len(register_command_stream))
135
136 # Append command stream words
137 da_list.extend(register_command_stream)
138 # Convert to bytes, in little endian format
139 return struct.pack("<{0}I".format(len(da_list)), *da_list)
140
141
142def npu_create_driver_payload(register_command_stream: List[int], accelerator: NpuAccelerator) -> bytes:
143 """Internal implementation of the public facing API to create driver payload"""
144 arch = create_default_arch(Accelerator.from_npu_accelerator(accelerator))
145 return create_driver_payload(register_command_stream, arch)