Line data Source code
1 : /**
2 : * Copyright (c) 2026 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 : #include "dump_stats_task.h"
11 :
12 : namespace kfc_dump_stats {
13 30 : void AddOneStatDumpTaskV1(uint8_t* sqeIn, KfcDumpOpInitParam* dumpParam, KfcDumpContext* dumpContext)
14 : {
15 30 : rtFftsPlusKernelSqe_t sqe = {};
16 30 : sqe.header.ie = 0;
17 30 : sqe.header.type = 0;
18 30 : sqe.header.pre_p = 0;
19 30 : sqe.header.post_p = 0;
20 30 : sqe.header.task_id = 0;
21 30 : sqe.ffts_type = static_cast<uint16_t>(KfcDumpTaskType::FFTS_TASK);
22 30 : sqe.header.wr_cqe = 0;
23 30 : sqe.header.block_dim = dumpContext->aiCoreNum;
24 30 : sqe.header.rt_stream_id = dumpParam->streamInfo.streamIds;
25 30 : sqe.res1 = 0;
26 30 : sqe.wrr_ratio = 1;
27 30 : sqe.res2 = 0;
28 30 : sqe.sqe_index = 0;
29 30 : sqe.kernel_credit = KERNEL_TIMEOUT_CONSTANT;
30 30 : sqe.schem = 1;
31 30 : sqe.res3 = 0;
32 30 : sqe.icache_prefetch_cnt = 0;
33 30 : sqe.stack_phy_base_low = static_cast<uint32_t>(dumpParam->kfcWorkSpace.stackPhyBase32k & LOW_ADDR_MASK);
34 30 : sqe.stack_phy_base_high = static_cast<uint32_t>(dumpParam->kfcWorkSpace.stackPhyBase32k >> TS_UINT32_BIT_NUM);
35 30 : sqe.res4 = 0;
36 30 : sqe.pmg = 0;
37 30 : sqe.ns = 1;
38 30 : sqe.part_id = 0;
39 30 : sqe.res5 = 0;
40 30 : sqe.qos = 0;
41 30 : sqe.res6 = 0;
42 30 : uint64_t pcAddr = dumpParam->config.dumpStatPcAddr;
43 30 : sqe.pc_addr_low = static_cast<uint32_t>(pcAddr & LOW_ADDR_MASK);
44 30 : sqe.pc_addr_high = static_cast<uint16_t>((pcAddr & HIGH_ADDR_MASK) >> TS_UINT32_BIT_NUM);
45 30 : uint64_t paramAddr = reinterpret_cast<uint64_t>(dumpContext);
46 30 : sqe.param_addr_low = static_cast<uint32_t>(paramAddr & LOW_ADDR_MASK);
47 30 : sqe.param_addr_high = static_cast<uint32_t>(paramAddr >> TS_UINT32_BIT_NUM);
48 30 : (void)memcpy_s(sqeIn, AC_SQE_SIZE, &sqe, AC_SQE_SIZE);
49 30 : }
50 2 : void AddOneStatDumpTaskV2(uint8_t* sqeIn, KfcDumpOpInitParam* dumpParam, KfcDumpContext* dumpContext)
51 : {
52 2 : hwts_kernel_sqe_t sqe = {};
53 2 : sqe.type = static_cast<uint16_t>(KfcDumpTaskType::AIVECTOR_TASK);
54 2 : sqe.graph_lock = 0;
55 2 : sqe.graph_unlock = 0;
56 2 : sqe.ie = 0;
57 2 : sqe.pre_p = 0;
58 2 : sqe.post_p = 0;
59 2 : sqe.wr_cqe = 0;
60 2 : sqe.rd_cond = 0;
61 2 : sqe.l2_lock = 0;
62 2 : sqe.l2_unlock = 0;
63 2 : sqe.block_dim = dumpContext->aiCoreNum;
64 2 : sqe.rt_stream_id = static_cast<uint16_t>(dumpParam->streamInfo.streamIds);
65 2 : sqe.task_id = 0;
66 2 : uint64_t pcAddr = dumpParam->config.dumpStatPcAddr;
67 2 : sqe.pc_addr_low = static_cast<uint32_t>(pcAddr & LOW_ADDR_MASK);
68 2 : sqe.pc_addr_high = static_cast<uint16_t>((pcAddr & HIGH_ADDR_MASK) >> TS_UINT32_BIT_NUM);
69 2 : sqe.kernel_credit = KERNEL_TIMEOUT_CONSTANT;
70 2 : AddOneStatDumpTaskV2Part2(sqe, dumpContext);
71 2 : (void)memcpy_s(sqeIn, AC_SQE_SIZE, &sqe, AC_SQE_SIZE);
72 2 : }
73 2 : void AddOneStatDumpTaskV2Part2(hwts_kernel_sqe_t& sqe, KfcDumpContext* dumpContext)
74 : {
75 2 : sqe.res0 = 0;
76 2 : sqe.prefetch_cnt = 1;
77 2 : auto paramAddr = reinterpret_cast<uint64_t>(dumpContext);
78 2 : sqe.param_addr_low = static_cast<uint32_t>(paramAddr & LOW_ADDR_MASK);
79 2 : sqe.param_addr_high = static_cast<uint32_t>(paramAddr >> TS_UINT32_BIT_NUM);
80 2 : sqe.l2_in_main = MAX_L2_MAIN_CACHE;
81 2 : sqe.res1 = 0;
82 2 : sqe.literal_addr_low = 0;
83 2 : sqe.literal_addr_high = 0;
84 2 : sqe.res2 = 0;
85 2 : sqe.literal_base_ub = 0;
86 2 : sqe.literal_buff_len = 0;
87 2 : sqe.sta_mode = 0;
88 2 : sqe.res3 = 0;
89 2 : sqe.res4 = 0;
90 2 : sqe.res5 = 0;
91 2 : sqe.p_l2ctrl_low = 0;
92 2 : sqe.p_l2ctrl_high = 0;
93 2 : sqe.res6 = 0;
94 2 : sqe.res7 = 0;
95 2 : }
96 :
97 2 : void AddStatDumpTaskCloudV4(uint8_t* sqeIn, KfcDumpOpInitParam* dumpParam, KfcDumpContext* dumpContext)
98 : {
99 2 : rtDavidStarsAicAivSqeCloudV4* sqe = reinterpret_cast<rtDavidStarsAicAivSqeCloudV4*>(sqeIn);
100 2 : sqe->header.type = 1U; // AIV
101 2 : sqe->header.blockDim = dumpContext->aiCoreNum;
102 2 : sqe->header.rtStreamId = dumpParam->streamInfo.streamIds;
103 : // blockDim小于2,groupDim指定为1,否则groupBlockdim为0不合法
104 2 : sqe->groupDim = (sqe->header.blockDim < GROUP_DIM_DEFAULT) ? 1U : GROUP_DIM_DEFAULT;
105 2 : sqe->groupBlockDim = sqe->header.blockDim / sqe->groupDim;
106 2 : sqe->kernelCredit = KERNEL_TIMEOUT_CONSTANT; // max 254
107 2 : sqe->stackPhyBaseLow = static_cast<uint32_t>(dumpParam->kfcWorkSpace.stackPhyBase32k & LOW_ADDR_MASK);
108 2 : sqe->stackPhyBaseHigh = static_cast<uint32_t>(dumpParam->kfcWorkSpace.stackPhyBase32k >> TS_UINT32_BIT_NUM);
109 2 : sqe->tail.aivNs = 1U;
110 2 : sqe->tail.aivWrrRd = 2U;
111 2 : sqe->tail.aivWrrWr = 2U;
112 2 : sqe->tail.ratio = 1U;
113 2 : sqe->tail.schem = 1U;
114 2 : uint64_t pcAddr = dumpParam->config.dumpStatPcAddr;
115 2 : sqe->tail.aivStartPcLow = static_cast<uint32_t>(pcAddr & LOW_ADDR_MASK);
116 2 : sqe->tail.aivStartPcHigh = static_cast<uint16_t>((pcAddr & HIGH_ADDR_MASK) >> TS_UINT32_BIT_NUM);
117 2 : uint64_t paramAddr = reinterpret_cast<uint64_t>(dumpContext);
118 2 : sqe->tail.aivTaskParamPtrLow = static_cast<uint32_t>(paramAddr & LOW_ADDR_MASK);
119 2 : sqe->tail.aivTaskParamPtrHigh = static_cast<uint32_t>(paramAddr >> TS_UINT32_BIT_NUM);
120 2 : }
121 :
122 4 : void AddStatDumpTaskCloudV5(uint8_t* sqeIn, KfcDumpOpInitParam* dumpParam, KfcDumpContext* dumpContext)
123 : {
124 4 : rtDavidStarsAicAivSqeCloudV5* sqe = reinterpret_cast<rtDavidStarsAicAivSqeCloudV5*>(sqeIn);
125 :
126 4 : sqe->header.type = 1U; // RT_DAVID_SQE_TYPE_AIV
127 4 : sqe->header.blockDim = dumpContext->aiCoreNum;
128 4 : sqe->header.rtStreamId = dumpParam->streamInfo.streamIds;
129 : // blockDim小于2,groupDim指定为1,否则groupBlockdim为0不合法
130 4 : sqe->groupDim = (sqe->header.blockDim < GROUP_DIM_DEFAULT) ? 1U : GROUP_DIM_DEFAULT;
131 4 : sqe->groupBlockdim = sqe->header.blockDim / sqe->groupDim;
132 4 : sqe->kernelCredit = KERNEL_TIMEOUT_CONSTANT; // max 254
133 4 : sqe->aicPreAllocateDisable = 1U;
134 4 : sqe->aivPreAllocateDisable = 0U;
135 4 : sqe->tail.aivNs = 1U;
136 4 : sqe->tail.aivWrrRd = 2U; // RT_DAVID_AIV_WRR_RD
137 4 : sqe->tail.aivWrrWr = 2U; // RT_DAVID_AIV_WRR_WR
138 4 : sqe->tail.schem = 1U; // RT_SCHEM_MODE_NORMAL
139 4 : sqe->tail.ratio = 1U; // only ratio is 1
140 :
141 4 : uint64_t pcAddr = dumpParam->config.dumpStatPcAddr;
142 4 : sqe->tail.aivStartPcLow = static_cast<uint32_t>(pcAddr & LOW_ADDR_MASK);
143 4 : sqe->tail.aivStartPcHigh = static_cast<uint16_t>((pcAddr & HIGH_ADDR_MASK) >> TS_UINT32_BIT_NUM);
144 4 : uint64_t paramAddr = reinterpret_cast<uint64_t>(dumpContext);
145 4 : sqe->tail.aivTaskParamPtrLow = static_cast<uint32_t>(paramAddr & LOW_ADDR_MASK);
146 4 : sqe->tail.aivTaskParamPtrHigh = static_cast<uint32_t>(paramAddr >> TS_UINT32_BIT_NUM);
147 4 : }
148 :
149 41 : KfcDumpResult KfcDumpTaskDispatcher::QuerySqBaseAddr(uint32_t devId, uint32_t sqId, uint64_t& outVal)
150 : {
151 41 : halSqCqQueryInfo queryInfo = {};
152 41 : queryInfo.tsId = 0;
153 41 : queryInfo.sqId = sqId;
154 41 : queryInfo.cqId = 0;
155 41 : queryInfo.type = DRV_NORMAL_TYPE;
156 41 : queryInfo.prop = DRV_SQCQ_PROP_SQ_BASE;
157 41 : uint32_t ret = halSqCqQuery(devId, &queryInfo);
158 41 : if (ret != 0) {
159 1 : IDE_LOGE("Failed to query sq base address, ret[%u] sqId[%u]", ret, queryInfo.sqId);
160 1 : return KFC_DUMP_E_DRIVE;
161 : }
162 40 : outVal = ((static_cast<uint64_t>(queryInfo.value[1])) << TS_UINT32_BIT_NUM) | queryInfo.value[0];
163 40 : return KFC_DUMP_SUCCESS;
164 : }
165 :
166 27053550 : KfcDumpResult KfcDumpTaskDispatcher::QuerySqStatusByType(
167 : int32_t devId, uint32_t sqId, drvSqCqPropType_t type, uint32_t& outVal)
168 : {
169 27053550 : halSqCqQueryInfo queryInfo = {};
170 27053550 : queryInfo.tsId = 0;
171 27053550 : queryInfo.sqId = sqId;
172 27053550 : queryInfo.cqId = 0;
173 27053550 : queryInfo.type = DRV_NORMAL_TYPE;
174 27053550 : queryInfo.prop = type;
175 27053550 : uint32_t ret = halSqCqQuery(devId, &queryInfo);
176 27053550 : if (ret != 0) {
177 3 : IDE_LOGE("Failed to query sq property[%d], ret[%u] sqId[%u]", type, ret, queryInfo.sqId);
178 3 : return KFC_DUMP_E_DRIVE;
179 : }
180 27053547 : outVal = queryInfo.value[0];
181 27053547 : return KFC_DUMP_SUCCESS;
182 : }
183 :
184 31 : KfcDumpResult KfcDumpTaskDispatcher::ConfigSqStatusByType(
185 : int32_t devId, uint32_t sqId, drvSqCqPropType_t type, uint32_t value)
186 : {
187 31 : halSqCqConfigInfo configInfo = {};
188 31 : configInfo.tsId = 0;
189 31 : configInfo.sqId = sqId;
190 31 : configInfo.cqId = 0;
191 31 : configInfo.type = DRV_NORMAL_TYPE;
192 31 : configInfo.prop = type;
193 31 : configInfo.value[0] = value;
194 31 : uint32_t ret = halSqCqConfig(devId, &configInfo);
195 31 : if (ret != 0) {
196 1 : IDE_LOGE("Failed to config sq property[%d] to value[%u], ret[%u] sqId[%u]", type, value, ret, configInfo.sqId);
197 1 : return KFC_DUMP_E_DRIVE;
198 : }
199 30 : return KFC_DUMP_SUCCESS;
200 : }
201 :
202 27053436 : static inline uint32_t GetUsedSqSlotNum(uint32_t head, uint32_t tail, uint32_t sqDepth)
203 : {
204 27053436 : return (tail < head ? sqDepth : 0U) + tail - head;
205 : }
206 :
207 27053436 : static inline bool IsSqFull(uint32_t head, uint32_t tail, uint32_t sqDepth)
208 : {
209 27053436 : return GetUsedSqSlotNum(head, tail, sqDepth) + 1U >= sqDepth;
210 : }
211 :
212 32 : KfcDumpResult KfcDumpTaskDispatcher::LaunchTask(uint8_t* sqeAddr, KfcDumpStreamCtx* kfcDumpStreamInfo)
213 : {
214 32 : uint32_t& head = kfcDumpStreamInfo->sqHead;
215 32 : uint32_t& tail = kfcDumpStreamInfo->sqTail;
216 32 : const uint32_t sqDepth = kfcDumpStreamInfo->sqDepth;
217 32 : uint32_t newTail = (tail + 1) % sqDepth;
218 32 : IDE_LOGI(
219 : "Launch kfc dump statistics operator: sqId[%u] sqHead[%u] sqTail[%u] newSqTail[%u]", kfcDumpStreamInfo->sqId,
220 : head, tail, newTail);
221 32 : uint64_t startLaunchTime = GetCurCpuTimestamp();
222 27053436 : while (IsSqFull(head, tail, sqDepth)) {
223 27053405 : DUMP_STATS_CHK_RET(
224 : QuerySqStatusByType(kfcDumpStreamInfo->devId, kfcDumpStreamInfo->sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
225 :
226 27053405 : if (CheckTimeOut(startLaunchTime) != KFC_DUMP_SUCCESS) {
227 1 : IDE_LOGE(
228 : "Wait for free sq slot timeout, sqId[%u] sqHead[%u] sqTail[%u] sqDepth[%u]", kfcDumpStreamInfo->sqId,
229 : head, tail, sqDepth);
230 1 : return KFC_DUMP_E_TIMEOUT;
231 : }
232 : }
233 62 : errno_t ret = memcpy_s(
234 31 : reinterpret_cast<uint8_t*>(kfcDumpStreamInfo->sqBaseAddr) + tail * AC_SQE_SIZE, AC_SQE_SIZE, sqeAddr,
235 : AC_SQE_SIZE);
236 31 : if (ret != EOK) {
237 0 : IDE_LOGE("Failed to write sqe into sq, sqTail[%u] ret[%d]", tail, ret);
238 0 : return KFC_DUMP_E_MEMORY;
239 : }
240 31 : DUMP_STATS_CHK_RET(
241 : ConfigSqStatusByType(kfcDumpStreamInfo->devId, kfcDumpStreamInfo->sqId, DRV_SQCQ_PROP_SQ_TAIL, newTail));
242 30 : tail = newTail;
243 30 : return KFC_DUMP_SUCCESS;
244 : }
245 : } // namespace kfc_dump_stats
|