blob: a0b9171c63282efa6000ae04aeaf91a66a1eb3af [file] [log] [blame]
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +01001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/****************************************************************************
20 * Includes
21 ****************************************************************************/
22
23#include "command_stream.hpp"
24
25#include <inttypes.h>
26#include <stdio.h>
27
28using namespace std;
29
30namespace EthosU {
31namespace CommandStream {
32
33/****************************************************************************
34 * DataPointer
35 ****************************************************************************/
36
37DataPointer::DataPointer() : data(nullptr), size(0) {}
38
39DataPointer::DataPointer(const char *_data, size_t _size) : data(_data), size(_size) {}
40
41bool DataPointer::operator!=(const DataPointer &other) {
42 if (size != other.size) {
43 return true;
44 }
45
46 for (size_t i = 0; i < size; i++) {
47 if (data[i] != other.data[i]) {
48 return true;
49 }
50 }
51
52 return false;
53}
54
55/****************************************************************************
56 * PmuConfig
57 ****************************************************************************/
58
Anton Moberg908a07c2021-04-08 09:50:57 +020059Pmu::Pmu(ethosu_driver *_drv, const PmuEvents &_config) : drv(_drv), config(_config) {
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +010060 // Enable PMU block
61 ETHOSU_PMU_Enable_v2(drv);
62
63 // Enable cycle counter
64 ETHOSU_PMU_CNTR_Enable_v2(drv, ETHOSU_PMU_CCNT_Msk);
65
66 // Configure event types
67 for (size_t i = 0; i < config.size(); i++) {
68 ETHOSU_PMU_Set_EVTYPER_v2(drv, i, config[i]);
69 ETHOSU_PMU_CNTR_Enable_v2(drv, 1 << i);
70 }
71}
72
73void Pmu::clear() {
74 ETHOSU_PMU_CYCCNT_Reset_v2(drv);
75 ETHOSU_PMU_EVCNTR_ALL_Reset_v2(drv);
76}
77
78void Pmu::print() {
79 printf("PMU={cycleCount=%llu, events=[%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 "]}\n",
Anton Moberg908a07c2021-04-08 09:50:57 +020080 ETHOSU_PMU_Get_CCNTR_v2(drv),
81 ETHOSU_PMU_Get_EVCNTR_v2(drv, 0),
82 ETHOSU_PMU_Get_EVCNTR_v2(drv, 1),
83 ETHOSU_PMU_Get_EVCNTR_v2(drv, 2),
84 ETHOSU_PMU_Get_EVCNTR_v2(drv, 3));
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +010085}
86
87uint64_t Pmu::getCycleCount() const {
88 return ETHOSU_PMU_Get_CCNTR_v2(drv);
89}
90
91uint32_t Pmu::getEventCount(size_t index) const {
92 return ETHOSU_PMU_Get_EVCNTR_v2(drv, index);
93}
94
95/****************************************************************************
96 * CommandStream
97 ****************************************************************************/
98
99CommandStream::CommandStream(const DataPointer &_commandStream,
100 const BasePointers &_basePointers,
101 const PmuEvents &_pmuEvents) :
102 drv(ethosu_reserve_driver()),
Anton Moberg908a07c2021-04-08 09:50:57 +0200103 commandStream(_commandStream), basePointers(_basePointers), pmu(drv, _pmuEvents) {
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +0100104 // Disable clock gating, else the NPU PMU will be clock gated and report too few cycles
105 ethosu_set_clock_and_power(&drv->dev, ETHOSU_CLOCK_Q_DISABLE, ETHOSU_POWER_Q_DISABLE);
106
107 // Use simplified driver setup
108 ethosu_set_power_mode_v2(drv, true);
109}
110
111CommandStream::~CommandStream() {
112 ethosu_set_power_mode_v2(drv, false);
113 ethosu_release_driver(drv);
114}
115
116int CommandStream::run(size_t repeat) {
117 // Base pointer array
118 uint64_t baseAddress[ETHOSU_DRIVER_BASEP_INDEXES];
119 size_t baseAddressSize[ETHOSU_DRIVER_BASEP_INDEXES];
120 for (size_t i = 0; i < ETHOSU_DRIVER_BASEP_INDEXES; i++) {
Anton Moberg908a07c2021-04-08 09:50:57 +0200121 baseAddress[i] = reinterpret_cast<uint64_t>(basePointers[i].data);
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +0100122 baseAddressSize[i] = reinterpret_cast<size_t>(basePointers[i].size);
123 }
124
125 while (repeat-- > 0) {
Anton Moberg908a07c2021-04-08 09:50:57 +0200126 int error = ethosu_invoke_v3(
127 drv, commandStream.data, commandStream.size, baseAddress, baseAddressSize, ETHOSU_DRIVER_BASEP_INDEXES);
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +0100128
129 if (error != 0) {
130 printf("Inference failed. error=%d\n", error);
131 return 1;
132 }
133
134 // Wait for interrupt
135 while (true) {
136 uint16_t status;
137 ethosu_get_status_mask(&drv->dev, &status);
138
139 // Return if NPU raise error status
140 if (status & 0xcc) {
141 printf("Job failed with error. status=0x%08x\n", status);
142 return 1;
143 }
144
145 // Break loop if job is no longer running
146 if ((status & 1) == 0) {
147 break;
148 }
149
150 // Sleep waiting on interrupt
151 __WFI();
152 }
153 }
154
155 return 0;
156}
157
Anton Moberg908a07c2021-04-08 09:50:57 +0200158DataPointer &CommandStream::getCommandStream() {
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +0100159 return commandStream;
160}
161
Anton Moberg908a07c2021-04-08 09:50:57 +0200162BasePointers &CommandStream::getBasePointers() {
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +0100163 return basePointers;
164}
165
Anton Moberg908a07c2021-04-08 09:50:57 +0200166Pmu &CommandStream::getPmu() {
Kristofer Jonssonb5f7cfe2021-03-10 17:13:52 +0100167 return pmu;
168}
169
170}; // namespace CommandStream
171}; // namespace EthosU