1 /* Copyright 2021 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 #ifndef TENSORFLOW_LITE_MICRO_MICRO_MUTABLE_OP_RESOLVER_H_ 16 #define TENSORFLOW_LITE_MICRO_MICRO_MUTABLE_OP_RESOLVER_H_ 17 18 #include <cstdio> 19 #include <cstring> 20 21 #include "tensorflow/lite/c/common.h" 22 #include "tensorflow/lite/core/api/error_reporter.h" 23 #include "tensorflow/lite/core/api/flatbuffer_conversions.h" 24 #include "tensorflow/lite/kernels/internal/compatibility.h" 25 #include "tensorflow/lite/kernels/op_macros.h" 26 #include "tensorflow/lite/micro/compatibility.h" 27 #include "tensorflow/lite/micro/kernels/conv.h" 28 #include "tensorflow/lite/micro/kernels/ethosu.h" 29 #include "tensorflow/lite/micro/kernels/fully_connected.h" 30 #include "tensorflow/lite/micro/kernels/micro_ops.h" 31 #include "tensorflow/lite/micro/kernels/softmax.h" 32 #include "tensorflow/lite/micro/micro_op_resolver.h" 33 #include "tensorflow/lite/schema/schema_generated.h" 34 35 namespace tflite { 36 TfLiteRegistration* Register_DETECTION_POSTPROCESS(); 37 38 template <unsigned int tOpCount> 39 class MicroMutableOpResolver : public MicroOpResolver { 40 public: 41 TF_LITE_REMOVE_VIRTUAL_DELETE 42 43 explicit MicroMutableOpResolver(ErrorReporter* error_reporter = nullptr) error_reporter_(error_reporter)44 : error_reporter_(error_reporter) {} 45 FindOp(tflite::BuiltinOperator op)46 const TfLiteRegistration* FindOp(tflite::BuiltinOperator op) const override { 47 if (op == BuiltinOperator_CUSTOM) return nullptr; 48 49 for (unsigned int i = 0; i < registrations_len_; ++i) { 50 const TfLiteRegistration& registration = registrations_[i]; 51 if (registration.builtin_code == op) { 52 return ®istration; 53 } 54 } 55 return nullptr; 56 } 57 FindOp(const char * op)58 const TfLiteRegistration* FindOp(const char* op) const override { 59 for (unsigned int i = 0; i < registrations_len_; ++i) { 60 const TfLiteRegistration& registration = registrations_[i]; 61 if ((registration.builtin_code == BuiltinOperator_CUSTOM) && 62 (strcmp(registration.custom_name, op) == 0)) { 63 return ®istration; 64 } 65 } 66 return nullptr; 67 } 68 GetOpDataParser(BuiltinOperator op)69 MicroOpResolver::BuiltinParseFunction GetOpDataParser( 70 BuiltinOperator op) const override { 71 TFLITE_DCHECK(num_buitin_ops_ <= tOpCount); 72 for (unsigned int i = 0; i < num_buitin_ops_; ++i) { 73 if (builtin_codes_[i] == op) return builtin_parsers_[i]; 74 } 75 return nullptr; 76 } 77 78 // Registers a Custom Operator with the MicroOpResolver. 79 // 80 // Only the first call for a given name will be successful. i.e. if this 81 // function is called again for a previously added Custom Operator, the 82 // MicroOpResolver will be unchanged and this function will return 83 // kTfLiteError. AddCustom(const char * name,TfLiteRegistration * registration)84 TfLiteStatus AddCustom(const char* name, TfLiteRegistration* registration) { 85 if (registrations_len_ >= tOpCount) { 86 if (error_reporter_) { 87 TF_LITE_REPORT_ERROR( 88 error_reporter_, 89 "Couldn't register custom op '%s', resolver size is too small (%d)", 90 name, tOpCount); 91 } 92 return kTfLiteError; 93 } 94 95 if (FindOp(name) != nullptr) { 96 if (error_reporter_ != nullptr) { 97 TF_LITE_REPORT_ERROR(error_reporter_, 98 "Calling AddCustom for the same op more than once " 99 "is not supported (Op: %s).", 100 name); 101 } 102 return kTfLiteError; 103 } 104 105 TfLiteRegistration* new_registration = ®istrations_[registrations_len_]; 106 registrations_len_ += 1; 107 108 *new_registration = *registration; 109 new_registration->builtin_code = BuiltinOperator_CUSTOM; 110 new_registration->custom_name = name; 111 return kTfLiteOk; 112 } 113 114 // The Add* functions below add the various Builtin operators to the 115 // MicroMutableOpResolver object. 116 AddAbs()117 TfLiteStatus AddAbs() { 118 return AddBuiltin(BuiltinOperator_ABS, tflite::ops::micro::Register_ABS(), 119 ParseAbs); 120 } 121 AddAdd()122 TfLiteStatus AddAdd() { 123 return AddBuiltin(BuiltinOperator_ADD, tflite::ops::micro::Register_ADD(), 124 ParseAdd); 125 } 126 AddAddN()127 TfLiteStatus AddAddN() { 128 return AddBuiltin(BuiltinOperator_ADD_N, tflite::Register_ADD_N(), 129 ParseAddN); 130 } 131 AddArgMax()132 TfLiteStatus AddArgMax() { 133 return AddBuiltin(BuiltinOperator_ARG_MAX, 134 tflite::ops::micro::Register_ARG_MAX(), ParseArgMax); 135 } 136 AddArgMin()137 TfLiteStatus AddArgMin() { 138 return AddBuiltin(BuiltinOperator_ARG_MIN, 139 tflite::ops::micro::Register_ARG_MIN(), ParseArgMin); 140 } 141 AddAveragePool2D()142 TfLiteStatus AddAveragePool2D() { 143 return AddBuiltin(BuiltinOperator_AVERAGE_POOL_2D, 144 tflite::Register_AVERAGE_POOL_2D(), ParsePool); 145 } 146 AddBatchToSpaceNd()147 TfLiteStatus AddBatchToSpaceNd() { 148 return AddBuiltin(BuiltinOperator_BATCH_TO_SPACE_ND, 149 Register_BATCH_TO_SPACE_ND(), ParseBatchToSpaceNd); 150 } 151 AddCast()152 TfLiteStatus AddCast() { 153 return AddBuiltin(BuiltinOperator_CAST, Register_CAST(), ParseCast); 154 } 155 AddCeil()156 TfLiteStatus AddCeil() { 157 return AddBuiltin(BuiltinOperator_CEIL, tflite::ops::micro::Register_CEIL(), 158 ParseCeil); 159 } 160 AddCircularBuffer()161 TfLiteStatus AddCircularBuffer() { 162 return AddCustom("CIRCULAR_BUFFER", 163 tflite::ops::micro::Register_CIRCULAR_BUFFER()); 164 } 165 AddConcatenation()166 TfLiteStatus AddConcatenation() { 167 return AddBuiltin(BuiltinOperator_CONCATENATION, 168 tflite::ops::micro::Register_CONCATENATION(), 169 ParseConcatenation); 170 } 171 172 TfLiteStatus AddConv2D( 173 const TfLiteRegistration& registration = Register_CONV_2D()) { 174 return AddBuiltin(BuiltinOperator_CONV_2D, registration, ParseConv2D); 175 } 176 AddCos()177 TfLiteStatus AddCos() { 178 return AddBuiltin(BuiltinOperator_COS, tflite::ops::micro::Register_COS(), 179 ParseCos); 180 } 181 AddCumSum()182 TfLiteStatus AddCumSum() { 183 return AddBuiltin(BuiltinOperator_CUMSUM, tflite::Register_CUMSUM(), 184 ParseCumsum); 185 } 186 AddDepthToSpace()187 TfLiteStatus AddDepthToSpace() { 188 return AddBuiltin(BuiltinOperator_DEPTH_TO_SPACE, 189 tflite::Register_DEPTH_TO_SPACE(), ParseDepthToSpace); 190 } 191 AddDepthwiseConv2D()192 TfLiteStatus AddDepthwiseConv2D() { 193 return AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, 194 Register_DEPTHWISE_CONV_2D(), ParseDepthwiseConv2D); 195 } 196 AddDequantize()197 TfLiteStatus AddDequantize() { 198 return AddBuiltin(BuiltinOperator_DEQUANTIZE, 199 tflite::ops::micro::Register_DEQUANTIZE(), 200 ParseDequantize); 201 } 202 AddDetectionPostprocess()203 TfLiteStatus AddDetectionPostprocess() { 204 return AddCustom("TFLite_Detection_PostProcess", 205 tflite::Register_DETECTION_POSTPROCESS()); 206 } 207 AddElu()208 TfLiteStatus AddElu() { 209 return AddBuiltin(BuiltinOperator_ELU, tflite::Register_ELU(), ParseElu); 210 } 211 AddEqual()212 TfLiteStatus AddEqual() { 213 return AddBuiltin(BuiltinOperator_EQUAL, 214 tflite::ops::micro::Register_EQUAL(), ParseEqual); 215 } 216 AddEthosU()217 TfLiteStatus AddEthosU() { 218 TfLiteRegistration* registration = tflite::Register_ETHOSU(); 219 if (registration) { 220 return AddCustom(tflite::GetString_ETHOSU(), registration); 221 } 222 return kTfLiteOk; 223 } 224 AddExp()225 TfLiteStatus AddExp() { 226 return AddBuiltin(BuiltinOperator_EXP, Register_EXP(), ParseExp); 227 } 228 AddExpandDims()229 TfLiteStatus AddExpandDims() { 230 return AddBuiltin(BuiltinOperator_EXPAND_DIMS, Register_EXPAND_DIMS(), 231 ParseExpandDims); 232 } 233 AddFill()234 TfLiteStatus AddFill() { 235 return AddBuiltin(BuiltinOperator_FILL, tflite::Register_FILL(), ParseFill); 236 } 237 AddFloor()238 TfLiteStatus AddFloor() { 239 return AddBuiltin(BuiltinOperator_FLOOR, 240 tflite::ops::micro::Register_FLOOR(), ParseFloor); 241 } 242 AddFloorDiv()243 TfLiteStatus AddFloorDiv() { 244 return AddBuiltin(BuiltinOperator_FLOOR_DIV, tflite::Register_FLOOR_DIV(), 245 ParseFloorDiv); 246 } 247 AddFloorMod()248 TfLiteStatus AddFloorMod() { 249 return AddBuiltin(BuiltinOperator_FLOOR_MOD, tflite::Register_FLOOR_MOD(), 250 ParseFloorMod); 251 } 252 253 TfLiteStatus AddFullyConnected( 254 const TfLiteRegistration& registration = Register_FULLY_CONNECTED()) { 255 return AddBuiltin(BuiltinOperator_FULLY_CONNECTED, registration, 256 ParseFullyConnected); 257 } 258 AddGather()259 TfLiteStatus AddGather() { 260 return AddBuiltin(BuiltinOperator_GATHER, tflite::Register_GATHER(), 261 ParseGather); 262 } 263 AddGatherNd()264 TfLiteStatus AddGatherNd() { 265 return AddBuiltin(BuiltinOperator_GATHER_ND, tflite::Register_GATHER_ND(), 266 ParseGatherNd); 267 } 268 AddGreater()269 TfLiteStatus AddGreater() { 270 return AddBuiltin(BuiltinOperator_GREATER, 271 tflite::ops::micro::Register_GREATER(), ParseGreater); 272 } 273 AddGreaterEqual()274 TfLiteStatus AddGreaterEqual() { 275 return AddBuiltin(BuiltinOperator_GREATER_EQUAL, 276 tflite::ops::micro::Register_GREATER_EQUAL(), 277 ParseGreaterEqual); 278 } 279 AddHardSwish()280 TfLiteStatus AddHardSwish() { 281 return AddBuiltin(BuiltinOperator_HARD_SWISH, tflite::Register_HARD_SWISH(), 282 ParseHardSwish); 283 } 284 AddIf()285 TfLiteStatus AddIf() { 286 return AddBuiltin(BuiltinOperator_IF, tflite::Register_IF(), ParseIf); 287 } 288 AddL2Normalization()289 TfLiteStatus AddL2Normalization() { 290 return AddBuiltin(BuiltinOperator_L2_NORMALIZATION, 291 tflite::ops::micro::Register_L2_NORMALIZATION(), 292 ParseL2Normalization); 293 } 294 AddL2Pool2D()295 TfLiteStatus AddL2Pool2D() { 296 return AddBuiltin(BuiltinOperator_L2_POOL_2D, tflite::Register_L2_POOL_2D(), 297 ParsePool); 298 } 299 AddLeakyRelu()300 TfLiteStatus AddLeakyRelu() { 301 return AddBuiltin(BuiltinOperator_LEAKY_RELU, tflite::Register_LEAKY_RELU(), 302 ParseLeakyRelu); 303 } 304 AddLess()305 TfLiteStatus AddLess() { 306 return AddBuiltin(BuiltinOperator_LESS, tflite::ops::micro::Register_LESS(), 307 ParseLess); 308 } 309 AddLessEqual()310 TfLiteStatus AddLessEqual() { 311 return AddBuiltin(BuiltinOperator_LESS_EQUAL, 312 tflite::ops::micro::Register_LESS_EQUAL(), 313 ParseLessEqual); 314 } 315 AddLog()316 TfLiteStatus AddLog() { 317 return AddBuiltin(BuiltinOperator_LOG, tflite::ops::micro::Register_LOG(), 318 ParseLog); 319 } 320 AddLogicalAnd()321 TfLiteStatus AddLogicalAnd() { 322 return AddBuiltin(BuiltinOperator_LOGICAL_AND, 323 tflite::Register_LOGICAL_AND(), ParseLogicalAnd); 324 } 325 AddLogicalNot()326 TfLiteStatus AddLogicalNot() { 327 return AddBuiltin(BuiltinOperator_LOGICAL_NOT, 328 tflite::ops::micro::Register_LOGICAL_NOT(), 329 ParseLogicalNot); 330 } 331 AddLogicalOr()332 TfLiteStatus AddLogicalOr() { 333 return AddBuiltin(BuiltinOperator_LOGICAL_OR, tflite::Register_LOGICAL_OR(), 334 ParseLogicalOr); 335 } 336 AddLogistic()337 TfLiteStatus AddLogistic() { 338 return AddBuiltin(BuiltinOperator_LOGISTIC, tflite::Register_LOGISTIC(), 339 ParseLogistic); 340 } 341 AddMaximum()342 TfLiteStatus AddMaximum() { 343 return AddBuiltin(BuiltinOperator_MAXIMUM, 344 tflite::ops::micro::Register_MAXIMUM(), ParseMaximum); 345 } 346 AddMaxPool2D()347 TfLiteStatus AddMaxPool2D() { 348 return AddBuiltin(BuiltinOperator_MAX_POOL_2D, 349 tflite::Register_MAX_POOL_2D(), ParsePool); 350 } 351 AddMean()352 TfLiteStatus AddMean() { 353 return AddBuiltin(BuiltinOperator_MEAN, tflite::ops::micro::Register_MEAN(), 354 ParseReducer); 355 } 356 AddMinimum()357 TfLiteStatus AddMinimum() { 358 return AddBuiltin(BuiltinOperator_MINIMUM, 359 tflite::ops::micro::Register_MINIMUM(), ParseMinimum); 360 } 361 AddMul()362 TfLiteStatus AddMul() { 363 return AddBuiltin(BuiltinOperator_MUL, tflite::ops::micro::Register_MUL(), 364 ParseMul); 365 } 366 AddNeg()367 TfLiteStatus AddNeg() { 368 return AddBuiltin(BuiltinOperator_NEG, tflite::ops::micro::Register_NEG(), 369 ParseNeg); 370 } 371 AddNotEqual()372 TfLiteStatus AddNotEqual() { 373 return AddBuiltin(BuiltinOperator_NOT_EQUAL, 374 tflite::ops::micro::Register_NOT_EQUAL(), ParseNotEqual); 375 } 376 AddPack()377 TfLiteStatus AddPack() { 378 return AddBuiltin(BuiltinOperator_PACK, tflite::ops::micro::Register_PACK(), 379 ParsePack); 380 } 381 AddPad()382 TfLiteStatus AddPad() { 383 return AddBuiltin(BuiltinOperator_PAD, tflite::ops::micro::Register_PAD(), 384 ParsePad); 385 } 386 AddPadV2()387 TfLiteStatus AddPadV2() { 388 return AddBuiltin(BuiltinOperator_PADV2, 389 tflite::ops::micro::Register_PADV2(), ParsePadV2); 390 } 391 AddPrelu()392 TfLiteStatus AddPrelu() { 393 return AddBuiltin(BuiltinOperator_PRELU, 394 tflite::ops::micro::Register_PRELU(), ParsePrelu); 395 } 396 AddQuantize()397 TfLiteStatus AddQuantize() { 398 return AddBuiltin(BuiltinOperator_QUANTIZE, Register_QUANTIZE(), 399 ParseQuantize); 400 } 401 AddReduceMax()402 TfLiteStatus AddReduceMax() { 403 return AddBuiltin(BuiltinOperator_REDUCE_MAX, 404 tflite::ops::micro::Register_REDUCE_MAX(), ParseReducer); 405 } 406 AddRelu()407 TfLiteStatus AddRelu() { 408 return AddBuiltin(BuiltinOperator_RELU, tflite::Register_RELU(), ParseRelu); 409 } 410 AddRelu6()411 TfLiteStatus AddRelu6() { 412 return AddBuiltin(BuiltinOperator_RELU6, tflite::Register_RELU6(), 413 ParseRelu6); 414 } 415 AddReshape()416 TfLiteStatus AddReshape() { 417 return AddBuiltin(BuiltinOperator_RESHAPE, 418 tflite::ops::micro::Register_RESHAPE(), ParseReshape); 419 } 420 AddResizeBilinear()421 TfLiteStatus AddResizeBilinear() { 422 return AddBuiltin(BuiltinOperator_RESIZE_BILINEAR, 423 Register_RESIZE_BILINEAR(), ParseResizeBilinear); 424 } 425 AddResizeNearestNeighbor()426 TfLiteStatus AddResizeNearestNeighbor() { 427 return AddBuiltin(BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, 428 tflite::ops::micro::Register_RESIZE_NEAREST_NEIGHBOR(), 429 ParseResizeNearestNeighbor); 430 } 431 AddRound()432 TfLiteStatus AddRound() { 433 return AddBuiltin(BuiltinOperator_ROUND, 434 tflite::ops::micro::Register_ROUND(), ParseRound); 435 } 436 AddRsqrt()437 TfLiteStatus AddRsqrt() { 438 return AddBuiltin(BuiltinOperator_RSQRT, 439 tflite::ops::micro::Register_RSQRT(), ParseRsqrt); 440 } 441 AddShape()442 TfLiteStatus AddShape() { 443 return AddBuiltin(BuiltinOperator_SHAPE, Register_SHAPE(), ParseShape); 444 } 445 AddSin()446 TfLiteStatus AddSin() { 447 return AddBuiltin(BuiltinOperator_SIN, tflite::ops::micro::Register_SIN(), 448 ParseSin); 449 } 450 451 TfLiteStatus AddSoftmax( 452 const TfLiteRegistration& registration = Register_SOFTMAX()) { 453 return AddBuiltin(BuiltinOperator_SOFTMAX, registration, ParseSoftmax); 454 } 455 AddSpaceToBatchNd()456 TfLiteStatus AddSpaceToBatchNd() { 457 return AddBuiltin(BuiltinOperator_SPACE_TO_BATCH_ND, 458 Register_SPACE_TO_BATCH_ND(), ParseSpaceToBatchNd); 459 } 460 AddSpaceToDepth()461 TfLiteStatus AddSpaceToDepth() { 462 return AddBuiltin(BuiltinOperator_SPACE_TO_DEPTH, Register_SPACE_TO_DEPTH(), 463 ParseSpaceToDepth); 464 } 465 AddSplit()466 TfLiteStatus AddSplit() { 467 return AddBuiltin(BuiltinOperator_SPLIT, 468 tflite::ops::micro::Register_SPLIT(), ParseSplit); 469 } 470 AddSplitV()471 TfLiteStatus AddSplitV() { 472 return AddBuiltin(BuiltinOperator_SPLIT_V, 473 tflite::ops::micro::Register_SPLIT_V(), ParseSplitV); 474 } 475 AddSqueeze()476 TfLiteStatus AddSqueeze() { 477 return AddBuiltin(BuiltinOperator_SQUEEZE, Register_SQUEEZE(), 478 ParseSqueeze); 479 } 480 AddSqrt()481 TfLiteStatus AddSqrt() { 482 return AddBuiltin(BuiltinOperator_SQRT, tflite::ops::micro::Register_SQRT(), 483 ParseSqrt); 484 } 485 AddSquare()486 TfLiteStatus AddSquare() { 487 return AddBuiltin(BuiltinOperator_SQUARE, 488 tflite::ops::micro::Register_SQUARE(), ParseSquare); 489 } 490 AddStridedSlice()491 TfLiteStatus AddStridedSlice() { 492 return AddBuiltin(BuiltinOperator_STRIDED_SLICE, 493 tflite::ops::micro::Register_STRIDED_SLICE(), 494 ParseStridedSlice); 495 } 496 AddSub()497 TfLiteStatus AddSub() { 498 return AddBuiltin(BuiltinOperator_SUB, tflite::ops::micro::Register_SUB(), 499 ParseSub); 500 } 501 AddSvdf()502 TfLiteStatus AddSvdf() { 503 return AddBuiltin(BuiltinOperator_SVDF, Register_SVDF(), ParseSvdf); 504 } 505 AddTanh()506 TfLiteStatus AddTanh() { 507 return AddBuiltin(BuiltinOperator_TANH, tflite::ops::micro::Register_TANH(), 508 ParseTanh); 509 } 510 AddTransposeConv()511 TfLiteStatus AddTransposeConv() { 512 return AddBuiltin(BuiltinOperator_TRANSPOSE_CONV, 513 tflite::Register_TRANSPOSE_CONV(), ParseTransposeConv); 514 } 515 AddTranspose()516 TfLiteStatus AddTranspose() { 517 return AddBuiltin(BuiltinOperator_TRANSPOSE, Register_TRANSPOSE(), 518 ParseTranspose); 519 } 520 AddUnpack()521 TfLiteStatus AddUnpack() { 522 return AddBuiltin(BuiltinOperator_UNPACK, 523 tflite::ops::micro::Register_UNPACK(), ParseUnpack); 524 } 525 AddZerosLike()526 TfLiteStatus AddZerosLike() { 527 return AddBuiltin(BuiltinOperator_ZEROS_LIKE, Register_ZEROS_LIKE(), 528 ParseZerosLike); 529 } 530 GetRegistrationLength()531 unsigned int GetRegistrationLength() { return registrations_len_; } 532 533 private: AddBuiltin(tflite::BuiltinOperator op,const TfLiteRegistration & registration,MicroOpResolver::BuiltinParseFunction parser)534 TfLiteStatus AddBuiltin(tflite::BuiltinOperator op, 535 const TfLiteRegistration& registration, 536 MicroOpResolver::BuiltinParseFunction parser) { 537 if (op == BuiltinOperator_CUSTOM) { 538 if (error_reporter_ != nullptr) { 539 TF_LITE_REPORT_ERROR(error_reporter_, 540 "Invalid parameter BuiltinOperator_CUSTOM to the " 541 "AddBuiltin function."); 542 } 543 return kTfLiteError; 544 } 545 546 if (FindOp(op) != nullptr) { 547 if (error_reporter_ != nullptr) { 548 TF_LITE_REPORT_ERROR(error_reporter_, 549 "Calling AddBuiltin with the same op more than " 550 "once is not supported (Op: #%d).", 551 op); 552 } 553 return kTfLiteError; 554 } 555 556 if (registrations_len_ >= tOpCount) { 557 if (error_reporter_) { 558 TF_LITE_REPORT_ERROR(error_reporter_, 559 "Couldn't register builtin op #%d, resolver size " 560 "is too small (%d).", 561 op, tOpCount); 562 } 563 return kTfLiteError; 564 } 565 566 registrations_[registrations_len_] = registration; 567 // Strictly speaking, the builtin_code is not necessary for TFLM but filling 568 // it in regardless. 569 registrations_[registrations_len_].builtin_code = op; 570 registrations_len_++; 571 572 builtin_codes_[num_buitin_ops_] = op; 573 builtin_parsers_[num_buitin_ops_] = parser; 574 num_buitin_ops_++; 575 576 return kTfLiteOk; 577 } 578 579 TfLiteRegistration registrations_[tOpCount]; 580 unsigned int registrations_len_ = 0; 581 582 // Arrays (and counter) to store the builtin codes and their corresponding 583 // parse functions as these are registered with the Op Resolver. 584 BuiltinOperator builtin_codes_[tOpCount]; 585 MicroOpResolver::BuiltinParseFunction builtin_parsers_[tOpCount]; 586 unsigned int num_buitin_ops_ = 0; 587 588 ErrorReporter* error_reporter_; 589 }; 590 591 }; // namespace tflite 592 593 #endif // TENSORFLOW_LITE_MICRO_MICRO_MUTABLE_OP_RESOLVER_H_ 594