// // Copyright © 2019 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #include "PeriodicCounterSelectionCommandHandler.hpp" #include "ProfilingUtils.hpp" #include #include #include #include namespace armnn { namespace profiling { void PeriodicCounterSelectionCommandHandler::ParseData(const Packet& packet, CaptureData& captureData) { std::vector counterIds; uint32_t sizeOfUint32 = boost::numeric_cast(sizeof(uint32_t)); uint32_t sizeOfUint16 = boost::numeric_cast(sizeof(uint16_t)); uint32_t offset = 0; if (packet.GetLength() < 4) { // Insufficient packet size return; } // Parse the capture period uint32_t capturePeriod = ReadUint32(packet.GetData(), offset); // Set the capture period captureData.SetCapturePeriod(capturePeriod); // Parse the counter ids unsigned int counters = (packet.GetLength() - 4) / 2; if (counters > 0) { counterIds.reserve(counters); offset += sizeOfUint32; for (unsigned int i = 0; i < counters; ++i) { // Parse the counter id uint16_t counterId = ReadUint16(packet.GetData(), offset); counterIds.emplace_back(counterId); offset += sizeOfUint16; } } // Set the counter ids captureData.SetCounterIds(counterIds); } void PeriodicCounterSelectionCommandHandler::operator()(const Packet& packet) { ProfilingState currentState = m_StateMachine.GetCurrentState(); switch (currentState) { case ProfilingState::Uninitialised: case ProfilingState::NotConnected: case ProfilingState::WaitingForAck: throw RuntimeException(boost::str(boost::format("Periodic Counter Selection Command Handler invoked while in " "an wrong state: %1%") % GetProfilingStateName(currentState))); case ProfilingState::Active: { // Process the packet if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 4u)) { throw armnn::InvalidArgumentException(boost::str(boost::format("Expected Packet family = 0, id = 4 but " "received family = %1%, id = %2%") % packet.GetPacketFamily() % packet.GetPacketId())); } // Parse the packet to get the capture period and counter UIDs CaptureData captureData; ParseData(packet, captureData); // Get the capture data uint32_t capturePeriod = captureData.GetCapturePeriod(); // Validate that the capture period is within the acceptable range. if (capturePeriod > 0 && capturePeriod < LOWEST_CAPTURE_PERIOD) { capturePeriod = LOWEST_CAPTURE_PERIOD; } const std::vector& counterIds = captureData.GetCounterIds(); // Check whether the selected counter UIDs are valid std::vector validCounterIds; for (uint16_t counterId : counterIds) { // Check whether the counter is registered if (!m_ReadCounterValues.IsCounterRegistered(counterId)) { // Invalid counter UID, ignore it and continue continue; } // The counter is valid validCounterIds.push_back(counterId); } // Set the capture data with only the valid counter UIDs m_CaptureDataHolder.SetCaptureData(capturePeriod, validCounterIds); // Echo back the Periodic Counter Selection packet to the Counter Stream Buffer m_SendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, validCounterIds); if (capturePeriod == 0 || validCounterIds.empty()) { // No data capture stop the thread m_PeriodicCounterCapture.Stop(); } else { // Start the Period Counter Capture thread (if not running already) m_PeriodicCounterCapture.Start(); } break; } default: throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1%") % static_cast(currentState))); } } } // namespace profiling } // namespace armnn