diff options
author | Kristofer Jonsson <kristofer.jonsson@arm.com> | 2022-01-27 17:39:06 +0100 |
---|---|---|
committer | Kristofer Jonsson <kristofer.jonsson@arm.com> | 2022-01-31 16:58:33 +0100 |
commit | 5410db1be8c1b8f84c5062e646156e8bca42a4c4 (patch) | |
tree | f782ab4ee6bbc9e15643733ad937a564def8cbe7 | |
parent | 6e9fdc0565ff07fce1fb5efc18bb7d5dbe3da489 (diff) | |
download | ethos-u-core-platform-5410db1be8c1b8f84c5062e646156e8bca42a4c4.tar.gz |
PMU multi NPU support
Update sample applications to use an external context for the PMU
configuration. The external context stored in the InferenceJob will
be set as TFLu external context and will be returned in the
ethosu_inference_begin() and ethosu_inference_end() callbacks.
Change-Id: Ief1f0943e322c2b50e8b964017af59161f67de6b
-rw-r--r-- | applications/baremetal/main.cpp | 33 | ||||
-rw-r--r-- | applications/driver_unit_tests/command_stream.cpp | 6 | ||||
-rw-r--r-- | applications/freertos/main.cpp | 14 | ||||
-rw-r--r-- | applications/message_handler/message_handler.cpp | 85 | ||||
-rw-r--r-- | applications/message_handler/message_handler.hpp | 8 | ||||
-rw-r--r-- | applications/trustzone_inference/secure/main_secure.cpp | 12 |
6 files changed, 90 insertions, 68 deletions
diff --git a/applications/baremetal/main.cpp b/applications/baremetal/main.cpp index ea5f03c..e9b398a 100644 --- a/applications/baremetal/main.cpp +++ b/applications/baremetal/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. All rights reserved. + * Copyright (c) 2021-2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -39,6 +39,7 @@ #endif using namespace std; +using namespace InferenceProcess; /**************************************************************************** * InferenceJob @@ -50,7 +51,7 @@ using namespace std; __attribute__((section(".bss.tensor_arena"), aligned(16))) uint8_t TFLuTensorArena[TENSOR_ARENA_SIZE]; -InferenceProcess::InferenceProcess inferenceProcess(TFLuTensorArena, TENSOR_ARENA_SIZE); +class InferenceProcess inferenceProcess(TFLuTensorArena, TENSOR_ARENA_SIZE); uint8_t outputData[sizeof(expectedOutputData)] __attribute__((aligned(16), section("output_data_sec"))); @@ -97,7 +98,7 @@ void SysTick_Handler(void) { ethosuMonitor.monitorSample(ethosuDrv); } -void ethosu_inference_begin(struct ethosu_driver *drv, const void *) { +void ethosu_inference_begin(struct ethosu_driver *drv, void *) { ethosuDrv = drv; ethosuMonitor.configure(drv, pmuEventConfig); @@ -105,7 +106,7 @@ void ethosu_inference_begin(struct ethosu_driver *drv, const void *) { SysTick_Config(delayMs); } -void ethosu_inference_end(struct ethosu_driver *drv, const void *) { +void ethosu_inference_end(struct ethosu_driver *drv, void *) { // Disable polling SysTick->CTRL = 0; @@ -117,25 +118,13 @@ void ethosu_inference_end(struct ethosu_driver *drv, const void *) { #endif int runInference() { - // Load inference data - vector<InferenceProcess::DataPtr> input; - input.push_back(InferenceProcess::DataPtr(inputData, sizeof(inputData))); - - vector<InferenceProcess::DataPtr> output; - output.push_back(InferenceProcess::DataPtr(outputData, sizeof(outputData))); - - vector<InferenceProcess::DataPtr> expected; - expected.push_back(InferenceProcess::DataPtr(expectedOutputData, sizeof(expectedOutputData))); - // Create job - InferenceProcess::InferenceJob job(string(modelName), - InferenceProcess::DataPtr(networkModelData, sizeof(networkModelData)), - input, - output, - expected, - 512, - std::vector<uint8_t>(4), - false); + InferenceJob job(string(modelName), + DataPtr(networkModelData, sizeof(networkModelData)), + {DataPtr(inputData, sizeof(inputData))}, + {DataPtr(outputData, sizeof(outputData))}, + {DataPtr(expectedOutputData, sizeof(expectedOutputData))}, + 512); // Run job bool failed = inferenceProcess.runJob(job); diff --git a/applications/driver_unit_tests/command_stream.cpp b/applications/driver_unit_tests/command_stream.cpp index 5b0de72..76dba6f 100644 --- a/applications/driver_unit_tests/command_stream.cpp +++ b/applications/driver_unit_tests/command_stream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. All rights reserved. + * Copyright (c) 2021-2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -121,8 +121,8 @@ int CommandStream::run(size_t repeat) { } while (repeat-- > 0) { - int error = ethosu_invoke( - drv, commandStream.data, commandStream.size, baseAddress, baseAddressSize, ETHOSU_BASEP_INDEXES); + int error = ethosu_invoke_v3( + drv, commandStream.data, commandStream.size, baseAddress, baseAddressSize, ETHOSU_BASEP_INDEXES, nullptr); if (error != 0) { printf("Inference failed. error=%d\n", error); diff --git a/applications/freertos/main.cpp b/applications/freertos/main.cpp index 0f4009e..81631ef 100644 --- a/applications/freertos/main.cpp +++ b/applications/freertos/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * Copyright (c) 2019-2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -99,17 +99,9 @@ struct xInferenceJob : public InferenceJob { const vector<DataPtr> &_output, const vector<DataPtr> &_expectedOutput, const size_t _numBytesToPrint, - const vector<uint8_t> &_pmuEventConfig, - const uint32_t _pmuCycleCounterEnable, + void *_userArg, QueueHandle_t _queue) : - InferenceJob(_name, - _networkModel, - _input, - _output, - _expectedOutput, - _numBytesToPrint, - _pmuEventConfig, - _pmuCycleCounterEnable), + InferenceJob(_name, _networkModel, _input, _output, _expectedOutput, _numBytesToPrint, _userArg), responseQueue(_queue), status(false) {} }; diff --git a/applications/message_handler/message_handler.cpp b/applications/message_handler/message_handler.cpp index f9f7304..585d63c 100644 --- a/applications/message_handler/message_handler.cpp +++ b/applications/message_handler/message_handler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * Copyright (c) 2020-2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -22,6 +22,7 @@ #ifdef ETHOSU #include <ethosu_driver.h> +#include <pmu_ethosu.h> #endif #include "FreeRTOS.h" @@ -150,12 +151,12 @@ bool IncomingMessageHandler::handleMessage() { break; } - printf("Msg: InferenceReq. user_arg=0x%" PRIx64 ", network={0x%" PRIx32 ", %" PRIu32 "}\n", + printf("Msg: InferenceReq. user_arg=0x%" PRIx64 ", network={0x%" PRIx32 ", %" PRIu32 "}, \n", inference.user_arg, inference.network.ptr, inference.network.size); - printf(", ifm_count=%" PRIu32 ", ifm=[", inference.ifm_count); + printf("ifm_count=%" PRIu32 ", ifm=[", inference.ifm_count); for (uint32_t i = 0; i < inference.ifm_count; ++i) { if (i > 0) { printf(", "); @@ -223,6 +224,9 @@ void InferenceHandler::run() { } void InferenceHandler::runInference(ethosu_core_inference_req &req, ethosu_core_inference_rsp &rsp) { + currentReq = &req; + currentRsp = &rsp; + /* * Setup inference job */ @@ -239,15 +243,7 @@ void InferenceHandler::runInference(ethosu_core_inference_req &req, ethosu_core_ ofm.push_back(InferenceProcess::DataPtr(reinterpret_cast<void *>(req.ofm[i].ptr), req.ofm[i].size)); } - std::vector<InferenceProcess::DataPtr> expectedOutput; - - std::vector<uint8_t> pmuEventConfig(ETHOSU_CORE_PMU_MAX); - for (uint32_t i = 0; i < ETHOSU_CORE_PMU_MAX; i++) { - pmuEventConfig[i] = req.pmu_event_config[i]; - } - - InferenceProcess::InferenceJob job( - "job", networkModel, ifm, ofm, expectedOutput, -1, pmuEventConfig, req.pmu_cycle_counter_enable); + InferenceProcess::InferenceJob job("job", networkModel, ifm, ofm, {}, -1, this); /* * Run inference @@ -269,16 +265,8 @@ void InferenceHandler::runInference(ethosu_core_inference_req &req, ethosu_core_ rsp.ofm_size[i] = job.output[i].size; } - for (size_t i = 0; i < job.pmuEventConfig.size(); i++) { - rsp.pmu_event_config[i] = job.pmuEventConfig[i]; - } - - for (size_t i = 0; i < job.pmuEventCount.size(); i++) { - rsp.pmu_event_count[i] = job.pmuEventCount[i]; - } - - rsp.pmu_cycle_counter_enable = job.pmuCycleCounterEnable; - rsp.pmu_cycle_counter_count = job.pmuCycleCounterCount; + currentReq = nullptr; + currentRsp = nullptr; } /**************************************************************************** @@ -404,3 +392,56 @@ void OutgoingMessageHandler::readCapabilties(ethosu_core_msg_capabilities_rsp &r } } // namespace MessageHandler + +extern "C" void ethosu_inference_begin(struct ethosu_driver *drv, void *userArg) { + MessageHandler::InferenceHandler *self = static_cast<MessageHandler::InferenceHandler *>(userArg); + + // Calculate maximum number of events + const int numEvents = std::min(static_cast<int>(ETHOSU_PMU_Get_NumEventCounters()), ETHOSU_CORE_PMU_MAX); + + // Enable PMU + ETHOSU_PMU_Enable(drv); + + // Configure and enable events + for (int i = 0; i < numEvents; i++) { + ETHOSU_PMU_Set_EVTYPER(drv, i, static_cast<ethosu_pmu_event_type>(self->currentReq->pmu_event_config[i])); + ETHOSU_PMU_CNTR_Enable(drv, 1 << i); + } + + // Enable cycle counter + if (self->currentReq->pmu_cycle_counter_enable) { + ETHOSU_PMU_CNTR_Enable(drv, ETHOSU_PMU_CCNT_Msk); + ETHOSU_PMU_CYCCNT_Reset(drv); + } + + // Reset all counters + ETHOSU_PMU_EVCNTR_ALL_Reset(drv); +} + +extern "C" void ethosu_inference_end(struct ethosu_driver *drv, void *userArg) { + MessageHandler::InferenceHandler *self = static_cast<MessageHandler::InferenceHandler *>(userArg); + + // Get cycle counter + self->currentRsp->pmu_cycle_counter_enable = self->currentReq->pmu_cycle_counter_enable; + if (self->currentReq->pmu_cycle_counter_enable) { + self->currentRsp->pmu_cycle_counter_count = ETHOSU_PMU_Get_CCNTR(drv); + } + + // Calculate maximum number of events + const int numEvents = std::min(static_cast<int>(ETHOSU_PMU_Get_NumEventCounters()), ETHOSU_CORE_PMU_MAX); + + // Get event counters + int i; + for (i = 0; i < numEvents; i++) { + self->currentRsp->pmu_event_config[i] = self->currentReq->pmu_event_config[i]; + self->currentRsp->pmu_event_count[i] = ETHOSU_PMU_Get_EVCNTR(drv, i); + } + + for (; i < ETHOSU_CORE_PMU_MAX; i++) { + self->currentRsp->pmu_event_config[i] = 0; + self->currentRsp->pmu_event_count[i] = 0; + } + + // Disable PMU + ETHOSU_PMU_Disable(drv); +} diff --git a/applications/message_handler/message_handler.hpp b/applications/message_handler/message_handler.hpp index 5a195f0..36768ee 100644 --- a/applications/message_handler/message_handler.hpp +++ b/applications/message_handler/message_handler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * Copyright (c) 2020-2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -24,6 +24,7 @@ #include "semphr.h" #include "message_queue.hpp" +#include <ethosu_driver.h> #include <inference_process.hpp> #include <mailbox.hpp> @@ -62,9 +63,14 @@ public: private: void runInference(EthosU::ethosu_core_inference_req &req, EthosU::ethosu_core_inference_rsp &rsp); + friend void ::ethosu_inference_begin(struct ethosu_driver *drv, void *userArg); + friend void ::ethosu_inference_end(struct ethosu_driver *drv, void *userArg); + QueueHandle_t inferenceQueue; QueueHandle_t outputQueue; InferenceProcess::InferenceProcess inference; + EthosU::ethosu_core_inference_req *currentReq; + EthosU::ethosu_core_inference_rsp *currentRsp; }; struct OutputMessage { diff --git a/applications/trustzone_inference/secure/main_secure.cpp b/applications/trustzone_inference/secure/main_secure.cpp index 984f19a..1e0ea58 100644 --- a/applications/trustzone_inference/secure/main_secure.cpp +++ b/applications/trustzone_inference/secure/main_secure.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. All rights reserved. + * Copyright (c) 2021-2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -356,14 +356,8 @@ int run_inference(void) { vector<InferenceProcess::DataPtr> expected; expected.push_back(InferenceProcess::DataPtr(expectedData, sizeof(expectedData))); - InferenceProcess::InferenceJob job("secure", - InferenceProcess::DataPtr(networkModelData, sizeof(networkModelData)), - input, - output, - expected, - 512, - std::vector<uint8_t>(4), - false); + InferenceProcess::InferenceJob job( + "secure", InferenceProcess::DataPtr(networkModelData, sizeof(networkModelData)), input, output, expected, 512); bool failed = inferenceProcess.runJob(job); printf("Status of executing the job: "); |