LCOV - code coverage report
Current view: top level - aicpu_schedule/core - aicpusd_message_queue.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.2 % 185 154
Test Date: 2026-08-12 11:05:02 Functions: 81.6 % 38 31

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "aicpusd_message_queue.h"
      12              : 
      13              : #include "ascend_hal.h"
      14              : #include "aicpusd_hal_interface_ref.h"
      15              : #include "type_def.h"
      16              : #include "aicpusd_status.h"
      17              : #include "aicpusd_drv_manager.h"
      18              : #include "aicpusd_feature_ctrl.h"
      19              : #include "aicpusd_msq_operator_manager.h"
      20              : 
      21              : namespace AicpuSchedule {
      22              : namespace {
      23              : enum class MsqDataSize : uint32_t {
      24              :     MSQ_DATA_SIZE_0 = 0b000,   // No message
      25              :     MSQ_DATA_SIZE_128 = 0b100, // Message is 128bit, MSQ_DATA[0:1]_EL0 are valid for read
      26              :     MSQ_DATA_SIZE_256 = 0b101, // Message is 256bit, MSQ_DATA[0:3]_EL0 are valid for read
      27              :     MSQ_DATA_SIZE_512 = 0b110, // Message is 512bit, MSQ_DATA[0:7]_EL0 are valid for read
      28              : };
      29              : 
      30              : enum class CqeStatus : uint16_t {
      31              :     CQE_STATUS_OK = 0b00000,
      32              :     CQE_STATUS_DEBUG = 0b00010,
      33              :     CQE_STATUS_EXCEPTION = 0b00100,
      34              :     CQE_STATUS_WARNING = 0b10000
      35              : };
      36              : 
      37              : constexpr uint32_t HARD_THREAD_NUM_PER_CPU = 2U;
      38              : constexpr uint32_t CQE_SIZE = 4U;
      39              : } // namespace
      40              : 
      41              : thread_local MessageQueue::MsqStatusFunc MessageQueue::readMsqStatusFunc_ = nullptr;
      42              : thread_local MessageQueue::MsqDataFunc MessageQueue::readMsqDataFunc_ = nullptr;
      43              : thread_local MessageQueue::MsqRspFunc MessageQueue::sendMsqRspFunc_ = nullptr;
      44              : thread_local uint32_t* MessageQueue::cqeAddr_ = nullptr;
      45              : std::shared_ptr<MsqImpl> MessageQueue::impl_ = nullptr;
      46              : 
      47           15 : MessageQueue& MessageQueue::GetInstance()
      48              : {
      49           15 :     static MessageQueue instance;
      50           15 :     return instance;
      51              : }
      52              : 
      53           25 : int32_t MessageQueue::InitMessageQueue(const uint32_t deviceId, const std::vector<uint32_t>& aicpuPhyIds)
      54              : {
      55           25 :     int32_t ret = AICPU_SCHEDULE_OK;
      56           25 :     deviceId_ = deviceId;
      57           25 :     aicpuPhyIds_ = aicpuPhyIds;
      58              : 
      59           25 :     ret = InitMsqImpl();
      60           25 :     if (ret != AICPU_SCHEDULE_OK) {
      61            0 :         aicpusd_err("Init message queue impl instance failed");
      62            0 :         return ret;
      63              :     }
      64              : 
      65           25 :     ret = InitCqeBaseAddr();
      66           25 :     if (ret != AICPU_SCHEDULE_OK) {
      67            2 :         aicpusd_err("Init cqe addr failed, ret=%d, deviceId=%u", ret, deviceId);
      68            2 :         return ret;
      69              :     }
      70              : 
      71           23 :     aicpusd_run_info(
      72              :         "Init message queue success, deviceId=%u, mode=%d", deviceId, static_cast<int32_t>(FeatureCtrl::IsUseMsqV2()));
      73              : 
      74           23 :     return AICPU_SCHEDULE_OK;
      75              : }
      76              : 
      77           25 : int32_t MessageQueue::InitMsqImpl() const
      78              : {
      79           25 :     int32_t ret = MsqOperatorManager::Init();
      80           25 :     if (ret != AICPU_SCHEDULE_OK) {
      81            0 :         aicpusd_err("Init msq operator manager failed");
      82            0 :         return ret;
      83              :     }
      84              : 
      85           25 :     impl_ = FeatureCtrl::IsUseMsqV2() ? std::make_shared<MsqImplV2>() : std::make_shared<MsqImplV1>();
      86           25 :     if (impl_ == nullptr) {
      87            0 :         aicpusd_err("Create msq impl failed by nullptr");
      88            0 :         return AICPU_SCHEDULE_ERROR_INNER_ERROR;
      89              :     }
      90              : 
      91           25 :     return AICPU_SCHEDULE_OK;
      92              : }
      93              : 
      94           25 : int32_t MessageQueue::InitCqeBaseAddr()
      95              : {
      96           25 :     cqeBaseAddr_ = MapResAddr(RES_ADDR_TYPE_STARS_TOPIC_CQE);
      97           25 :     if (cqeBaseAddr_ == nullptr) {
      98            2 :         aicpusd_err("Failed to get CQE base address: nullptr");
      99            2 :         return AICPU_SCHEDULE_ERROR_DRV_ERR;
     100              :     }
     101           23 :     aicpusd_info("Init cqe base addr success, va=0x%x", cqeBaseAddr_);
     102           23 :     return AICPU_SCHEDULE_OK;
     103              : }
     104              : 
     105           25 : uint32_t* MessageQueue::MapResAddr(const res_addr_type resType) const
     106              : {
     107           25 :     if (&halResAddrMap == nullptr) {
     108            0 :         aicpusd_err("Get resource address failed by nullptr");
     109            0 :         return nullptr;
     110              :     }
     111              : 
     112           25 :     res_addr_info resInfo = {};
     113           25 :     resInfo.id = 0U;
     114           25 :     resInfo.target_proc_type = PROCESS_CP1;
     115           25 :     resInfo.res_type = resType;
     116           25 :     resInfo.res_id = 0U;
     117           25 :     uint64_t va = 0UL;
     118           25 :     uint32_t len = 0U;
     119           25 :     const int32_t ret = halResAddrMap(deviceId_, &resInfo, &va, &len);
     120           25 :     if (ret != DRV_ERROR_NONE) {
     121            2 :         aicpusd_err("Get resource address failed, ret=%d, drvType=%u, deviceId=%u", ret, resType, deviceId_);
     122            2 :         return nullptr;
     123              :     }
     124              : 
     125           23 :     aicpusd_info("Get resource address success, type=%u, deviceId=%u, va=0x%x, len=%u", resType, deviceId_, va, len);
     126              : 
     127           23 :     return PtrToPtr<void, uint32_t>(ValueToPtr(va));
     128              : }
     129              : 
     130           11 : int32_t MessageQueue::InitMessageQueueForThread(const size_t threadIndex) const
     131              : {
     132           11 :     aicpusd_info("Start initializing message queue for thread");
     133              : 
     134           11 :     int32_t ret = ResetMessageQueueStatus(threadIndex);
     135           11 :     if (ret != AICPU_SCHEDULE_OK) {
     136            1 :         aicpusd_err("Reset message queue status failed, threadIndex=%u", threadIndex);
     137            1 :         return ret;
     138              :     }
     139              : 
     140           10 :     ret = InitMessageQueueStatusReadFunc(threadIndex);
     141           10 :     if (ret != AICPU_SCHEDULE_OK) {
     142            1 :         aicpusd_err("Init message queue status read func failed, threadIndex=%u", threadIndex);
     143            1 :         return ret;
     144              :     }
     145              : 
     146            9 :     ret = InitMessageQueueDataReadFunc(threadIndex);
     147            9 :     if (ret != AICPU_SCHEDULE_OK) {
     148            1 :         aicpusd_err("Init message queue data read func failed, threadIndex=%u", threadIndex);
     149            1 :         return ret;
     150              :     }
     151              : 
     152            8 :     ret = InitMessageQueueRspFunc(threadIndex);
     153            8 :     if (ret != AICPU_SCHEDULE_OK) {
     154            1 :         aicpusd_err("Init message queue rsp func failed, threadIndex=%u", threadIndex);
     155            1 :         return ret;
     156              :     }
     157              : 
     158            7 :     ret = InitCqeAddr(threadIndex);
     159            7 :     if (ret != AICPU_SCHEDULE_OK) {
     160            1 :         aicpusd_err("Init cqe addr failed, threadIndex=%u", threadIndex);
     161            1 :         return ret;
     162              :     }
     163              : 
     164            6 :     aicpusd_info("Init message queue for thread success, threadIndex=%u", threadIndex);
     165              : 
     166            6 :     return AICPU_SCHEDULE_OK;
     167              : }
     168              : 
     169           10 : int32_t MessageQueue::ResetMessageQueueStatus(const size_t threadIndex) const
     170              : {
     171              :     // MSQ{0-7}_STATUS_EL0
     172           10 :     aicpusd_info("Start reset message queue status");
     173           10 :     int32_t ret = AICPU_SCHEDULE_OK;
     174           10 :     MsqStatus msqStatus = {};
     175           10 :     if (isEnableHardThread_) {
     176            1 :         ret = IsUseMsqT0(threadIndex) ? ResetMsqT0Status() : ResetMsqT1Status();
     177            1 :         msqStatus = IsUseMsqT0(threadIndex) ? ReadMsqT0Status() : ReadMsqT1Status();
     178              :     } else {
     179            9 :         (void)ResetMsqT0Status();
     180            9 :         ret = ResetMsqT1Status();
     181            9 :         msqStatus = ReadMsqT0Status();
     182              :     }
     183              : 
     184           10 :     aicpusd_info("End reset message queue status, ret=%d, valid=%u, comp=%u", ret, msqStatus.valid, msqStatus.comp);
     185              : 
     186           10 :     return ret;
     187              : }
     188              : 
     189           10 : int32_t MessageQueue::ResetMsqT0Status() const { return impl_->ResetMsqT0Status(); }
     190              : 
     191            9 : int32_t MessageQueue::ResetMsqT1Status() const { return impl_->ResetMsqT1Status(); }
     192              : 
     193            9 : int32_t MessageQueue::InitMessageQueueStatusReadFunc(const size_t threadIndex) const
     194              : {
     195            9 :     if (isEnableHardThread_) {
     196            1 :         readMsqStatusFunc_ = IsUseMsqT0(threadIndex) ? &MessageQueue::ReadMsqT0Status : &MessageQueue::ReadMsqT1Status;
     197              :     } else {
     198            8 :         readMsqStatusFunc_ = &MessageQueue::ReadMsqT0Status;
     199              :     }
     200              : 
     201            9 :     return AICPU_SCHEDULE_OK;
     202              : }
     203              : 
     204           11 : MsqStatus MessageQueue::ReadMsqT0Status() { return impl_->ReadMsqT0Status(); }
     205              : 
     206            0 : MsqStatus MessageQueue::ReadMsqT1Status() { return impl_->ReadMsqT1Status(); }
     207              : 
     208            8 : int32_t MessageQueue::InitMessageQueueDataReadFunc(const size_t threadIndex) const
     209              : {
     210            8 :     if (isEnableHardThread_) {
     211            1 :         readMsqDataFunc_ = IsUseMsqT0(threadIndex) ? &MessageQueue::ReadMsqT0Data : &MessageQueue::ReadMsqT1Data;
     212              :     } else {
     213            7 :         readMsqDataFunc_ = &MessageQueue::ReadMsqT0Data;
     214              :     }
     215              : 
     216            8 :     return AICPU_SCHEDULE_OK;
     217              : }
     218              : 
     219            2 : void MessageQueue::ReadMsqT0Data(const uint32_t msgSize, MsqDatas& datas) { impl_->ReadMsqT0Data(msgSize, datas); }
     220              : 
     221            2 : void MessageQueue::ReadMsqT1Data(const uint32_t msgSize, MsqDatas& datas) { impl_->ReadMsqT1Data(msgSize, datas); }
     222              : 
     223            7 : int32_t MessageQueue::InitMessageQueueRspFunc(const size_t threadIndex) const
     224              : {
     225            7 :     if (isEnableHardThread_) {
     226            1 :         sendMsqRspFunc_ = IsUseMsqT0(threadIndex) ? &MessageQueue::SendMsqT0Response : &MessageQueue::SendMsqT1Response;
     227              :     } else {
     228            6 :         sendMsqRspFunc_ = &MessageQueue::SendMsqT0Response;
     229              :     }
     230              : 
     231            7 :     return AICPU_SCHEDULE_OK;
     232              : }
     233              : 
     234            1 : void MessageQueue::SendMsqT0Response() { impl_->SendMsqT0Response(); }
     235              : 
     236            1 : void MessageQueue::SendMsqT1Response() { impl_->SendMsqT1Response(); }
     237              : 
     238            9 : int32_t MessageQueue::InitCqeAddr(const size_t threadIndex) const
     239              : {
     240            9 :     if (threadIndex >= aicpuPhyIds_.size()) {
     241            2 :         aicpusd_err(
     242              :             "Init cqe addr failed, threadIdx larger than aicpuPhyIds size, threadIndex=%zu, size=%zu", threadIndex,
     243              :             aicpuPhyIds_.size());
     244            2 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     245              :     }
     246              : 
     247            7 :     cqeAddr_ = &(cqeBaseAddr_[aicpuPhyIds_[threadIndex] * CQE_SIZE]);
     248            7 :     aicpusd_info("Init cqe addr success, threadIndex=%zu, base=0x%x, va=0x%x", threadIndex, cqeBaseAddr_, cqeAddr_);
     249            7 :     return AICPU_SCHEDULE_OK;
     250              : }
     251              : 
     252          100 : void MessageQueue::SendResponse(const uint32_t errCode, const uint32_t status)
     253              : {
     254          100 :     if (sendMsqRspFunc_ == nullptr) {
     255           99 :         return;
     256              :     }
     257            1 :     MessageQueue::sendMsqRspFunc_();
     258            1 :     SetCQE(errCode, status);
     259              : }
     260              : 
     261            7 : bool MessageQueue::IsMsqRspComplete()
     262              : {
     263            7 :     if (readMsqStatusFunc_ == nullptr) {
     264            7 :         return false;
     265              :     }
     266              : 
     267            0 :     const MsqStatus status = readMsqStatusFunc_();
     268            0 :     return (status.valid == 0U);
     269              : }
     270              : 
     271            1 : void MessageQueue::SetCQE(const uint32_t errCode, const uint32_t status)
     272              : {
     273              :     /**
     274              :      * Topic CQE
     275              :      * 上报执行错误码
     276              :      *
     277              :      * total 32bit
     278              :      * [31:16](RW): error code
     279              :      * [15:0](RW): status
     280              :      */
     281              : 
     282            1 :     const uint32_t cqeStatus = (status == 0U) ? static_cast<uint32_t>(CqeStatus::CQE_STATUS_OK) :
     283              :                                                 static_cast<uint32_t>(CqeStatus::CQE_STATUS_EXCEPTION);
     284              : 
     285            1 :     aicpusd_info(
     286              :         "Begin to set cqe, va=0x%x, errCode=%u, status=%u, cqeStatus=%u", cqeAddr_, errCode, status, cqeStatus);
     287            1 :     *cqeAddr_ = ((errCode << 16U) | (cqeStatus));
     288            1 :     aicpusd_info("End to set cqe, va=0x%x, errCode=%u, status=%u, cqeStatus=%u", cqeAddr_, errCode, status, cqeStatus);
     289            1 : }
     290              : 
     291            1 : bool MessageQueue::WaitMsqInfoOnce(MsqDatas& datas)
     292              : {
     293            1 :     const MsqStatus status = readMsqStatusFunc_();
     294            1 :     if (status.valid == 0U) {
     295            1 :         WaitForEvent();
     296            1 :         return false;
     297              :     }
     298              : 
     299            0 :     aicpusd_info("Begin to read message queue datas, size=%u", status.size);
     300            0 :     readMsqDataFunc_(status.size, datas);
     301            0 :     aicpusd_info("End to read message queue datas, size=%u", status.size);
     302              : 
     303            0 :     return true;
     304              : }
     305              : 
     306            1 : void MessageQueue::WaitForEvent()
     307              : {
     308            1 :     MsqOperatorManager::CallWait();
     309            1 :     return;
     310              : }
     311              : 
     312            5 : bool MessageQueue::IsUseMsqT0(const size_t threadIndex) { return ((threadIndex % HARD_THREAD_NUM_PER_CPU) == 0U); }
     313              : 
     314           10 : int32_t MsqImplV1::ResetMsqT0Status() const
     315              : {
     316           10 :     MsqOperatorManager::CallV1ResetT0Status();
     317           10 :     return AICPU_SCHEDULE_OK;
     318              : }
     319              : 
     320            9 : int32_t MsqImplV1::ResetMsqT1Status() const
     321              : {
     322            9 :     MsqOperatorManager::CallV1ResetT1Status();
     323            9 :     return AICPU_SCHEDULE_OK;
     324              : }
     325              : 
     326           11 : MsqStatus MsqImplV1::ReadMsqT0Status() const { return MsqOperatorManager::CallV1ReadT0Status(); }
     327              : 
     328            0 : MsqStatus MsqImplV1::ReadMsqT1Status() const { return MsqOperatorManager::CallV1ReadT1Status(); }
     329              : 
     330            2 : void MsqImplV1::ReadMsqT0Data(const uint32_t msgSize, MsqDatas& datas) const
     331              : {
     332            2 :     if (msgSize == static_cast<uint32_t>(MsqDataSize::MSQ_DATA_SIZE_0)) {
     333            1 :         aicpusd_err("Message size is 0");
     334            1 :         return;
     335              :     }
     336              : 
     337            1 :     MsqOperatorManager::CallV1ReadT0Data(msgSize, &datas);
     338              : }
     339              : 
     340            2 : void MsqImplV1::ReadMsqT1Data(const uint32_t msgSize, MsqDatas& datas) const
     341              : {
     342            2 :     if (msgSize == static_cast<uint32_t>(MsqDataSize::MSQ_DATA_SIZE_0)) {
     343            1 :         aicpusd_err("Message size is 0");
     344            1 :         return;
     345              :     }
     346              : 
     347            1 :     MsqOperatorManager::CallV1ReadT1Data(msgSize, &datas);
     348              : }
     349              : 
     350            1 : void __attribute__((optimize("O0"))) MsqImplV1::SendMsqT0Response() const
     351              : {
     352              :     // O2 compilation optimization will optimize away the msq write operation, so O0 optimization must be used.
     353            1 :     MsqOperatorManager::CallV1SendT0Response();
     354            1 : }
     355              : 
     356            1 : void __attribute__((optimize("O0"))) MsqImplV1::SendMsqT1Response() const
     357              : {
     358            1 :     MsqOperatorManager::CallV1SendT1Response();
     359            1 : }
     360              : 
     361            0 : int32_t MsqImplV2::ResetMsqT0Status() const
     362              : {
     363            0 :     MsqOperatorManager::CallV2ResetT0Status();
     364            0 :     return AICPU_SCHEDULE_OK;
     365              : }
     366              : 
     367            0 : int32_t MsqImplV2::ResetMsqT1Status() const
     368              : {
     369            0 :     MsqOperatorManager::CallV2ResetT1Status();
     370            0 :     return AICPU_SCHEDULE_OK;
     371              : }
     372              : 
     373            0 : MsqStatus MsqImplV2::ReadMsqT1Status() const { return MsqOperatorManager::CallV2ReadT1Status(); }
     374              : 
     375            0 : void MsqImplV2::ReadMsqT1Data(const uint32_t msgSize, MsqDatas& datas) const
     376              : {
     377            0 :     if (msgSize == static_cast<uint32_t>(MsqDataSize::MSQ_DATA_SIZE_0)) {
     378            0 :         aicpusd_err("Message size is 0");
     379            0 :         return;
     380              :     }
     381              : 
     382            0 :     MsqOperatorManager::CallV2ReadT1Data(msgSize, &datas);
     383              : }
     384              : 
     385            0 : void __attribute__((optimize("O0"))) MsqImplV2::SendMsqT1Response() const
     386              : {
     387            0 :     MsqOperatorManager::CallV2SendT1Response();
     388            0 : }
     389              : } // namespace AicpuSchedule
        

Generated by: LCOV version 2.0-1