• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2021 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <map>
17 #include <functional>
18 #include <numeric>
19 #include "common/kernel_base.h"
20 #include "common/kernel_errcode.h"
21 #include "common/tensor.h"
22 
23 namespace aicpu {
24 namespace {
25 // max param len limit 10k.
26 constexpr uint32_t MAX_PARAM_LEN = 10240;
27 // max io address num limit 1024
28 constexpr uint32_t MAX_IO_ADDR_NUMPARAM_LEN = 1024;
29 }  // namespace
30 
31 static const std::map<const ::aicpuops::DataType, size_t> kKernelBaseDataTypeSize = {
32   {aicpuops::MS_BOOL, sizeof(bool)},           {aicpuops::MS_INT8, sizeof(int8_t)},
33   {aicpuops::MS_UINT8, sizeof(uint8_t)},       {aicpuops::MS_INT16, sizeof(int16_t)},
34   {aicpuops::MS_UINT16, sizeof(uint16_t)},     {aicpuops::MS_INT32, sizeof(int32_t)},
35   {aicpuops::MS_UINT32, sizeof(uint32_t)},     {aicpuops::MS_INT64, sizeof(int64_t)},
36   {aicpuops::MS_UINT64, sizeof(uint64_t)},     {aicpuops::MS_FLOAT16, sizeof(float) / 2},
37   {aicpuops::MS_FLOAT32, sizeof(float)},       {aicpuops::MS_FLOAT64, sizeof(double)},
38   {aicpuops::MS_COMPLEX64, sizeof(float) * 2}, {aicpuops::MS_COMPLEX128, sizeof(double) * 2}};
39 
KernelBase(const std::string & kernel_name)40 KernelBase::KernelBase(const std::string &kernel_name)
41     : kernel_name_(kernel_name),
42       extend_param_len_(0),
43       extend_param_base_(nullptr),
44       param_head_(nullptr),
45       unknow_shape_(false) {}
46 
ParseParam(void * param)47 uint32_t KernelBase::ParseParam(void *param) {
48   if (param == nullptr) {
49     AICPU_LOGE("Kernel:%s ParseParam param is null.", kernel_name_.c_str());
50     return kAicpuKernelStateInvalid;
51   }
52 
53   // parse param_len
54   param_head_ = static_cast<AicpuParamHead *>(param);
55   if (param_head_->length < sizeof(AicpuParamHead) || param_head_->length > MAX_PARAM_LEN) {
56     AICPU_LOGE("Kernel:%s param length=%u not in [%zu, %u].", kernel_name_.c_str(), param_head_->length,
57                sizeof(AicpuParamHead), MAX_PARAM_LEN);
58     return kAicpuKernelStateInvalid;
59   }
60 
61   auto param_base = static_cast<uint8_t *>(param);
62   extend_param_base_ = param_base + sizeof(AicpuParamHead);
63   extend_param_len_ = param_head_->length - sizeof(AicpuParamHead);
64 
65   if (param_head_->ioAddrNum > 0) {
66     if (param_head_->ioAddrNum > MAX_IO_ADDR_NUMPARAM_LEN) {
67       AICPU_LOGE("Kernel:%s param ioAddrNum=%u is over %u.", kernel_name_.c_str(), param_head_->ioAddrNum,
68                  MAX_IO_ADDR_NUMPARAM_LEN);
69       return kAicpuKernelStateInvalid;
70     }
71     uint32_t addr_len = static_cast<uint32_t>(param_head_->ioAddrNum * sizeof(uint64_t));
72     if (extend_param_len_ < addr_len) {
73       AICPU_LOGE("Kernel:%s extend param is not enough for io addr, ioAddrNum=%u, extendParamLen=%u.",
74                  kernel_name_.c_str(), param_head_->ioAddrNum, extend_param_len_);
75       return kAicpuKernelStateInvalid;
76     }
77     auto io_addr_base = reinterpret_cast<uint64_t *>(extend_param_base_);
78     for (uint32_t i = 0; i < param_head_->ioAddrNum; ++i) {
79       io_addrs_.push_back(static_cast<uintptr_t>(io_addr_base[i]));
80     }
81     extend_param_base_ = extend_param_base_ + addr_len;
82     extend_param_len_ -= addr_len;
83   }
84   AICPU_CHK_STATUS_RET(ParseNodeDef())
85   AICPU_CHK_STATUS_RET(ParseExtInfo())
86   if (unknow_shape_) {
87     AICPU_LOGI("Unknown shape op: %s", kernel_name_.c_str());
88     UpdateInputShape();
89     UpdateOutputShape();
90   }
91   return ParseKernelParam();
92 }
93 
Compute(void * param)94 uint32_t KernelBase::Compute(void *param) {
95   uint32_t ret = ParseParam(param);
96   if (ret != kAicpuKernelStateSucess) {
97     AICPU_LOGE("Kernel:%s ParseParam failed, ret=%u.", kernel_name_.c_str(), ret);
98     return ret;
99   }
100   return DoCompute();
101 }
102 
GetDataTypeSize(::aicpuops::DataType data_type) const103 size_t KernelBase::GetDataTypeSize(::aicpuops::DataType data_type) const {
104   auto it = kKernelBaseDataTypeSize.find(data_type);
105   if (it == kKernelBaseDataTypeSize.end()) {
106     AICPU_LOGE("don't support input tensor types");
107     return 0;
108   }
109   return it->second;
110 }
111 
GetTensorMemSizeByShape(const::aicpuops::Tensor & tensor)112 size_t KernelBase::GetTensorMemSizeByShape(const ::aicpuops::Tensor &tensor) {
113   std::vector<int64_t> shape;
114   auto tensor_shape = tensor.tensor_shape();
115   for (int i = 0; i < tensor_shape.dim_size(); ++i) {
116     shape.push_back(tensor_shape.dim(i).size());
117   }
118   auto data_type = static_cast<aicpuops::DataType>(tensor.tensor_type());
119   int64_t element_num = std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<int64_t>());
120   return LongToSize(element_num) * GetDataTypeSize(data_type);
121 }
122 
123 template <typename T>
ParseExtendParam(T * param_var,const std::string & param_name)124 uint32_t KernelBase::ParseExtendParam(T *param_var, const std::string &param_name) {
125   if (extend_param_len_ < sizeof(T)) {
126     AICPU_LOGE("Kernel:%s extend param is not enough for [%s] addr, need_len=%u, extendParamLen=%u.",
127                kernel_name_.c_str(), param_name.c_str(), sizeof(T), extend_param_len_);
128     return kAicpuKernelStateInvalid;
129   }
130   T *param = reinterpret_cast<T *>(extend_param_base_);
131   if (param != nullptr) {
132     *param_var = *param;
133     extend_param_base_ += sizeof(T);
134     extend_param_len_ -= sizeof(T);
135     return kAicpuKernelStateSucess;
136   }
137   AICPU_LOGE("Kernel:%s extend param for [%s] addr is invalid.", kernel_name_.c_str(), param_name.c_str());
138   return kAicpuKernelStateInvalid;
139 }
140 
ParseNodeDef()141 uint32_t KernelBase::ParseNodeDef() {
142   uint32_t node_def_len;
143   AICPU_CHK_STATUS_RET(ParseExtendParam(&node_def_len, "node_def_len"))
144 
145   if (extend_param_len_ < node_def_len) {
146     AICPU_LOGE("Kernel:%s extend param is not enough for customizeAttr addr, node_def_len=%u, extendParamLen=%u.",
147                kernel_name_.c_str(), node_def_len, extend_param_len_);
148     return kAicpuKernelStateInvalid;
149   }
150   std::string std_data(reinterpret_cast<char *>(extend_param_base_), node_def_len);
151   if (!node_def_.ParseFromString(std_data)) {
152     AICPU_LOGE("parse %s KernelBase proto failed, nodeDef=%s.", kernel_name_.c_str(), std_data.c_str());
153     return kAicpuKernelStateInvalid;
154   }
155   extend_param_base_ += node_def_len;
156   extend_param_len_ -= node_def_len;
157   return kAicpuKernelStateSucess;
158 }
159 
ParseExtShapeType(FWKAdapter::ExtInfo * ext_info)160 uint32_t KernelBase::ParseExtShapeType(FWKAdapter::ExtInfo *ext_info) {
161   if (ext_info->infoLen != sizeof(int32_t)) {
162     AICPU_LOGE("Kernel:%s parse ext shape type failed as infoLen must be %zu but %u.", kernel_name_.c_str(),
163                sizeof(int32_t), ext_info->infoLen);
164     return kAicpuKernelStateInvalid;
165   }
166   unknow_shape_ = true;
167   return kAicpuKernelStateSucess;
168 }
169 
ParseExtInputShape(FWKAdapter::ExtInfo * ext_info)170 uint32_t KernelBase::ParseExtInputShape(FWKAdapter::ExtInfo *ext_info) {
171   // no overflow
172   auto need_len = node_def_.inputs_size() * sizeof(FWKAdapter::ShapeAndType);
173   if (ext_info->infoLen != need_len) {
174     AICPU_LOGE(
175       "Kernel:%s parse ext input shape failed as infoLen must be "
176       "input_num[%d]*sizeof(ShapeAndType)[%zu], but %u.",
177       kernel_name_.c_str(), node_def_.inputs_size(), sizeof(FWKAdapter::ShapeAndType), ext_info->infoLen);
178     return kAicpuKernelStateInvalid;
179   }
180   input_shape_and_type_.clear();
181   auto input = reinterpret_cast<FWKAdapter::ShapeAndType *>(ext_info->infoMsg);
182   for (int index = 0; index < node_def_.inputs_size(); ++index) {
183     (void)input_shape_and_type_.emplace_back(&input[index]);
184   }
185   return kAicpuKernelStateSucess;
186 }
187 
ParseExtOutputShape(FWKAdapter::ExtInfo * ext_info)188 uint32_t KernelBase::ParseExtOutputShape(FWKAdapter::ExtInfo *ext_info) {
189   // no overflow
190   auto need_len = node_def_.outputs_size() * sizeof(FWKAdapter::ShapeAndType);
191   if (ext_info->infoLen != need_len) {
192     AICPU_LOGE(
193       "Kernel:%s parse ext output shape failed as infoLen must be "
194       "output_num[%d]*sizeof(ShapeAndType)[%zu], but %u.",
195       kernel_name_.c_str(), node_def_.outputs_size(), sizeof(FWKAdapter::ShapeAndType), ext_info->infoLen);
196     return kAicpuKernelStateInvalid;
197   }
198   output_shape_and_type_.clear();
199   auto output = reinterpret_cast<FWKAdapter::ShapeAndType *>(ext_info->infoMsg);
200   for (int index = 0; index < node_def_.outputs_size(); ++index) {
201     (void)output_shape_and_type_.emplace_back(&output[index]);
202   }
203   return kAicpuKernelStateSucess;
204 }
205 
ParseExtInfo()206 uint32_t KernelBase::ParseExtInfo() {
207   uint32_t offset = 0;
208   FWKAdapter::ExtInfo *ext_info_ptr = nullptr;
209   char *ext_info_buf = reinterpret_cast<char *>(static_cast<uintptr_t>(param_head_->extInfoAddr));
210   while (offset + sizeof(FWKAdapter::ExtInfo) <= param_head_->extInfoLength) {
211     ext_info_ptr = reinterpret_cast<FWKAdapter::ExtInfo *>(ext_info_buf + offset);
212     if (ext_info_ptr == nullptr) {
213       AICPU_LOGE("Kernel:%s ext_info is nullptr, extInfoLength=%u, extInfoAddr=%p, offset=%zu.", kernel_name_.c_str(),
214                  param_head_->extInfoLength, param_head_->extInfoAddr, offset);
215       return kAicpuKernelStateInvalid;
216     }
217     switch (ext_info_ptr->infoType) {
218       case FWKAdapter::FWK_ADPT_EXT_SHAPE_TYPE:
219         AICPU_CHK_STATUS_RET(ParseExtShapeType(ext_info_ptr))
220         break;
221       case FWKAdapter::FWK_ADPT_EXT_INPUT_SHAPE:
222         AICPU_CHK_STATUS_RET(ParseExtInputShape(ext_info_ptr))
223         break;
224       case FWKAdapter::FWK_ADPT_EXT_OUTPUT_SHAPE:
225         AICPU_CHK_STATUS_RET(ParseExtOutputShape(ext_info_ptr))
226         break;
227       default:
228         AICPU_LOGI("Kernel:%s ignore infoType=%d, infoLen=%u.", kernel_name_.c_str(), ext_info_ptr->infoType,
229                    ext_info_ptr->infoLen);
230         break;
231     }
232     // not overflow
233     offset += FWKAdapter::kExtInfoHeadSize;
234     offset += ext_info_ptr->infoLen;
235   }
236   return kAicpuKernelStateSucess;
237 }
238 
UpdateInputShape()239 void KernelBase::UpdateInputShape() {
240   for (int i = 0; i < node_def_.inputs_size(); ++i) {
241     aicpuops::Tensor *input_tensor = node_def_.mutable_inputs(i);
242     aicpuops::TensorShape *input_tensor_shape = input_tensor->mutable_tensor_shape();
243     input_tensor_shape->clear_dim();
244     for (uint32_t index = 0; index < FWKAdapter::kMaxShapeDims; ++index) {
245       // LLONG_MIN for dim end flag
246       if (input_shape_and_type_[i]->dims[index] == LLONG_MIN) {
247         break;
248       }
249       input_tensor_shape->add_dim()->set_size(input_shape_and_type_[IntToSize(i)]->dims[index]);
250     }
251   }
252 }
253 
UpdateOutputShape()254 void KernelBase::UpdateOutputShape() {
255   for (int i = 0; i < node_def_.outputs_size(); ++i) {
256     aicpuops::Tensor *output_tensor = node_def_.mutable_outputs(i);
257     aicpuops::TensorShape *output_tensor_shape = output_tensor->mutable_tensor_shape();
258     output_tensor_shape->clear_dim();
259     for (uint32_t index = 0; index < FWKAdapter::kMaxShapeDims; ++index) {
260       // LLONG_MIN for dim end flag
261       if (output_shape_and_type_[i]->dims[index] == LLONG_MIN) {
262         break;
263       }
264       output_tensor_shape->add_dim()->set_size(output_shape_and_type_[i]->dims[index]);
265     }
266   }
267 }
268 }  // namespace aicpu
269