Export min_runtime_version in MLIR converter
This change fixes the issue for missing min_runtime_version in flatbuffers exported by MLIR converter. Specifically: *Export `min_runtime_version` in metadata of flatbuffer (fixed-length byte array). *Update all related mlir tests to have metadata. PiperOrigin-RevId: 299894972 Change-Id: Ic79f3ab05b593882362f5baf62493861961acbe3
This commit is contained in:
parent
356c9a830c
commit
30f3741ddf
@ -580,7 +580,7 @@ cc_library(
|
||||
"//tensorflow/lite/delegates/flex:whitelisted_flex_ops_lib",
|
||||
"//tensorflow/lite/kernels/internal:kernel_utils",
|
||||
"//tensorflow/lite/schema:schema_fbs",
|
||||
"//tensorflow/lite/tools/versioning:op_version",
|
||||
"//tensorflow/lite/tools/versioning",
|
||||
"@com_google_absl//absl/base",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
|
@ -76,6 +76,7 @@ limitations under the License.
|
||||
#include "tensorflow/lite/schema/schema_generated.h"
|
||||
#include "tensorflow/lite/string_util.h"
|
||||
#include "tensorflow/lite/tools/versioning/op_version.h"
|
||||
#include "tensorflow/lite/tools/versioning/runtime_version.h"
|
||||
#include "tensorflow/lite/version.h"
|
||||
|
||||
using llvm::dyn_cast;
|
||||
@ -1230,21 +1231,27 @@ BufferOffset<tflite::Metadata> Translator::BuildMetadata(StringRef name,
|
||||
Optional<VectorBufferOffset<BufferOffset<tflite::Metadata>>>
|
||||
Translator::CreateMetadataVector() {
|
||||
auto dict_attr = module_.getAttrOfType<mlir::DictionaryAttr>("tfl.metadata");
|
||||
if (!dict_attr) return VectorBufferOffset<BufferOffset<tflite::Metadata>>();
|
||||
|
||||
std::vector<BufferOffset<tflite::Metadata>> metadata;
|
||||
for (const auto& named_attr : dict_attr) {
|
||||
StringRef name = named_attr.first;
|
||||
mlir::Attribute attr = named_attr.second;
|
||||
if (auto content = attr.dyn_cast<StringAttr>()) {
|
||||
metadata.push_back(BuildMetadata(name, content.getValue()));
|
||||
} else {
|
||||
module_.emitError(
|
||||
"all values in tfl.metadata's dictionary key-value pairs should be "
|
||||
"string attributes");
|
||||
return llvm::None;
|
||||
if (dict_attr) {
|
||||
for (const auto& named_attr : dict_attr) {
|
||||
StringRef name = named_attr.first;
|
||||
mlir::Attribute attr = named_attr.second;
|
||||
if (auto content = attr.dyn_cast<StringAttr>()) {
|
||||
metadata.push_back(BuildMetadata(name, content.getValue()));
|
||||
} else {
|
||||
module_.emitError(
|
||||
"all values in tfl.metadata's dictionary key-value pairs should be "
|
||||
"string attributes");
|
||||
return llvm::None;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Runtime version string is generated after we update the op
|
||||
// versions. Here we put a 16-byte dummy string as a placeholder. We choose
|
||||
// 16-byte because it's the alignment of buffers in flatbuffer, so it won't
|
||||
// cause any waste of space if the actual string is shorter than 16 bytes.
|
||||
metadata.push_back(
|
||||
BuildMetadata("min_runtime_version", std::string(16, '\0')));
|
||||
return builder_.CreateVector(metadata);
|
||||
}
|
||||
|
||||
@ -1359,6 +1366,7 @@ Optional<std::string> Translator::TranslateInternal() {
|
||||
builder_.CreateVector(buffers_), metadata_buffer, *metadata);
|
||||
tflite::FinishModelBuffer(builder_, model);
|
||||
tflite::UpdateOpVersion(builder_.GetBufferPointer());
|
||||
tflite::UpdateMinimumRuntimeVersionForModel(builder_.GetBufferPointer());
|
||||
|
||||
// Return serialized string for the built FlatBuffer.
|
||||
return std::string(reinterpret_cast<const char*>(builder_.GetBufferPointer()),
|
||||
|
@ -1,4 +1,4 @@
|
||||
# RUN: tf_tfl_translate -tf-input-arrays=input0,input1 -tf-input-shapes=4:4 -tf-input-data-types=DT_INT32,DT_INT32 -tf-output-arrays=Add %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
# RUN: tf_tfl_translate -tf-input-arrays=input0,input1 -tf-input-shapes=4:4 -tf-input-data-types=DT_INT32,DT_INT32 -tf-output-arrays=Add %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
# Add two tensor<4xi32> inputs and return the result
|
||||
|
||||
@ -90,5 +90,11 @@ versions {
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: }, {
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: }, {
|
||||
# CHECK-NEXT: data: [ 49, 46, 53, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
# CHECK-NEXT: } ],
|
||||
# CHECK-NEXT: metadata: [ {
|
||||
# CHECK-NEXT: name: "min_runtime_version",
|
||||
# CHECK-NEXT: buffer: 4
|
||||
# CHECK-NEXT: } ]
|
||||
# CHECK-NEXT: }
|
||||
|
@ -108,6 +108,12 @@ func @main(tensor<1x384xf32>, tensor<1x96xf32>, tensor<384x480xf32>, tensor<384x
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 48, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 10
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_translate --tflite-flatbuffer-to-mlir -o - | FileCheck --check-prefix=MLIR %s
|
||||
|
||||
|
||||
@ -61,6 +61,12 @@ func @main(%arg0: tensor<32x4x4x128xf32>, %arg1: tensor<1x32x42x128xf32>, %arg2:
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 5
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
^bb0(%arg0: tensor<4xf32>):
|
||||
@ -90,6 +90,12 @@ func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 55, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -82,6 +82,12 @@ func @main(tensor<1x224x224x3xf32>) -> tensor<1x112x112x32xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 51, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -84,6 +84,12 @@ func @main(tensor<1x224x224x3xf32>) -> tensor<1x112x112x32xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 51, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
^bb0(%arg0: tensor<4xf32>):
|
||||
@ -88,6 +88,12 @@ func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 55, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_translate -tflite-flatbuffer-to-mlir - -o - | FileCheck --check-prefix=IMPORT %s
|
||||
|
||||
func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
@ -46,6 +46,12 @@ func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 53, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 3
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-select-tf-ops=true -emit-builtin-tflite-ops=false -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-select-tf-ops=true -emit-builtin-tflite-ops=false -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(%arg0: tensor<3x2xf32>) -> tensor<3x2xf32> {
|
||||
// CHECK: {
|
||||
@ -39,6 +39,12 @@ func @main(%arg0: tensor<3x2xf32>) -> tensor<3x2xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 3
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-select-tf-ops -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-select-tf-ops -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
^bb0(%arg0: tensor<4xf32>):
|
||||
@ -89,6 +89,12 @@ func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 55, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -61,6 +61,12 @@ func @main(tensor<40x37xf32>, tensor<40x37xf32>) -> tensor<40x40xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 53, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 5
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -61,6 +61,12 @@ func @main(tensor<40x37xf32>, tensor<40x37xf32>) -> tensor<40x40xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 48, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 5
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -156,6 +156,12 @@
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 52, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 11
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4xi1>) -> tensor<4xi1> {
|
||||
^bb0(%arg0: tensor<4xi1>):
|
||||
@ -78,6 +78,12 @@ func @main(tensor<4xi1>) -> tensor<4xi1> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 49, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>) -> tensor<4 x f32> {
|
||||
// CHECK: {
|
||||
@ -249,6 +249,12 @@ func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, t
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 55, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 26
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
|
@ -128,6 +128,12 @@ func @main(tensor<4xf32>) -> tensor<4xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 51, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 8
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_translate --tflite-flatbuffer-to-mlir -o - | FileCheck --check-prefix=MLIR %s
|
||||
|
||||
func @main(%arg0: tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x32x32x32xf32>) {
|
||||
@ -50,6 +50,12 @@ func @main(%arg0: tensor<1x64x64x32xf32>) -> (tensor<1x32x32x32xf32>, tensor<1x3
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 4
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -emit-custom-ops -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_translate --tflite-flatbuffer-to-mlir -o - | FileCheck --check-prefix=MLIR %s
|
||||
|
||||
func @main(%arg0: tensor<1x8x8x128xf32>, %arg1: tensor<1x8x8x128xf32>) -> tensor<1x8x8x128xf32> {
|
||||
@ -50,6 +50,12 @@ func @main(%arg0: tensor<1x8x8x128xf32>, %arg1: tensor<1x8x8x128xf32>) -> tensor
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 4
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -20,6 +20,8 @@ module attributes {
|
||||
// CHECK-NEXT: data: [ 118, 97, 108, 117, 101, 49 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 118, 97, 108, 117, 101, 50 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 54, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "key1",
|
||||
@ -27,4 +29,8 @@ module attributes {
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: name: "key2",
|
||||
// CHECK-NEXT: buffer: 5
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
@ -58,6 +58,12 @@ func @main(tensor<3x!quant.uniform<i8:f32, 0.1>>) -> tensor<3x!quant.uniform<i8:
|
||||
// CHECK-NEXT: data: [ 2, 2, 2 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 52, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 4
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -58,6 +58,12 @@ func @main(tensor<3x!quant.uniform<i8:f32, 1.0>>) -> tensor<3x!quant.uniform<i8:
|
||||
// CHECK-NEXT: data: [ 2, 2, 2 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 53, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 4
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<1x6x6x16xf32>) -> tensor<1x1x1x16xf32> {
|
||||
^bb0(%arg0: tensor<1x6x6x16xf32>):
|
||||
@ -47,6 +47,12 @@ func @main(tensor<1x6x6x16xf32>) -> tensor<1x1x1x16xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 53, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 3
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
// CHECK: {
|
||||
// CHECK-NEXT: version: 3,
|
||||
@ -40,6 +40,12 @@
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 3
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(%arg0: tensor<1x224x224x3xf32>) -> tensor<1x1001xf32> {
|
||||
// CHECK: {
|
||||
@ -153,6 +153,12 @@ func @main(%arg0: tensor<1x224x224x3xf32>) -> tensor<1x1001xf32> {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 51, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 10
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT:}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<3x2xi32>) -> tensor<6xi32> {
|
||||
^bb0(%arg0: tensor<3x2xi32>):
|
||||
@ -51,6 +51,12 @@ func @main(tensor<3x2xi32>) -> tensor<6xi32> {
|
||||
// CHECK-NEXT: data: [ 6, 0, 0, 0 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 53, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 4
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -97,6 +97,12 @@ func @main(tensor<3x2xi32>) -> tensor<3x2xi32>
|
||||
// CHECK-NEXT: data: [ 10, 0, 0, 0 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 54, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 6
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>) -> tensor<4 x f32> {
|
||||
// CHECK: {
|
||||
@ -79,6 +79,12 @@ func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>) -
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 53, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 7
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4 x f32>, tensor<4 x i8>, tensor<4 x f32>, tensor<4 x f32>) -> tensor<4 x f32> {
|
||||
// CHECK: {
|
||||
@ -80,6 +80,12 @@ func @main(tensor<4 x f32>, tensor<4 x i8>, tensor<4 x f32>, tensor<4 x f32>) ->
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 52, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 7
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
|
@ -189,6 +189,12 @@
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 52, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 14
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>) -> tensor<4 x f32> {
|
||||
// CHECK: {
|
||||
@ -249,6 +249,12 @@ func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, t
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 51, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 26
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>) -> tensor<4 x f32> {
|
||||
// CHECK: {
|
||||
@ -79,6 +79,12 @@ func @main(tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>, tensor<4 x f32>) -
|
||||
// CHECK-NEXT: data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 52, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 7
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck %s
|
||||
// RUN: flatbuffer_translate -mlir-to-tflite-flatbuffer %s -o - | flatbuffer_to_string - | FileCheck --dump-input-on-failure %s
|
||||
|
||||
// CHECK: {
|
||||
// CHECK-NEXT: version: 3,
|
||||
@ -189,6 +189,12 @@
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: }, {
|
||||
// CHECK-NEXT: data: [ 49, 46, 49, 52, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
// CHECK-NEXT: } ],
|
||||
// CHECK-NEXT: metadata: [ {
|
||||
// CHECK-NEXT: name: "min_runtime_version",
|
||||
// CHECK-NEXT: buffer: 14
|
||||
// CHECK-NEXT: } ]
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -163,7 +163,7 @@ execute the op. In this example, it means:
|
||||
* Populate version=2 otherwise.
|
||||
|
||||
To do this, you need to override `GetVersion` function for the operator class in
|
||||
`lite/toco/tflite/operator.cc`.
|
||||
`lite/tools/versioning/op_version.cc`.
|
||||
|
||||
For ops with only one version, the `GetVersion` function is defined as:
|
||||
|
||||
@ -191,7 +191,8 @@ The last step is to add the new version info into the operator version map. This
|
||||
step is required because we need generate the model's minimum required runtime
|
||||
version based on this version map.
|
||||
|
||||
To do this, you need to add a new map entry in `lite/toco/tflite/op_version.cc`.
|
||||
To do this, you need to add a new map entry in
|
||||
`lite/tools/versioning/op_version.cc`.
|
||||
|
||||
In this example, it means you need to add the following into `op_version_map`:
|
||||
```
|
||||
|
@ -182,7 +182,7 @@ cc_library(
|
||||
"//tensorflow/lite/testing:util",
|
||||
"//tensorflow/lite/tools/optimize:quantization_utils",
|
||||
"//tensorflow/lite/tools/optimize/sparsity:format_converter",
|
||||
"//tensorflow/lite/tools/versioning:op_version",
|
||||
"//tensorflow/lite/tools/versioning",
|
||||
"@com_google_googletest//:gtest",
|
||||
],
|
||||
)
|
||||
|
@ -225,8 +225,20 @@ string FlatBufferModel::GetMinimumRuntime() const {
|
||||
auto buf = metadata->buffer();
|
||||
auto* buffer = (*model_->buffers())[buf];
|
||||
auto* array = buffer->data();
|
||||
return string(reinterpret_cast<const char*>(array->data()),
|
||||
array->size());
|
||||
// Get the real length of the runtime string, since there might be
|
||||
// trailing
|
||||
// '\0's in the buffer.
|
||||
for (int len = 0; len < array->size(); ++len) {
|
||||
if (array->data()[len] == '\0') {
|
||||
return string(reinterpret_cast<const char*>(array->data()), len);
|
||||
}
|
||||
}
|
||||
// If there is no '\0' in the buffer, this indicates that the flatbuffer
|
||||
// is malformed.
|
||||
TF_LITE_REPORT_ERROR(
|
||||
error_reporter_,
|
||||
"Min_runtime_version in model metadata is malformed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
@ -366,7 +366,7 @@ TEST(BasicFlatBufferModel, TestReadRuntimeVersionFromModel) {
|
||||
"tensorflow/lite/testdata/test_min_runtime.bin");
|
||||
ASSERT_TRUE(model2);
|
||||
// Check that we have read the runtime string correctly.
|
||||
ASSERT_EQ(model2->GetMinimumRuntime(), "1.10.0");
|
||||
ASSERT_EQ(model2->GetMinimumRuntime(), "1.5.0");
|
||||
}
|
||||
|
||||
// The test model has the following tensor encoded in the TACO format:
|
||||
|
BIN
tensorflow/lite/testdata/test_min_runtime.bin
vendored
BIN
tensorflow/lite/testdata/test_min_runtime.bin
vendored
Binary file not shown.
@ -32,7 +32,7 @@ cc_library(
|
||||
"//tensorflow/lite/schema:schema_fbs",
|
||||
"//tensorflow/lite/toco:graph_transformations",
|
||||
"//tensorflow/lite/toco:model",
|
||||
"//tensorflow/lite/tools/versioning:op_version",
|
||||
"//tensorflow/lite/tools/versioning",
|
||||
"@com_google_absl//absl/memory",
|
||||
"@flatbuffers",
|
||||
],
|
||||
@ -147,6 +147,7 @@ cc_library(
|
||||
":operator",
|
||||
"//tensorflow/lite/toco:model",
|
||||
"//tensorflow/lite/toco:tooling_util",
|
||||
"//tensorflow/lite/tools/versioning",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
@ -22,27 +22,13 @@ limitations under the License.
|
||||
#include "tensorflow/lite/toco/model.h"
|
||||
#include "tensorflow/lite/toco/tflite/operator.h"
|
||||
#include "tensorflow/lite/toco/tooling_util.h"
|
||||
#include "tensorflow/lite/tools/versioning/runtime_version.h"
|
||||
|
||||
namespace toco {
|
||||
namespace tflite {
|
||||
|
||||
bool CompareVersion(const string& v1, const string& v2) {
|
||||
const std::vector<string>& vec1 = absl::StrSplit(v1, '.');
|
||||
const std::vector<string>& vec2 = absl::StrSplit(v2, '.');
|
||||
int i = 0;
|
||||
while (i < vec1.size() && i < vec2.size()) {
|
||||
int v1_val, v2_val;
|
||||
if (absl::SimpleAtoi(vec1[i], &v1_val) &&
|
||||
absl::SimpleAtoi(vec2[i], &v2_val)) {
|
||||
if (v1_val != v2_val) return v1_val < v2_val;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
// If there are remaining items in v2 not being compared, then v1 should
|
||||
// precede v2.
|
||||
return i < vec2.size();
|
||||
}
|
||||
|
||||
// Deprecated and please register new ops/versions in
|
||||
// tflite/tools/versioning/op_version.cc".
|
||||
string GetMinimumRuntimeVersionForModel(const Model& model) {
|
||||
// Use this as the placeholder string if a particular op is not yet included
|
||||
// in any Tensorflow's RC/Final release source package. Once that op is
|
||||
@ -253,7 +239,7 @@ string GetMinimumRuntimeVersionForModel(const Model& model) {
|
||||
// doesn't have a minimum runtime version associated, continue.
|
||||
continue;
|
||||
}
|
||||
if (CompareVersion(model_min_version, it->second)) {
|
||||
if (::tflite::CompareRuntimeVersion(model_min_version, it->second)) {
|
||||
// Current min model runtime version should be bumped if we see a higher
|
||||
// op version.
|
||||
model_min_version = it->second;
|
||||
|
@ -20,11 +20,6 @@ limitations under the License.
|
||||
namespace toco {
|
||||
namespace tflite {
|
||||
|
||||
// Returns true if the first version string precedes the second.
|
||||
// For example, '1.14' should precede '1.9', also '1.14.1' should precede
|
||||
// '1.14'. If two version string is equal, then false will be returned.
|
||||
bool CompareVersion(const string&, const string&);
|
||||
|
||||
// Get the minimum TF Lite runtime required to run a model. Each built-in
|
||||
// operator in the model will have its own minimum requirement of a runtime, and
|
||||
// the model's minimum requirement of runtime is defined as the maximum of all
|
||||
|
@ -22,6 +22,7 @@ namespace toco {
|
||||
namespace tflite {
|
||||
namespace {
|
||||
|
||||
// TODO(b/150701120): port the tests to tools/versioning/op_version_test.cc.
|
||||
TEST(OpVersionTest, MinimumVersionForSameOpVersions) {
|
||||
Model model;
|
||||
// Float convolutional kernel is introduced since '1.5.0'.
|
||||
@ -138,18 +139,6 @@ TEST(OpVersionTest, MinimumVersionForMixedOpVersions) {
|
||||
EXPECT_EQ(GetMinimumRuntimeVersionForModel(model), "1.10.0");
|
||||
}
|
||||
|
||||
TEST(OpVersionTest, CompareVersionString) {
|
||||
EXPECT_TRUE(CompareVersion("1.9", "1.13"));
|
||||
EXPECT_FALSE(CompareVersion("1.13", "1.13"));
|
||||
EXPECT_TRUE(CompareVersion("1.14", "1.14.1"));
|
||||
EXPECT_FALSE(CompareVersion("1.14.1", "1.14"));
|
||||
EXPECT_FALSE(CompareVersion("1.14.1", "1.9"));
|
||||
EXPECT_FALSE(CompareVersion("1.0.9", "1.0.8"));
|
||||
EXPECT_FALSE(CompareVersion("2.1.0", "1.2.0"));
|
||||
EXPECT_TRUE(CompareVersion("", "1.13"));
|
||||
EXPECT_FALSE(CompareVersion("", ""));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tflite
|
||||
} // namespace toco
|
||||
|
@ -9,14 +9,20 @@ package(
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "op_version",
|
||||
srcs = ["op_version.cc"],
|
||||
name = "versioning",
|
||||
srcs = [
|
||||
"op_version.cc",
|
||||
"runtime_version.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"op_version.h",
|
||||
"runtime_version.h",
|
||||
],
|
||||
deps = [
|
||||
"//tensorflow/core:tflite_portable_logging",
|
||||
"//tensorflow/lite:minimal_logging",
|
||||
"//tensorflow/lite/kernels/internal:compatibility",
|
||||
"//tensorflow/lite/schema:schema_fbs",
|
||||
"//tensorflow/lite/schema:schema_fbs_with_mutable",
|
||||
"@com_google_absl//absl/memory",
|
||||
"@com_google_absl//absl/strings",
|
||||
@ -25,10 +31,13 @@ cc_library(
|
||||
)
|
||||
|
||||
tf_cc_test(
|
||||
name = "op_version_test",
|
||||
srcs = ["op_version_test.cc"],
|
||||
name = "versioning_test",
|
||||
srcs = [
|
||||
"op_version_test.cc",
|
||||
"runtime_version_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":op_version",
|
||||
":versioning",
|
||||
"//tensorflow/lite/schema:schema_fbs_with_mutable",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
|
285
tensorflow/lite/tools/versioning/runtime_version.cc
Normal file
285
tensorflow/lite/tools/versioning/runtime_version.cc
Normal file
@ -0,0 +1,285 @@
|
||||
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
#include "tensorflow/lite/tools/versioning/runtime_version.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "absl/strings/numbers.h"
|
||||
#include "absl/strings/str_split.h"
|
||||
#include "tensorflow/lite/minimal_logging.h"
|
||||
#include "tensorflow/lite/schema/mutable/schema_generated.h"
|
||||
|
||||
namespace tflite {
|
||||
|
||||
bool CompareRuntimeVersion(const std::string& v1, const std::string& v2) {
|
||||
const std::vector<std::string> vec1 = absl::StrSplit(v1, '.');
|
||||
const std::vector<std::string> vec2 = absl::StrSplit(v2, '.');
|
||||
int i = 0;
|
||||
while (i < vec1.size() && i < vec2.size()) {
|
||||
int v1_val, v2_val;
|
||||
if (absl::SimpleAtoi(vec1[i], &v1_val) &&
|
||||
absl::SimpleAtoi(vec2[i], &v2_val)) {
|
||||
if (v1_val != v2_val) return v1_val < v2_val;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
// If there are remaining items in v2 not being compared, then v1 should
|
||||
// precede v2.
|
||||
return i < vec2.size();
|
||||
}
|
||||
|
||||
void UpdateMinimumRuntimeVersionForModel(uint8_t* model_buffer_pointer) {
|
||||
// Use this as the placeholder string if a particular op is not yet included
|
||||
// in any Tensorflow's RC/Final release source package. Once that op is
|
||||
// included in the release, please update this with the real version string.
|
||||
static constexpr char kPendingReleaseOpVersion[] = "UNKNOWN";
|
||||
// A map from the version key of an op to its minimum runtime version.
|
||||
// For example, {{kAveragePool, 1}, "1.5.0"}, means the 1st version of
|
||||
// AveragePool requires a minimum TF Lite runtime version '1.5.0`.
|
||||
static const std::map<std::pair<BuiltinOperator, int>, std::string>*
|
||||
op_version_map =
|
||||
new std::map<std::pair<BuiltinOperator, int>, std::string>({
|
||||
{{BuiltinOperator_AVERAGE_POOL_2D, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_AVERAGE_POOL_2D, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_CONV_2D, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_CONV_2D, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_CONV_2D, 3}, "1.14.0"},
|
||||
{{BuiltinOperator_DEPTHWISE_CONV_2D, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_DEPTHWISE_CONV_2D, 2}, "1.12.0"},
|
||||
{{BuiltinOperator_DEPTHWISE_CONV_2D, 3}, "1.14.0"},
|
||||
{{BuiltinOperator_ADD, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_ADD, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_ADD_N, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_SPACE_TO_BATCH_ND, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_SPACE_TO_BATCH_ND, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SUB, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_SUB, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_DIV, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_BATCH_TO_SPACE_ND, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_BATCH_TO_SPACE_ND, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_CAST, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_CONCATENATION, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_CONCATENATION, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_DEPTH_TO_SPACE, 1}, "2.1.0"},
|
||||
{{BuiltinOperator_FAKE_QUANT, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_FAKE_QUANT, 2}, "1.10.0"},
|
||||
{{BuiltinOperator_FULLY_CONNECTED, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_FULLY_CONNECTED, 2}, "1.10.0"},
|
||||
{{BuiltinOperator_FULLY_CONNECTED, 3}, "1.14.0"},
|
||||
{{BuiltinOperator_FULLY_CONNECTED, 4}, "1.14.0"},
|
||||
{{BuiltinOperator_FULLY_CONNECTED, 5}, "2.0.0"},
|
||||
{{BuiltinOperator_FULLY_CONNECTED, 6}, "2.1.0"},
|
||||
{{BuiltinOperator_GATHER, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_GATHER, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_GATHER, 3}, "1.15.0"},
|
||||
{{BuiltinOperator_GATHER_ND, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_SVDF, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_SVDF, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SVDF, 3}, "2.2.0"},
|
||||
{{BuiltinOperator_L2_NORMALIZATION, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_L2_NORMALIZATION, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_L2_POOL_2D, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_MAX_POOL_2D, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_MAX_POOL_2D, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_MAXIMUM, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_MAXIMUM, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_MINIMUM, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_MINIMUM, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_MUL, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_MUL, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_MUL, 3}, "1.15.0"},
|
||||
{{BuiltinOperator_PAD, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_PAD, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_TILE, 1}, "1.10.1"},
|
||||
{{BuiltinOperator_TILE, 2}, "2.2.0"},
|
||||
{{BuiltinOperator_PADV2, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_PADV2, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_RESHAPE, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_SOFTMAX, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_SOFTMAX, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SPACE_TO_DEPTH, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_SPACE_TO_DEPTH, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_TRANSPOSE, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_TRANSPOSE, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_TRANSPOSE, 3}, "1.15.0"},
|
||||
{{BuiltinOperator_LSTM, 1}, "1.7.0"},
|
||||
{{BuiltinOperator_LSTM, 2}, "1.10.0"},
|
||||
{{BuiltinOperator_LSTM, 3}, "1.14.0"},
|
||||
{{BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM, 1}, "1.13.1"},
|
||||
{{BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_MEAN, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_MEAN, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SUM, 1}, "1.10.0"},
|
||||
{{BuiltinOperator_SUM, 2}, "1.15.0"},
|
||||
{{BuiltinOperator_REDUCE_MAX, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_REDUCE_MAX, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_REDUCE_MIN, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_REDUCE_MIN, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_REDUCE_PROD, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_REDUCE_ANY, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_RELU6, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_RELU6, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_RESIZE_BILINEAR, 1}, "1.7.0"},
|
||||
{{BuiltinOperator_RESIZE_BILINEAR, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_RESIZE_BILINEAR, 3}, "2.2.0"},
|
||||
{{BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, 1}, "1.13.1"},
|
||||
{{BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SQUEEZE, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_SPLIT, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_SPLIT, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SPLIT, 3}, "1.14.0"},
|
||||
{{BuiltinOperator_SPLIT_V, 1}, "1.13.1"},
|
||||
{{BuiltinOperator_STRIDED_SLICE, 1}, "1.6.0"},
|
||||
{{BuiltinOperator_STRIDED_SLICE, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_STRIDED_SLICE, 3}, "2.1.0"},
|
||||
{{BuiltinOperator_TOPK_V2, 1}, "1.7.0"},
|
||||
{{BuiltinOperator_TOPK_V2, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_ARG_MAX, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_ARG_MAX, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_ARG_MIN, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_ARG_MIN, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_TRANSPOSE_CONV, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_SPARSE_TO_DENSE, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_SPARSE_TO_DENSE, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SPARSE_TO_DENSE, 3}, "1.15.0"},
|
||||
{{BuiltinOperator_EXPAND_DIMS, 1}, "1.10.0"},
|
||||
{{BuiltinOperator_PACK, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_PACK, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SHAPE, 1}, "1.10.0"},
|
||||
{{BuiltinOperator_SLICE, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_SLICE, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SLICE, 3}, "1.14.0"},
|
||||
{{BuiltinOperator_TANH, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_TANH, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_ONE_HOT, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_UNPACK, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_UNPACK, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_UNPACK, 3}, "2.2.0"},
|
||||
{{BuiltinOperator_LEAKY_RELU, 1}, "1.13.1"},
|
||||
{{BuiltinOperator_LOGISTIC, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_LOGISTIC, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_LOG_SOFTMAX, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_LOG_SOFTMAX, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SQUARED_DIFFERENCE, 1}, "1.13.1"},
|
||||
{{BuiltinOperator_MIRROR_PAD, 1}, "1.13.1"},
|
||||
{{BuiltinOperator_UNIQUE, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_WHERE, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_DEQUANTIZE, 1}, "1.13.1"},
|
||||
{{BuiltinOperator_DEQUANTIZE, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_DEQUANTIZE, 3}, "1.15.0"},
|
||||
{{BuiltinOperator_REVERSE_SEQUENCE, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_EQUAL, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_EQUAL, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_NOT_EQUAL, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_NOT_EQUAL, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_GREATER, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_GREATER, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_GREATER_EQUAL, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_GREATER_EQUAL, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_LESS, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_LESS, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_LESS_EQUAL, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_LESS_EQUAL, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SEGMENT_SUM, 1}, "2.2.0"},
|
||||
{{BuiltinOperator_SELECT, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_SELECT, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_SELECT_V2, 1}, "2.2.0"},
|
||||
{{BuiltinOperator_FLOOR_DIV, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_FLOOR_DIV, 2}, "1.14.0"},
|
||||
{{BuiltinOperator_FLOOR, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_CEIL, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_MATRIX_DIAG, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_MATRIX_SET_DIAG, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_ELU, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_ROUND, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_RELU, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_RELU, 2}, "2.1.0"},
|
||||
{{BuiltinOperator_RELU_N1_TO_1, 1}, "1.5.0"},
|
||||
{{BuiltinOperator_PRELU, 1}, "1.8.0"},
|
||||
{{BuiltinOperator_EXP, 1}, "1.7.0"},
|
||||
{{BuiltinOperator_COS, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_NEG, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_POW, 1}, "1.10.0"},
|
||||
{{BuiltinOperator_LOGICAL_OR, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_LOGICAL_AND, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_LOGICAL_NOT, 1}, "1.11.0"},
|
||||
{{BuiltinOperator_FLOOR_MOD, 1}, "1.13.0"},
|
||||
{{BuiltinOperator_RANGE, 1}, "1.13.0"},
|
||||
{{BuiltinOperator_SIN, 1}, "1.9.0"},
|
||||
{{BuiltinOperator_LOG, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_RSQRT, 1}, "1.10.0"},
|
||||
{{BuiltinOperator_SQUARE, 1}, "1.12.0"},
|
||||
{{BuiltinOperator_ZEROS_LIKE, 1}, "1.12.0"},
|
||||
{{BuiltinOperator_ABS, 1}, "1.13.0"},
|
||||
{{BuiltinOperator_HARD_SWISH, 1}, "1.15.0"},
|
||||
{{BuiltinOperator_FILL, 1}, "1.13.0"},
|
||||
{{BuiltinOperator_REVERSE_V2, 1}, "1.14.0"},
|
||||
{{BuiltinOperator_REVERSE_V2, 2}, "2.2.0"},
|
||||
{{BuiltinOperator_RANK, 1}, "1.14.0"},
|
||||
});
|
||||
|
||||
auto model = GetMutableModel(model_buffer_pointer);
|
||||
std::string model_min_version;
|
||||
auto subgraphs = model->subgraphs();
|
||||
for (int i = 0; i < subgraphs->Length(); ++i) {
|
||||
const SubGraph* subgraph = subgraphs->Get(i);
|
||||
for (int j = 0; j < subgraph->operators()->Length(); ++j) {
|
||||
const Operator* op = subgraph->operators()->Get(j);
|
||||
const OperatorCode* op_code =
|
||||
model->operator_codes()->Get(op->opcode_index());
|
||||
std::pair<BuiltinOperator, int> version_key = {op_code->builtin_code(),
|
||||
op_code->version()};
|
||||
auto it = op_version_map->find(version_key);
|
||||
if (it == op_version_map->end() ||
|
||||
it->second == kPendingReleaseOpVersion) {
|
||||
// In case we didn't find the current op in the map, or the operator
|
||||
// doesn't have a minimum runtime version associated, continue.
|
||||
continue;
|
||||
}
|
||||
if (CompareRuntimeVersion(model_min_version, it->second)) {
|
||||
// Current min model runtime version should be bumped if we see a higher
|
||||
// op version.
|
||||
model_min_version = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
// The size of the `min_runtime_version` metadata buffer is 16 bytes. If the
|
||||
// generated `model_min_version` is equal or longer than 16 bytes, print a
|
||||
// warning message and return.
|
||||
if (model_min_version.size() >= 16) {
|
||||
TFLITE_LOG(TFLITE_LOG_WARNING,
|
||||
"Skip writing minimum runtime version string since it's "
|
||||
"longer than 16 bytes.");
|
||||
return;
|
||||
}
|
||||
// Copy over the bytes from `model_min_version` into the buffer.
|
||||
for (int i = 0; i < model->metadata()->size(); ++i) {
|
||||
if (model->metadata()->Get(i)->name()->str() == "min_runtime_version") {
|
||||
auto buffer = model->metadata()->Get(i)->buffer();
|
||||
auto buffer_data =
|
||||
model->mutable_buffers()->GetMutableObject(buffer)->mutable_data();
|
||||
memset(buffer_data->data(), 0, buffer_data->size());
|
||||
memcpy(buffer_data->data(), model_min_version.data(),
|
||||
model_min_version.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tflite
|
33
tensorflow/lite/tools/versioning/runtime_version.h
Normal file
33
tensorflow/lite/tools/versioning/runtime_version.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
#ifndef TENSORFLOW_LITE_TOOLS_VERSIONING_RUNTIME_VERSION_H_
|
||||
#define TENSORFLOW_LITE_TOOLS_VERSIONING_RUNTIME_VERSION_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h" // TF:flatbuffers
|
||||
|
||||
namespace tflite {
|
||||
// Update minimum runtime version of the given TFL flatbuffer model.
|
||||
void UpdateMinimumRuntimeVersionForModel(uint8_t* model_buffer_pointer);
|
||||
|
||||
// Returns true if the first version string precedes the second.
|
||||
// For example, '1.14' should precede '1.9', also '1.14.1' should precede
|
||||
// '1.14'. If two version string is equal, then false will be returned.
|
||||
bool CompareRuntimeVersion(const std::string&, const std::string&);
|
||||
|
||||
} // namespace tflite
|
||||
|
||||
#endif // TENSORFLOW_LITE_TOOLS_VERSIONING_RUNTIME_VERSION_H_
|
34
tensorflow/lite/tools/versioning/runtime_version_test.cc
Normal file
34
tensorflow/lite/tools/versioning/runtime_version_test.cc
Normal file
@ -0,0 +1,34 @@
|
||||
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
#include "tensorflow/lite/tools/versioning/runtime_version.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace tflite {
|
||||
|
||||
TEST(OpVersionTest, CompareRuntimeVersion) {
|
||||
EXPECT_TRUE(CompareRuntimeVersion("1.9", "1.13"));
|
||||
EXPECT_FALSE(CompareRuntimeVersion("1.13", "1.13"));
|
||||
EXPECT_TRUE(CompareRuntimeVersion("1.14", "1.14.1"));
|
||||
EXPECT_FALSE(CompareRuntimeVersion("1.14.1", "1.14"));
|
||||
EXPECT_FALSE(CompareRuntimeVersion("1.14.1", "1.9"));
|
||||
EXPECT_FALSE(CompareRuntimeVersion("1.0.9", "1.0.8"));
|
||||
EXPECT_FALSE(CompareRuntimeVersion("2.1.0", "1.2.0"));
|
||||
EXPECT_TRUE(CompareRuntimeVersion("", "1.13"));
|
||||
EXPECT_FALSE(CompareRuntimeVersion("", ""));
|
||||
}
|
||||
|
||||
} // namespace tflite
|
Loading…
Reference in New Issue
Block a user