blob: 07f7f22fd41644d2f7c318509d60f45f88242c39 [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
59Pmu::Pmu(ethosu_driver *_drv, const PmuEvents &_config) :
60 drv(_drv),
61 config(_config)
62{
63 // Enable PMU block
64 ETHOSU_PMU_Enable_v2(drv);
65
66 // Enable cycle counter
67 ETHOSU_PMU_CNTR_Enable_v2(drv, ETHOSU_PMU_CCNT_Msk);
68
69 // Configure event types
70 for (size_t i = 0; i < config.size(); i++) {
71 ETHOSU_PMU_Set_EVTYPER_v2(drv, i, config[i]);
72 ETHOSU_PMU_CNTR_Enable_v2(drv, 1 << i);
73 }
74}
75
76void Pmu::clear() {
77 ETHOSU_PMU_CYCCNT_Reset_v2(drv);
78 ETHOSU_PMU_EVCNTR_ALL_Reset_v2(drv);
79}
80
81void Pmu::print() {
82 printf("PMU={cycleCount=%llu, events=[%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 "]}\n",
83 ETHOSU_PMU_Get_CCNTR_v2(drv),
84 ETHOSU_PMU_Get_EVCNTR_v2(drv, 0),
85 ETHOSU_PMU_Get_EVCNTR_v2(drv, 1),
86 ETHOSU_PMU_Get_EVCNTR_v2(drv, 2),
87 ETHOSU_PMU_Get_EVCNTR_v2(drv, 3));
88}
89
90uint64_t Pmu::getCycleCount() const {
91 return ETHOSU_PMU_Get_CCNTR_v2(drv);
92}
93
94uint32_t Pmu::getEventCount(size_t index) const {
95 return ETHOSU_PMU_Get_EVCNTR_v2(drv, index);
96}
97
98/****************************************************************************
99 * CommandStream
100 ****************************************************************************/
101
102CommandStream::CommandStream(const DataPointer &_commandStream,
103 const BasePointers &_basePointers,
104 const PmuEvents &_pmuEvents) :
105 drv(ethosu_reserve_driver()),
106 commandStream(_commandStream),
107 basePointers(_basePointers),
108 pmu(drv, _pmuEvents)
109{
110 // Disable clock gating, else the NPU PMU will be clock gated and report too few cycles
111 ethosu_set_clock_and_power(&drv->dev, ETHOSU_CLOCK_Q_DISABLE, ETHOSU_POWER_Q_DISABLE);
112
113 // Use simplified driver setup
114 ethosu_set_power_mode_v2(drv, true);
115}
116
117CommandStream::~CommandStream() {
118 ethosu_set_power_mode_v2(drv, false);
119 ethosu_release_driver(drv);
120}
121
122int CommandStream::run(size_t repeat) {
123 // Base pointer array
124 uint64_t baseAddress[ETHOSU_DRIVER_BASEP_INDEXES];
125 size_t baseAddressSize[ETHOSU_DRIVER_BASEP_INDEXES];
126 for (size_t i = 0; i < ETHOSU_DRIVER_BASEP_INDEXES; i++) {
127 baseAddress[i] = reinterpret_cast<uint64_t>(basePointers[i].data);
128 baseAddressSize[i] = reinterpret_cast<size_t>(basePointers[i].size);
129 }
130
131 while (repeat-- > 0) {
132 int error = ethosu_invoke_v3(drv, commandStream.data, commandStream.size, baseAddress, baseAddressSize, ETHOSU_DRIVER_BASEP_INDEXES);
133
134 if (error != 0) {
135 printf("Inference failed. error=%d\n", error);
136 return 1;
137 }
138
139 // Wait for interrupt
140 while (true) {
141 uint16_t status;
142 ethosu_get_status_mask(&drv->dev, &status);
143
144 // Return if NPU raise error status
145 if (status & 0xcc) {
146 printf("Job failed with error. status=0x%08x\n", status);
147 return 1;
148 }
149
150 // Break loop if job is no longer running
151 if ((status & 1) == 0) {
152 break;
153 }
154
155 // Sleep waiting on interrupt
156 __WFI();
157 }
158 }
159
160 return 0;
161}
162
163DataPointer &CommandStream::getCommandStream()
164{
165 return commandStream;
166}
167
168BasePointers &CommandStream::getBasePointers()
169{
170 return basePointers;
171}
172
173Pmu &CommandStream::getPmu()
174{
175 return pmu;
176}
177
178}; // namespace CommandStream
179}; // namespace EthosU