Skip to content

Commit aa13d6a

Browse files
committed
TfLite functional template in place.
1 parent df75d5c commit aa13d6a

4 files changed

Lines changed: 4534 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
"""
18+
Tools for converting TFLite graphs into Relax graphs.
19+
"""
20+
from .tflite_frontend import from_tflite
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
# pylint: disable=invalid-name, unused-argument, too-many-lines, import-outside-toplevel
18+
# pylint: disable=broad-exception-raised, use-list-literal
19+
"""Tensorflow lite frontend helper to parse custom options in Flexbuffer format."""
20+
21+
import struct
22+
from enum import IntEnum
23+
24+
25+
class BitWidth(IntEnum):
26+
"""Flexbuffer bit width schema from flexbuffers.h"""
27+
28+
BIT_WIDTH_8 = 0
29+
BIT_WIDTH_16 = 1
30+
BIT_WIDTH_32 = 2
31+
BIT_WIDTH_64 = 3
32+
33+
34+
class FlexBufferType(IntEnum):
35+
"""Flexbuffer type schema from flexbuffers.h"""
36+
37+
FBT_NULL = 0
38+
FBT_INT = 1
39+
FBT_UINT = 2
40+
FBT_FLOAT = 3
41+
# Types above stored inline, types below store an offset.
42+
FBT_KEY = 4
43+
FBT_STRING = 5
44+
FBT_INDIRECT_INT = 6
45+
FBT_INDIRECT_UINT = 7
46+
FBT_INDIRECT_FLOAT = 8
47+
FBT_MAP = 9
48+
FBT_VECTOR = 10 # Untyped.
49+
FBT_VECTOR_INT = 11 # Typed any size (stores no type table).
50+
FBT_VECTOR_UINT = 12
51+
FBT_VECTOR_FLOAT = 13
52+
FBT_VECTOR_KEY = 14
53+
FBT_VECTOR_STRING = 15
54+
FBT_VECTOR_INT2 = 16 # Typed tuple (no type table, no size field).
55+
FBT_VECTOR_UINT2 = 17
56+
FBT_VECTOR_FLOAT2 = 18
57+
FBT_VECTOR_INT3 = 19 # Typed triple (no type table, no size field).
58+
FBT_VECTOR_UINT3 = 20
59+
FBT_VECTOR_FLOAT3 = 21
60+
FBT_VECTOR_INT4 = 22 # Typed quad (no type table, no size field).
61+
FBT_VECTOR_UINT4 = 23
62+
FBT_VECTOR_FLOAT4 = 24
63+
FBT_BLOB = 25
64+
FBT_BOOL = 26
65+
FBT_VECTOR_BOOL = 36 # To Allow the same type of conversion of type to vector type
66+
67+
68+
class FlexBufferDecoder(object):
69+
"""
70+
This implements partial flexbuffer deserialization to be able
71+
to read custom options. It is not intended to be a general
72+
purpose flexbuffer deserializer and as such only supports a
73+
limited number of types and assumes the data is a flat map.
74+
"""
75+
76+
def __init__(self, buffer):
77+
self.buffer = buffer
78+
79+
def indirect_jump(self, offset, byte_width):
80+
"""Helper function to read the offset value and jump"""
81+
unpack_str = ""
82+
if byte_width == 1:
83+
unpack_str = "<B"
84+
elif byte_width == 4:
85+
unpack_str = "<i"
86+
assert unpack_str != ""
87+
back_jump = struct.unpack(unpack_str, self.buffer[offset : offset + byte_width])[0]
88+
return offset - back_jump
89+
90+
def decode_keys(self, end, size, byte_width):
91+
"""Decodes the flexbuffer type vector. Map keys are stored in this form"""
92+
# Keys are strings here. The format is all strings separated by null, followed by back
93+
# offsets for each of the string. For example, (str1)\0(str1)\0(offset1)(offset2) The end
94+
# pointer is pointing at the end of all strings
95+
keys = list()
96+
for i in range(0, size):
97+
offset_pos = end + i * byte_width
98+
start_index = self.indirect_jump(offset_pos, byte_width)
99+
str_size = self.buffer[start_index:].find(b"\0")
100+
assert str_size != -1
101+
s = self.buffer[start_index : start_index + str_size].decode("utf-8")
102+
keys.append(s)
103+
return keys
104+
105+
def decode_vector(self, end, size, byte_width):
106+
"""Decodes the flexbuffer vector"""
107+
# Each entry in the vector can have different datatype. Each entry is of fixed length. The
108+
# format is a sequence of all values followed by a sequence of datatype of all values. For
109+
# example - (4)(3.56)(int)(float) The end here points to the start of the values.
110+
values = list()
111+
for i in range(0, size):
112+
value_type_pos = end + size * byte_width + i
113+
value_type = FlexBufferType(self.buffer[value_type_pos] >> 2)
114+
value_bytes = self.buffer[end + i * byte_width : end + (i + 1) * byte_width]
115+
if value_type == FlexBufferType.FBT_BOOL:
116+
value = bool(value_bytes[0])
117+
elif value_type == FlexBufferType.FBT_INT:
118+
value = struct.unpack("<i", value_bytes)[0]
119+
elif value_type == FlexBufferType.FBT_UINT:
120+
value = struct.unpack("<I", value_bytes)[0]
121+
elif value_type == FlexBufferType.FBT_FLOAT:
122+
value = struct.unpack("<f", value_bytes)[0]
123+
else:
124+
raise Exception
125+
values.append(value)
126+
return values
127+
128+
def decode_map(self, end, byte_width, parent_byte_width):
129+
"""Decodes the flexbuffer map and returns a dict"""
130+
mid_loc = self.indirect_jump(end, parent_byte_width)
131+
map_size = struct.unpack("<i", self.buffer[mid_loc - byte_width : mid_loc])[0]
132+
133+
# Find keys
134+
keys_offset = mid_loc - byte_width * 3
135+
keys_end = self.indirect_jump(keys_offset, byte_width)
136+
keys = self.decode_keys(keys_end, map_size, 1)
137+
138+
# Find values
139+
values_end = self.indirect_jump(end, parent_byte_width)
140+
values = self.decode_vector(values_end, map_size, byte_width)
141+
return dict(zip(keys, values))
142+
143+
def decode(self):
144+
"""Decode the buffer. Decoding is partially implemented"""
145+
root_end = len(self.buffer) - 1
146+
root_byte_width = self.buffer[root_end]
147+
root_end -= 1
148+
root_packed_type = self.buffer[root_end]
149+
root_end -= root_byte_width
150+
151+
root_type = FlexBufferType(root_packed_type >> 2)
152+
byte_width = 1 << BitWidth(root_packed_type & 3)
153+
154+
if root_type == FlexBufferType.FBT_MAP:
155+
return self.decode_map(root_end, byte_width, root_byte_width)
156+
raise NotImplementedError("Flexbuffer Decoding is partially imlpemented.")

0 commit comments

Comments
 (0)