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 : /*!
12 : * \file kernel_vec_proposal_check.cpp
13 : * \brief
14 : */
15 :
16 : #include "kernel_check_params.h"
17 : #include "kernel_vec_proposal_check.h"
18 :
19 : namespace AscendC {
20 : namespace check {
21 : const uint32_t ONE_REPEAT_CAL_NUM = 16; // 1 repeat = 16 region proposals
22 : const uint32_t PROPOSAL_SIZE = 8; // 1 proposal = 8 element
23 :
24 56 : bool TikcppVecProposalCheck::CheckAddrAlign(const std::string& src0Name)
25 : {
26 56 : uint8_t alignByte = ONE_BLK_SIZE;
27 56 : bool dstRes = true;
28 56 : bool src0Res = true;
29 56 : if (apiName == "MrgSort") {
30 4 : alignByte = 8; // half and float type align Bytes is 8B
31 8 : dstRes = CheckTensorAddrAlign(param_.dstAddr, param_.dstPos, ONE_BLK_SIZE, "dst");
32 4 : src0Res = CheckTensorAddrAlign(param_.src0Addr, param_.src0Pos, alignByte, src0Name);
33 4 : return dstRes && src0Res;
34 : }
35 52 : if (apiName == "MrgSort4" && param_.dstDtypeBytes == sizeof(half)) {
36 0 : alignByte = 16; // half type align Bytes is 16B
37 : }
38 104 : dstRes = CheckTensorAddrAlign(param_.dstAddr, param_.dstPos, alignByte, "dst");
39 52 : src0Res = CheckTensorAddrAlign(param_.src0Addr, param_.src0Pos, alignByte, src0Name);
40 52 : return dstRes && src0Res;
41 : }
42 :
43 : // validBit to num of proposal lists: 3->2, 7->3, 15->4
44 12 : uint8_t TikcppVecProposalCheck::CountBit(uint16_t validBit) const
45 : {
46 12 : uint8_t count = 0;
47 60 : while (validBit != 0) {
48 48 : count += (validBit & 0x1);
49 48 : validBit >>= 1;
50 : }
51 12 : return count;
52 : }
53 :
54 12 : bool TikcppVecProposalCheck::CheckValidBit(uint16_t validBit) const
55 : {
56 12 : bool validBitRes = validBit == 3 || validBit == 7 || validBit == 15;
57 12 : ASCENDC_CHECK_AND_LOG((validBitRes), {
58 : CHECK_LOG_ERROR(
59 : "Failed to check validBit value in %s, its valid value is "
60 : "[3, 7, 15], current value is %u.",
61 : apiName.c_str(), validBit);
62 : });
63 12 : return true;
64 : }
65 :
66 : // calculate total elements that needs to be sorted per repeatTimes. (1 proposal -> 1 element)
67 12 : uint64_t TikcppVecProposalCheck::CalSortElemPerRep(uint16_t elementLengths[4], uint8_t count) const
68 : {
69 12 : uint64_t elePerRep = 0;
70 60 : for (uint8_t i = 0; i < count; ++i) {
71 48 : elePerRep += elementLengths[i];
72 : }
73 12 : return elePerRep;
74 : }
75 :
76 12 : bool TikcppVecProposalCheck::NeedRepeatTimes() const
77 : {
78 : // 1. 4 region proposals has same lengths
79 36 : bool cond1 = (param_.elementLengths[0] == param_.elementLengths[1]) &&
80 24 : (param_.elementLengths[1] == param_.elementLengths[2]) &&
81 12 : (param_.elementLengths[2] == param_.elementLengths[3]);
82 : // 2. continuous stored 3. ifExhaused = false 4. validBit = 15
83 12 : return cond1 && param_.isContinuous && (!param_.isExhausted) && (param_.validBit == 15);
84 : }
85 :
86 12 : bool TikcppVecProposalCheck::Vbs16Check() const
87 : {
88 : // 1 repeat = 16 proposals, 1 proposals = 8 * element. Data are continuously stored.
89 12 : uint64_t calCount = param_.repeatTimes * ONE_REPEAT_CAL_NUM * PROPOSAL_SIZE;
90 36 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, calCount, "dstLocal"));
91 24 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, calCount, "srcLocal"));
92 4 : return true;
93 : }
94 :
95 12 : bool TikcppVecProposalCheck::Vbs32Check() const
96 : {
97 36 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
98 : param_.src1Size, GlobalParams::Instance().bufferSizeMap.at(param_.src1Pos),
99 : "check src1 tensor buffersize failed"));
100 :
101 12 : if (param_.dstDtypeBytes == 0) {
102 0 : CHECK_LOG_ERROR("dst dtype bytes is zero");
103 0 : return false;
104 : }
105 : // In 1 repeat, dst: 256B src0: 32 * element src1: 32 element
106 12 : const uint32_t oneCalNumVbs32 = 32; // 1 repeat calculates 32 groups of (score + index)
107 12 : uint32_t elemPerRepeat = ONE_REPEAT_BYTE_SIZE / param_.dstDtypeBytes;
108 36 : ASCENDC_CHECK(
109 : CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, elemPerRepeat * param_.repeatTimes, "dstLocal"));
110 24 : ASCENDC_CHECK(CheckTensorOverflowHigh(
111 : param_.src0DtypeBytes, param_.src0Size, oneCalNumVbs32 * param_.repeatTimes, "src0Local"));
112 12 : ASCENDC_CHECK(CheckTensorOverflowHigh(
113 : param_.src1DtypeBytes, param_.src1Size, oneCalNumVbs32 * param_.repeatTimes, "src1Local"));
114 4 : return true;
115 : }
116 :
117 8 : bool TikcppVecProposalCheck::Vms4Check() const
118 : {
119 8 : ASCENDC_CHECK(CheckValidBit(param_.validBit));
120 8 : uint8_t count = CountBit(param_.validBit);
121 8 : if (param_.srcIndex >= count) {
122 0 : return true; // if current list index is large than valid list number, no need to check
123 : }
124 :
125 8 : uint64_t sortElePerRep = CalSortElemPerRep(param_.elementLengths, count);
126 8 : uint64_t elemPerRep = sortElePerRep * PROPOSAL_SIZE; // 1 sort element = 1 proposal = 8 elements
127 8 : uint64_t validRepeatTimes = 1;
128 8 : if (NeedRepeatTimes()) {
129 0 : validRepeatTimes = param_.repeatTimes;
130 0 : ASCENDC_CHECK_VALUE_RANGE(validRepeatTimes, 1, MAX_REPEAT_TIMES, "repeatTimes", "MrgSort4");
131 : }
132 : // if exhausted, do not know total size. Thus no check
133 8 : if (!param_.isExhausted) {
134 24 : ASCENDC_CHECK(
135 : CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, elemPerRep * param_.repeatTimes, "dstLocal"));
136 : }
137 4 : std::string tensorName = "src" + std::to_string(param_.srcIndex) + " in srcLocal";
138 4 : uint64_t srcEle = (validRepeatTimes - 1) * elemPerRep + param_.elementLengths[param_.srcIndex] * PROPOSAL_SIZE;
139 4 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, srcEle, tensorName));
140 4 : return true;
141 4 : }
142 :
143 4 : bool TikcppVecProposalCheck::Vms4v2Check() const
144 : {
145 4 : ASCENDC_CHECK(CheckValidBit(param_.validBit));
146 4 : uint8_t count = CountBit(param_.validBit);
147 4 : if (param_.srcIndex >= count) {
148 0 : return true; // if current list index is large than valid list number, no need to check
149 : }
150 :
151 4 : uint64_t sortElePerRep = CalSortElemPerRep(param_.elementLengths, count);
152 4 : uint64_t bytePerRep = sortElePerRep * PROPOSAL_SIZE; // 1 sorted element = 8 Byte
153 4 : uint64_t validRepeatTimes = 1;
154 4 : if (NeedRepeatTimes()) {
155 0 : validRepeatTimes = param_.repeatTimes;
156 0 : ASCENDC_CHECK_VALUE_RANGE(validRepeatTimes, 1, MAX_REPEAT_TIMES, "repeatTimes", "MrgSort");
157 : }
158 : // if exhausted, do not know total size. Thus no check
159 4 : if (!param_.isExhausted) {
160 12 : ASCENDC_CHECK(CheckTensorOverflowHigh(1, param_.dstSize, bytePerRep * param_.repeatTimes, "dstLocal"));
161 : }
162 0 : std::string tensorName = "src" + std::to_string(param_.srcIndex) + " in srcLocal";
163 0 : uint64_t srcBytes = (validRepeatTimes - 1) * bytePerRep + param_.elementLengths[param_.srcIndex] * PROPOSAL_SIZE;
164 : // calcount is set as Bytes, thus set sizeof(dtype) to 1
165 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(1, param_.src0Size, srcBytes, tensorName));
166 0 : return true;
167 0 : }
168 :
169 12 : bool TikcppVecProposalCheck::VconcatCheck() const
170 : {
171 : // src: repeat * 16 element, dst: repeat * 16 region proposal (16 * 8 element) both continuously stored
172 12 : uint32_t base = param_.repeatTimes * ONE_REPEAT_CAL_NUM;
173 36 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, base, "srcLocal"));
174 36 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, base * PROPOSAL_SIZE, "dstLocal"));
175 8 : return true;
176 : }
177 :
178 8 : bool TikcppVecProposalCheck::VextractCheck() const
179 : {
180 : // src: repeat * 16 region proposal (16 * 8 element), dst: repeat * 16 element both continuously stored
181 8 : uint32_t base = param_.repeatTimes * ONE_REPEAT_CAL_NUM;
182 24 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, base * PROPOSAL_SIZE, "srcLocal"));
183 12 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, base, "dstLocal"));
184 4 : return true;
185 : }
186 :
187 0 : bool TikcppVecProposalCheck::ConcatCheck() const
188 : {
189 : // src: repeat * 16 element dst: V220 dst = src, V200: repeat * 16 region proposal (16 * 8 element)
190 0 : uint32_t base = param_.repeatTimes * ONE_REPEAT_CAL_NUM;
191 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, base, "srcLocal"));
192 : #if defined(__NPU_ARCH__) && ((__NPU_ARCH__ == 2201) || (__NPU_ARCH__ == 3002) || (__NPU_ARCH__ == 3102) || \
193 : (__NPU_ARCH__ == 3510) || (__NPU_ARCH__ == 5102))
194 : // tmpLocal is not used
195 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, base, "concatLocal"));
196 : #elif defined(__NPU_ARCH__) && ((__NPU_ARCH__ == 1001) || (__NPU_ARCH__ == 2002))
197 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src1DtypeBytes, param_.src1Size, base * PROPOSAL_SIZE, "tmpLocal"));
198 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, base * PROPOSAL_SIZE, "concatLocal"));
199 : #endif
200 0 : return true;
201 : }
202 :
203 0 : bool TikcppVecProposalCheck::ExtractCheck() const
204 : {
205 : // In extract: dst -> dstValueLocal, src1 -> dstIndexLocal, src0 -> sortedLocal
206 : #if defined(__NPU_ARCH__) && ((__NPU_ARCH__ == 2201) || (__NPU_ARCH__ == 3002) || (__NPU_ARCH__ == 3102) || \
207 : (__NPU_ARCH__ == 3510) || (__NPU_ARCH__ == 5102))
208 : // 1 repeat: 32 groups of (score + index) sortedLocal: 256B dst: 32 elements
209 0 : uint64_t groupNumPerRep = 32; // 1 sort result is 8 Bytes, thus 1 repeat = 32 groups
210 0 : uint64_t totalEleNum = groupNumPerRep * param_.repeatTimes;
211 0 : ASCENDC_CHECK(
212 : CheckTensorSizeOverflow(param_.repeatTimes * ONE_REPEAT_BYTE_SIZE, param_.src0Size, "sortedLocal", "Extract"));
213 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src1DtypeBytes, param_.src1Size, totalEleNum, "dstIndexLocal"));
214 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, totalEleNum, "dstValueLocal"));
215 : #elif defined(__NPU_ARCH__) && ((__NPU_ARCH__ == 1001) || (__NPU_ARCH__ == 2002))
216 : // 1 repeat: src: 16 region proposal dst: 16 elements
217 0 : uint32_t base = param_.repeatTimes * ONE_REPEAT_CAL_NUM;
218 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src0DtypeBytes, param_.src0Size, base * PROPOSAL_SIZE, "sortedLocal"));
219 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.src1DtypeBytes, param_.src1Size, base, "dstIndexLocal"));
220 0 : ASCENDC_CHECK(CheckTensorOverflowHigh(param_.dstDtypeBytes, param_.dstSize, base, "dstValueLocal"));
221 : #endif
222 0 : return true;
223 : }
224 :
225 80 : bool TikcppVecProposalCheck::CheckAllHighLevel()
226 : {
227 80 : const std::string supportPos = "VECIN/VECOUT/VECCALC";
228 240 : ASCENDC_CHECK(CheckTensorScope(param_.dstLogicPos, static_cast<uint8_t>(HardWareIndex::UB), "dst", supportPos));
229 56 : std::string src0Name = "src0";
230 56 : if (apiName == "MrgSort" || apiName == "MrgSort4") { // only has src1 ~ src4
231 12 : src0Name = "src" + std::to_string(param_.srcIndex) + " in srcLocal";
232 : }
233 56 : ASCENDC_CHECK(CheckTensorScope(param_.src0LogicPos, static_cast<uint8_t>(HardWareIndex::UB), src0Name, supportPos));
234 56 : if (apiName == "Sort32" || apiName == "Concat" || apiName == "Extract") {
235 36 : ASCENDC_CHECK(
236 : CheckTensorScope(param_.src1LogicPos, static_cast<uint8_t>(HardWareIndex::UB), "src1", supportPos));
237 36 : ASCENDC_CHECK(CheckTensorAddrAlign(param_.src1Addr, param_.src1Pos, ONE_BLK_SIZE, "src1"));
238 : }
239 :
240 56 : ASCENDC_CHECK(CheckAddrAlign(src0Name));
241 :
242 56 : std::string bufferSrc0 = "check " + src0Name + " tensor buffersize failed";
243 168 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
244 : param_.dstSize, GlobalParams::Instance().bufferSizeMap.at(param_.dstPos),
245 : "check dst tensor buffersize failed"));
246 56 : ASCENDC_CHECK(CheckBufferSizeOverFlow(
247 : param_.src0Size, GlobalParams::Instance().bufferSizeMap.at(param_.src0Pos), bufferSrc0));
248 :
249 56 : if (apiName == "Sort32") {
250 12 : return Vbs32Check();
251 44 : } else if (apiName == "ProposalConcat") {
252 12 : return VconcatCheck();
253 32 : } else if (apiName == "Concat") {
254 0 : return ConcatCheck();
255 32 : } else if (apiName == "ProposalExtract") {
256 8 : return VextractCheck();
257 24 : } else if (apiName == "Extract") {
258 0 : return ExtractCheck();
259 24 : } else if (apiName == "RpSort16") {
260 12 : return Vbs16Check();
261 12 : } else if (apiName == "MrgSort4") {
262 8 : return Vms4Check();
263 4 : } else if (apiName == "MrgSort") {
264 4 : return Vms4v2Check();
265 : }
266 0 : return true;
267 80 : }
268 : } // namespace check
269 : } // namespace AscendC
|