tico 0.1.0.dev250630__py3-none-any.whl → 0.1.0.dev250702__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tico/__init__.py +1 -1
- tico/interpreter/infer.py +33 -27
- tico/passes/legalize_predefined_layout_operators.py +84 -1
- tico/serialize/operators/op_conv2d.py +16 -32
- tico/serialize/operators/op_depthwise_conv2d.py +22 -37
- tico/serialize/operators/op_transpose_conv.py +149 -0
- tico/utils/convert.py +8 -0
- tico/utils/installed_packages.py +35 -0
- tico/utils/padding.py +54 -19
- tico/utils/register_custom_op.py +108 -0
- tico/utils/validate_args_kwargs.py +39 -0
- {tico-0.1.0.dev250630.dist-info → tico-0.1.0.dev250702.dist-info}/METADATA +1 -1
- {tico-0.1.0.dev250630.dist-info → tico-0.1.0.dev250702.dist-info}/RECORD +17 -15
- {tico-0.1.0.dev250630.dist-info → tico-0.1.0.dev250702.dist-info}/LICENSE +0 -0
- {tico-0.1.0.dev250630.dist-info → tico-0.1.0.dev250702.dist-info}/WHEEL +0 -0
- {tico-0.1.0.dev250630.dist-info → tico-0.1.0.dev250702.dist-info}/entry_points.txt +0 -0
- {tico-0.1.0.dev250630.dist-info → tico-0.1.0.dev250702.dist-info}/top_level.txt +0 -0
tico/__init__.py
CHANGED
@@ -21,7 +21,7 @@ from tico.config import CompileConfigV1, get_default_config
|
|
21
21
|
from tico.utils.convert import convert, convert_from_exported_program, convert_from_pt2
|
22
22
|
|
23
23
|
# THIS LINE IS AUTOMATICALLY GENERATED BY setup.py
|
24
|
-
__version__ = "0.1.0.
|
24
|
+
__version__ = "0.1.0.dev250702"
|
25
25
|
|
26
26
|
MINIMUM_SUPPORTED_VERSION = "2.5.0"
|
27
27
|
SECURE_TORCH_VERSION = "2.6.0"
|
tico/interpreter/infer.py
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
from typing import Any
|
15
|
+
from typing import Any, Sequence
|
16
16
|
|
17
17
|
import numpy as np
|
18
18
|
import torch
|
@@ -20,40 +20,46 @@ from circle_schema import circle
|
|
20
20
|
|
21
21
|
from tico.interpreter.interpreter import Interpreter
|
22
22
|
from tico.serialize.circle_mapping import np_dtype_from_circle_dtype, to_circle_dtype
|
23
|
+
from tico.utils.installed_packages import is_dynamic_cache_available
|
23
24
|
|
24
25
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
26
|
+
def flatten_and_convert(inputs: Sequence) -> tuple:
|
27
|
+
result = [] # type: ignore[var-annotated]
|
28
|
+
for item in inputs:
|
29
|
+
if item is None:
|
30
|
+
continue
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
"""
|
33
|
-
l = []
|
34
|
-
for value in inputs:
|
35
|
-
if value == None:
|
32
|
+
# 1. recursion on list and tuple
|
33
|
+
if isinstance(item, (list, tuple)):
|
34
|
+
result.extend(flatten_and_convert(item))
|
36
35
|
continue
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
36
|
+
|
37
|
+
# 2. handle DynamicCache
|
38
|
+
if is_dynamic_cache_available():
|
39
|
+
from transformers.cache_utils import DynamicCache
|
40
|
+
|
41
|
+
if isinstance(item, DynamicCache):
|
42
|
+
# NOTE The tensor order is: key_in → key_out → value_in → value_out
|
43
|
+
#
|
44
|
+
# Refer to https://github.com/huggingface/transformers/blob/3457e8e73e4f5532cc69059682b1ba4484d7e7e8/src/transformers/cache_utils.py#L557
|
45
|
+
# ```py
|
46
|
+
# self.key_cache[layer_idx] = torch.cat([self.key_cache[layer_idx], key_states], dim=-2)
|
47
|
+
# self.value_cache[layer_idx] = torch.cat([self.value_cache[layer_idx], value_states], dim=-2)
|
48
|
+
# ```
|
49
|
+
result.extend(item.key_cache)
|
50
|
+
result.extend(item.value_cache)
|
51
|
+
continue
|
52
|
+
|
53
|
+
# 3. Convert to tensors
|
54
|
+
result.append(item if isinstance(item, torch.Tensor) else torch.tensor(item))
|
55
|
+
|
56
|
+
return tuple(result)
|
46
57
|
|
47
58
|
|
48
59
|
def infer(circle_binary: bytes, *args: Any, **kwargs: Any) -> Any:
|
49
60
|
# When converting a model, it is assumed that the order of keyword arguments is maintained.
|
50
|
-
|
51
|
-
user_inputs =
|
52
|
-
# Cast them to torch.Tensor to make it simple.
|
53
|
-
user_inputs = tuple(
|
54
|
-
torch.tensor(user_input) if type(user_input) != torch.Tensor else user_input
|
55
|
-
for user_input in user_inputs
|
56
|
-
)
|
61
|
+
raw_inputs = args + tuple(kwargs.values())
|
62
|
+
user_inputs = flatten_and_convert(raw_inputs)
|
57
63
|
|
58
64
|
# Get input spec from circle binary.
|
59
65
|
model = circle.Model.Model.GetRootAsModel(circle_binary, 0)
|
@@ -30,6 +30,7 @@ from tico.utils.utils import is_target_node
|
|
30
30
|
from tico.utils.validate_args_kwargs import (
|
31
31
|
AvgPool2dArgs,
|
32
32
|
Conv2DArgs,
|
33
|
+
ConvTranspose2DArgs,
|
33
34
|
DequantizePerChannelArgs,
|
34
35
|
DequantizePerTensorArgs,
|
35
36
|
InstanceNormArgs,
|
@@ -37,7 +38,9 @@ from tico.utils.validate_args_kwargs import (
|
|
37
38
|
)
|
38
39
|
|
39
40
|
|
40
|
-
def get_permute_weight_input(
|
41
|
+
def get_permute_weight_input(
|
42
|
+
conv_args: Conv2DArgs | ConvTranspose2DArgs,
|
43
|
+
) -> torch.fx.Node:
|
41
44
|
"""
|
42
45
|
Retrieves the weight input for the permute operation.
|
43
46
|
|
@@ -194,6 +197,85 @@ class LegalizePreDefinedLayoutOperators(PassBase):
|
|
194
197
|
modified = True
|
195
198
|
return modified
|
196
199
|
|
200
|
+
def legalize_conv_transpose2d(self, exported_program, node) -> bool:
|
201
|
+
logger = logging.getLogger(__name__)
|
202
|
+
modified = False
|
203
|
+
|
204
|
+
graph_module = exported_program.graph_module
|
205
|
+
graph = graph_module.graph
|
206
|
+
|
207
|
+
args = ConvTranspose2DArgs(*node.args, **node.kwargs) # type: ignore[arg-type]
|
208
|
+
input = args.input
|
209
|
+
padding = args.padding
|
210
|
+
groups = args.groups
|
211
|
+
dilation = args.dilation
|
212
|
+
|
213
|
+
input_shape = extract_shape(input)
|
214
|
+
if not (len(input_shape) == 4):
|
215
|
+
raise NotYetSupportedError(
|
216
|
+
f"Only support 4D input tensor: node's input shape: {input_shape}"
|
217
|
+
)
|
218
|
+
|
219
|
+
if groups != 1:
|
220
|
+
raise NotYetSupportedError(
|
221
|
+
f"Only support groups=1: node's groups: {groups}"
|
222
|
+
)
|
223
|
+
|
224
|
+
if dilation != [1, 1]:
|
225
|
+
raise NotYetSupportedError(
|
226
|
+
f"Only support dilation=[1, 1]: node's groups: {dilation}"
|
227
|
+
)
|
228
|
+
|
229
|
+
NCHW_to_NHWC = [0, 2, 3, 1]
|
230
|
+
# input permute
|
231
|
+
with graph.inserting_after(input):
|
232
|
+
input_permute = create_node(
|
233
|
+
graph,
|
234
|
+
torch.ops.aten.permute.default,
|
235
|
+
args=(input, NCHW_to_NHWC),
|
236
|
+
origin=input,
|
237
|
+
)
|
238
|
+
node.update_arg(node.args.index(input), input_permute)
|
239
|
+
|
240
|
+
# weight permute
|
241
|
+
weight = get_permute_weight_input(args)
|
242
|
+
with graph.inserting_after(weight):
|
243
|
+
perm = [1, 2, 3, 0] # IOHW_to_OHWI
|
244
|
+
weight_permute = create_node(
|
245
|
+
graph,
|
246
|
+
torch.ops.aten.permute.default,
|
247
|
+
args=(weight, perm),
|
248
|
+
origin=weight,
|
249
|
+
)
|
250
|
+
if args.weight.target in [
|
251
|
+
torch.ops.quantized_decomposed.dequantize_per_channel.default,
|
252
|
+
torch.ops.quantized_decomposed.dequantize_per_tensor.default,
|
253
|
+
]:
|
254
|
+
dq = args.weight
|
255
|
+
dq.update_arg(dq.args.index(weight), weight_permute)
|
256
|
+
# Need to update dq.meta["val"] in FillMetaVal pass.
|
257
|
+
del dq.meta["val"]
|
258
|
+
else:
|
259
|
+
node.update_arg(node.args.index(weight), weight_permute)
|
260
|
+
|
261
|
+
with graph.inserting_before(node):
|
262
|
+
legalized_op = torch.ops.circle_custom.transpose_conv
|
263
|
+
circle_op = create_node(
|
264
|
+
graph, legalized_op, args=node.args, kwargs=node.kwargs, origin=node
|
265
|
+
)
|
266
|
+
# output permute
|
267
|
+
NHWC_to_NCHW = [0, 3, 1, 2]
|
268
|
+
conv_out_permute = create_node(
|
269
|
+
graph,
|
270
|
+
torch.ops.aten.permute.default,
|
271
|
+
args=(circle_op, NHWC_to_NCHW),
|
272
|
+
)
|
273
|
+
node.replace_all_uses_with(conv_out_permute, propagate_meta=True)
|
274
|
+
|
275
|
+
logger.debug(f"{node.name} is replaced with {circle_op.name}")
|
276
|
+
modified = True
|
277
|
+
return modified
|
278
|
+
|
197
279
|
def legalize_instance_norm(self, exported_program, node) -> bool:
|
198
280
|
logger = logging.getLogger(__name__)
|
199
281
|
modified = False
|
@@ -365,6 +447,7 @@ class LegalizePreDefinedLayoutOperators(PassBase):
|
|
365
447
|
target_to_legalize_func = {
|
366
448
|
torch.ops.aten.conv2d.default: self.legalize_conv2d,
|
367
449
|
torch.ops.aten.conv2d.padding: self.legalize_conv2d,
|
450
|
+
torch.ops.aten.conv_transpose2d.input: self.legalize_conv_transpose2d,
|
368
451
|
torch.ops.aten.max_pool2d_with_indices.default: self.legalize_max_pool2d_with_indices,
|
369
452
|
torch.ops.aten.avg_pool2d.default: self.legalize_avg_pool2d,
|
370
453
|
torch.ops.aten.instance_norm.default: self.legalize_instance_norm,
|
@@ -26,7 +26,7 @@ from tico.serialize.operators.node_visitor import NodeVisitor, register_node_vis
|
|
26
26
|
from tico.serialize.operators.utils import create_builtin_operator, get_op_index
|
27
27
|
from tico.serialize.quant_param import QPARAM_KEY, QuantParam
|
28
28
|
from tico.utils.define import define_pad_node
|
29
|
-
from tico.utils.padding import
|
29
|
+
from tico.utils.padding import identify_padding
|
30
30
|
from tico.utils.validate_args_kwargs import Conv2DArgs
|
31
31
|
|
32
32
|
|
@@ -111,53 +111,39 @@ class Conv2dVisitor(NodeVisitor):
|
|
111
111
|
|
112
112
|
assert groups == 1, "Only support group 1 conv2d"
|
113
113
|
|
114
|
-
input_dtype: int = extract_circle_dtype(input_)
|
115
114
|
input_shape = list(extract_shape(input_))
|
115
|
+
output_shape = list(extract_shape(node))
|
116
|
+
weight_shape = list(extract_shape(weight))
|
116
117
|
assert len(input_shape) == 4, len(input_shape)
|
117
|
-
output_shape = extract_shape(node)
|
118
118
|
assert len(output_shape) == 4, len(output_shape)
|
119
|
+
assert len(weight_shape) == 4, len(weight_shape)
|
119
120
|
|
120
|
-
|
121
|
-
weight_shape = list(extract_shape(weight))
|
122
|
-
|
123
|
-
if is_valid_padding(padding):
|
124
|
-
conv2d_padding_type = VALID
|
125
|
-
elif is_same_padding(padding, input_shape, output_shape) and stride == [1, 1]:
|
126
|
-
conv2d_padding_type = SAME
|
127
|
-
else:
|
128
|
-
assert isinstance(padding, list) and len(padding) == 2
|
121
|
+
pad_decision = identify_padding(padding, input_shape, output_shape, stride)
|
129
122
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
# when data_foramt is "NHWC", padding should be [[0, 0], [pad_top, pad_bottom], [pad_left, pad_right], [0, 0]]
|
123
|
+
conv_input: torch.fx.Node | circle.Tensor.TensorT = input_
|
124
|
+
if pad_decision.explicit_pad_hw is not None:
|
125
|
+
pad_h, pad_w = pad_decision.explicit_pad_hw
|
134
126
|
paddings = torch.tensor(
|
135
127
|
[
|
136
128
|
[0, 0],
|
137
|
-
[
|
138
|
-
[
|
129
|
+
[pad_h, pad_h],
|
130
|
+
[pad_w, pad_w],
|
139
131
|
[0, 0],
|
140
132
|
],
|
141
133
|
dtype=torch.int32,
|
142
134
|
)
|
143
135
|
pad_output_shape = [
|
144
136
|
input_shape[0],
|
145
|
-
input_shape[1],
|
146
|
-
input_shape[2],
|
137
|
+
input_shape[1] + pad_h * 2,
|
138
|
+
input_shape[2] + pad_w * 2,
|
147
139
|
input_shape[3],
|
148
140
|
]
|
149
|
-
# Add (pad_top+pad_bottom) to pad_output_shape_h
|
150
|
-
pad_output_shape[1] += padding[0] * 2
|
151
|
-
# Add (pad_left+pad_Right) to pad_output_shape_w
|
152
|
-
pad_output_shape[2] += padding[1] * 2
|
153
141
|
# create padded output tensor
|
154
|
-
input_qparam: Optional[QuantParam] = (
|
155
|
-
input_.meta[QPARAM_KEY] if QPARAM_KEY in input_.meta else None
|
156
|
-
)
|
142
|
+
input_qparam: Optional[QuantParam] = input_.meta.get(QPARAM_KEY)
|
157
143
|
pad_output = self.graph.add_tensor_from_scratch(
|
158
144
|
prefix=f"{node.name}_input_pad_output",
|
159
145
|
shape=pad_output_shape,
|
160
|
-
dtype=
|
146
|
+
dtype=extract_circle_dtype(input_),
|
161
147
|
qparam=input_qparam,
|
162
148
|
source_node=node,
|
163
149
|
)
|
@@ -170,13 +156,11 @@ class Conv2dVisitor(NodeVisitor):
|
|
170
156
|
|
171
157
|
if bias is None:
|
172
158
|
# luci-interpreter can't run no bias conv. Let's add zero vector for bias.
|
173
|
-
|
174
|
-
out_channel = weight_shape[0]
|
175
|
-
bias = [0.0] * out_channel # type: ignore[assignment]
|
159
|
+
bias = [0.0] * weight_shape[0] # type: ignore[assignment]
|
176
160
|
|
177
161
|
# Conv2D
|
178
162
|
conv2d_operator = self.define_conv2d_node(
|
179
|
-
|
163
|
+
pad_decision.conv_padding_type, # 'SAME'(0) or 'VALID'(1)
|
180
164
|
stride,
|
181
165
|
dilation,
|
182
166
|
[conv_input, weight, bias],
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
from typing import Dict, List, TYPE_CHECKING
|
15
|
+
from typing import Dict, List, Optional, TYPE_CHECKING
|
16
16
|
|
17
17
|
if TYPE_CHECKING:
|
18
18
|
import torch._ops
|
@@ -24,8 +24,9 @@ from tico.serialize.circle_mapping import extract_circle_dtype, extract_shape
|
|
24
24
|
from tico.serialize.operators.hashable_opcode import OpCode
|
25
25
|
from tico.serialize.operators.node_visitor import NodeVisitor, register_node_visitor
|
26
26
|
from tico.serialize.operators.utils import create_builtin_operator, get_op_index
|
27
|
+
from tico.serialize.quant_param import QPARAM_KEY, QuantParam
|
27
28
|
from tico.utils.define import define_pad_node
|
28
|
-
from tico.utils.padding import
|
29
|
+
from tico.utils.padding import identify_padding
|
29
30
|
from tico.utils.validate_args_kwargs import Conv2DArgs
|
30
31
|
|
31
32
|
|
@@ -114,63 +115,49 @@ class DepthwiseConv2dVisitor(NodeVisitor):
|
|
114
115
|
dilation = args.dilation
|
115
116
|
groups = args.groups
|
116
117
|
|
117
|
-
input_dtype: int = extract_circle_dtype(input_)
|
118
118
|
input_shape = list(extract_shape(input_)) # OHWI
|
119
|
-
assert len(input_shape) == 4, len(input_shape)
|
120
|
-
|
121
119
|
output_shape = list(extract_shape(node)) # OHWI
|
122
|
-
assert len(output_shape) == 4, len(output_shape)
|
123
|
-
|
124
120
|
weight_shape = list(extract_shape(weight)) # 1HWO
|
125
|
-
assert (
|
126
|
-
|
127
|
-
)
|
128
|
-
|
121
|
+
assert len(input_shape) == 4, len(input_shape)
|
122
|
+
assert len(output_shape) == 4, len(output_shape)
|
123
|
+
assert len(weight_shape) == 4
|
129
124
|
assert weight_shape[0] == 1
|
130
125
|
assert weight_shape[3] == output_shape[3]
|
131
126
|
assert input_shape[3] == groups
|
127
|
+
assert (
|
128
|
+
weight_shape[3] % groups == 0
|
129
|
+
), "Depthwise convolution requires output channel to be divisible by groups"
|
132
130
|
|
133
131
|
depthMultiplier = weight_shape[3] // input_shape[3]
|
134
132
|
assert weight_shape[3] % input_shape[3] == 0, "depthMultiplier must be integer"
|
135
133
|
|
136
|
-
|
137
|
-
|
138
|
-
if is_valid_padding(padding):
|
139
|
-
dconv2d_padding_type = VALID
|
140
|
-
elif is_same_padding(padding, input_shape, output_shape):
|
141
|
-
dconv2d_padding_type = SAME
|
142
|
-
else:
|
143
|
-
assert isinstance(padding, list) and len(padding) == 2
|
134
|
+
pad_decision = identify_padding(padding, input_shape, output_shape, stride)
|
144
135
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
# when data_format is "NHWC", padding should be [[0, 0], [pad_top, pad_bottom], [pad_left, pad_right], [0, 0]]
|
136
|
+
conv_input: torch.fx.Node | circle.Tensor.TensorT = input_
|
137
|
+
if pad_decision.explicit_pad_hw is not None:
|
138
|
+
pad_h, pad_w = pad_decision.explicit_pad_hw
|
149
139
|
paddings = torch.tensor(
|
150
140
|
[
|
151
141
|
[0, 0],
|
152
|
-
[
|
153
|
-
[
|
142
|
+
[pad_h, pad_h],
|
143
|
+
[pad_w, pad_w],
|
154
144
|
[0, 0],
|
155
145
|
],
|
156
146
|
dtype=torch.int32,
|
157
147
|
)
|
158
148
|
pad_output_shape = [
|
159
149
|
input_shape[0],
|
160
|
-
input_shape[1],
|
161
|
-
input_shape[2],
|
150
|
+
input_shape[1] + pad_h * 2,
|
151
|
+
input_shape[2] + pad_w * 2,
|
162
152
|
input_shape[3],
|
163
153
|
]
|
164
|
-
# Add (pad_top+pad_bottom) to pad_output_shape_h
|
165
|
-
pad_output_shape[1] += padding[0] * 2
|
166
|
-
# Add (pad_left+pad_Right) to pad_output_shape_w
|
167
|
-
pad_output_shape[2] += padding[1] * 2
|
168
154
|
# create padded output tensor
|
169
|
-
|
155
|
+
input_qparam: Optional[QuantParam] = input_.meta.get(QPARAM_KEY)
|
170
156
|
pad_output = self.graph.add_tensor_from_scratch(
|
171
157
|
prefix=f"{node.name}_input_pad_output",
|
172
158
|
shape=pad_output_shape,
|
173
|
-
dtype=
|
159
|
+
dtype=extract_circle_dtype(input_),
|
160
|
+
qparam=input_qparam,
|
174
161
|
source_node=node,
|
175
162
|
)
|
176
163
|
# CirclePad
|
@@ -182,13 +169,11 @@ class DepthwiseConv2dVisitor(NodeVisitor):
|
|
182
169
|
|
183
170
|
if bias is None:
|
184
171
|
# luci-interpreter can't run no bias conv. Let's add zero vector for bias.
|
185
|
-
|
186
|
-
out_channel = weight_shape[3]
|
187
|
-
bias = [0.0] * out_channel # type: ignore[assignment]
|
172
|
+
bias = [0.0] * weight_shape[3] # type: ignore[assignment]
|
188
173
|
|
189
174
|
# DConv2D
|
190
175
|
dconv2d_operator = self.define_dconv_node(
|
191
|
-
|
176
|
+
pad_decision.conv_padding_type,
|
192
177
|
stride,
|
193
178
|
dilation,
|
194
179
|
depthMultiplier,
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# Copyright (c) 2025 Samsung Electronics Co., Ltd. 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
|
+
from typing import Dict, List, Optional, TYPE_CHECKING
|
16
|
+
|
17
|
+
if TYPE_CHECKING:
|
18
|
+
import torch._ops
|
19
|
+
import torch.fx
|
20
|
+
import torch
|
21
|
+
from circle_schema import circle
|
22
|
+
|
23
|
+
from tico.serialize.circle_mapping import (
|
24
|
+
circle_legalize_dtype_to,
|
25
|
+
extract_circle_dtype,
|
26
|
+
extract_shape,
|
27
|
+
)
|
28
|
+
from tico.serialize.operators.hashable_opcode import OpCode
|
29
|
+
from tico.serialize.operators.node_visitor import NodeVisitor, register_node_visitor
|
30
|
+
from tico.serialize.operators.utils import create_builtin_operator, get_op_index
|
31
|
+
from tico.serialize.quant_param import QPARAM_KEY, QuantParam
|
32
|
+
from tico.utils.define import define_pad_node
|
33
|
+
from tico.utils.padding import identify_padding
|
34
|
+
from tico.utils.validate_args_kwargs import ConvTranspose2DArgs
|
35
|
+
|
36
|
+
|
37
|
+
@register_node_visitor
|
38
|
+
class TransposeConvVisitor(NodeVisitor):
|
39
|
+
target: List[torch._ops.OpOverload] = [
|
40
|
+
torch.ops.circle_custom.transpose_conv,
|
41
|
+
]
|
42
|
+
|
43
|
+
def define_transpose_conv_node(
|
44
|
+
self, padding: int, stride: List, inputs: List, outputs: List
|
45
|
+
) -> circle.Operator.OperatorT:
|
46
|
+
def set_transpose_conv_option(operator, stride):
|
47
|
+
operator.builtinOptionsType = (
|
48
|
+
circle.BuiltinOptions.BuiltinOptions.TransposeConvOptions
|
49
|
+
)
|
50
|
+
option = circle.TransposeConvOptions.TransposeConvOptionsT()
|
51
|
+
option.padding = padding
|
52
|
+
option.strideH = stride[0]
|
53
|
+
option.strideW = stride[1]
|
54
|
+
option.fusedActivationFunction = (
|
55
|
+
circle.ActivationFunctionType.ActivationFunctionType.NONE
|
56
|
+
)
|
57
|
+
operator.builtinOptions = option
|
58
|
+
|
59
|
+
transpose_conv_op_index = get_op_index(
|
60
|
+
circle.BuiltinOperator.BuiltinOperator.TRANSPOSE_CONV, self._op_codes
|
61
|
+
)
|
62
|
+
operator = create_builtin_operator(
|
63
|
+
self.graph, transpose_conv_op_index, inputs, outputs
|
64
|
+
)
|
65
|
+
set_transpose_conv_option(operator, stride)
|
66
|
+
return operator
|
67
|
+
|
68
|
+
def __init__(self, op_codes: Dict[OpCode, int], graph):
|
69
|
+
super().__init__(op_codes, graph)
|
70
|
+
|
71
|
+
def define_node(self, node: torch.fx.Node) -> circle.Operator.OperatorT:
|
72
|
+
args = ConvTranspose2DArgs(*node.args, **node.kwargs) # type: ignore[arg-type]
|
73
|
+
|
74
|
+
input_ = args.input
|
75
|
+
weight = args.weight
|
76
|
+
bias = args.bias
|
77
|
+
stride = args.stride
|
78
|
+
padding = args.padding
|
79
|
+
output_padding = args.output_padding
|
80
|
+
groups = args.groups
|
81
|
+
dilation = args.dilation
|
82
|
+
|
83
|
+
assert groups == 1, "Only support group 1"
|
84
|
+
|
85
|
+
input_shape = list(extract_shape(input_))
|
86
|
+
output_shape = list(extract_shape(node))
|
87
|
+
weight_shape = list(extract_shape(weight))
|
88
|
+
assert len(input_shape) == 4, len(input_shape)
|
89
|
+
assert len(output_shape) == 4, len(output_shape)
|
90
|
+
assert len(weight_shape) == 4, len(weight_shape)
|
91
|
+
|
92
|
+
pad_decision = identify_padding(padding, input_shape, output_shape, stride)
|
93
|
+
|
94
|
+
conv_input: torch.fx.Node | circle.Tensor.TensorT = input_
|
95
|
+
if pad_decision.explicit_pad_hw is not None:
|
96
|
+
pad_h, pad_w = pad_decision.explicit_pad_hw
|
97
|
+
paddings = torch.tensor(
|
98
|
+
[
|
99
|
+
[0, 0],
|
100
|
+
[pad_h, pad_h],
|
101
|
+
[pad_w, pad_w],
|
102
|
+
[0, 0],
|
103
|
+
],
|
104
|
+
dtype=torch.int32,
|
105
|
+
)
|
106
|
+
pad_output_shape = [
|
107
|
+
input_shape[0],
|
108
|
+
input_shape[1] + pad_h * 2,
|
109
|
+
input_shape[2] + pad_w * 2,
|
110
|
+
input_shape[3],
|
111
|
+
]
|
112
|
+
# create padded output tensor
|
113
|
+
input_qparam: Optional[QuantParam] = input_.meta.get(QPARAM_KEY)
|
114
|
+
pad_output = self.graph.add_tensor_from_scratch(
|
115
|
+
prefix=f"{node.name}_input_pad_output",
|
116
|
+
shape=pad_output_shape,
|
117
|
+
dtype=extract_circle_dtype(input_),
|
118
|
+
qparam=input_qparam,
|
119
|
+
source_node=node,
|
120
|
+
)
|
121
|
+
# CirclePad
|
122
|
+
pad_operator = define_pad_node(
|
123
|
+
self.graph, self._op_codes, [input_, paddings], [pad_output]
|
124
|
+
)
|
125
|
+
self.graph.add_operator(pad_operator)
|
126
|
+
conv_input = pad_output
|
127
|
+
|
128
|
+
if bias is None:
|
129
|
+
# luci-interpreter can't run no bias conv. Let's add zero vector for bias.
|
130
|
+
bias = [0.0] * weight_shape[0] # type: ignore[assignment]
|
131
|
+
|
132
|
+
# First arguemnt is output shape of tconv.
|
133
|
+
assert output_shape[0] == input_shape[0]
|
134
|
+
assert output_shape[3] == weight_shape[0]
|
135
|
+
tconv_output = circle_legalize_dtype_to(output_shape, dtype=torch.int32)
|
136
|
+
|
137
|
+
tconv_output_tensor = self.graph.add_const_tensor(
|
138
|
+
tconv_output, source_node=node
|
139
|
+
)
|
140
|
+
|
141
|
+
# TConv2D
|
142
|
+
tconv2d_operator = self.define_transpose_conv_node(
|
143
|
+
pad_decision.conv_padding_type, # 'SAME'(0) or 'VALID'(1)
|
144
|
+
stride,
|
145
|
+
[tconv_output_tensor, weight, conv_input, bias],
|
146
|
+
[node],
|
147
|
+
)
|
148
|
+
|
149
|
+
return tconv2d_operator
|
tico/utils/convert.py
CHANGED
@@ -100,6 +100,7 @@ def traced_run_decompositions(exported_program: ExportedProgram):
|
|
100
100
|
torch.ops.aten.conv2d.padding,
|
101
101
|
torch.ops.aten.conv1d.default,
|
102
102
|
torch.ops.aten.conv1d.padding,
|
103
|
+
torch.ops.aten.conv_transpose2d.input,
|
103
104
|
torch.ops.aten.instance_norm.default,
|
104
105
|
torch.ops.aten._safe_softmax.default,
|
105
106
|
torch.ops.aten.relu6.default, # Do not decompose to hardtanh
|
@@ -116,6 +117,7 @@ def traced_run_decompositions(exported_program: ExportedProgram):
|
|
116
117
|
torch.ops.aten.conv2d.padding,
|
117
118
|
torch.ops.aten.conv1d.default,
|
118
119
|
torch.ops.aten.conv1d.padding,
|
120
|
+
torch.ops.aten.conv_transpose2d.input,
|
119
121
|
torch.ops.aten.instance_norm.default,
|
120
122
|
torch.ops.aten._safe_softmax.default,
|
121
123
|
torch.ops.aten.relu6.default, # Do not decompose to hardtanh
|
@@ -287,6 +289,12 @@ def convert(
|
|
287
289
|
strict: bool = True,
|
288
290
|
config: CompileConfigBase = get_default_config(),
|
289
291
|
) -> CircleModel:
|
292
|
+
if hasattr(mod, "training") and mod.training:
|
293
|
+
logger = logging.getLogger(__name__)
|
294
|
+
logger.fatal(
|
295
|
+
"Your model is in TRAINING MODE. PLEASE CHECK IF YOU FORGOT `model.eval()`."
|
296
|
+
)
|
297
|
+
|
290
298
|
with torch.no_grad():
|
291
299
|
exported_program = export(mod, args, kwargs, strict=strict)
|
292
300
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright (c) 2025 Samsung Electronics Co., Ltd. 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
|
+
##############################
|
16
|
+
#### Transformers Package ####
|
17
|
+
##############################
|
18
|
+
|
19
|
+
|
20
|
+
def is_transformers_installed():
|
21
|
+
try:
|
22
|
+
import transformers
|
23
|
+
|
24
|
+
return True
|
25
|
+
except ImportError:
|
26
|
+
return False
|
27
|
+
|
28
|
+
|
29
|
+
def is_dynamic_cache_available():
|
30
|
+
try:
|
31
|
+
from transformers.cache_utils import DynamicCache
|
32
|
+
|
33
|
+
return True
|
34
|
+
except ImportError:
|
35
|
+
return False
|
tico/utils/padding.py
CHANGED
@@ -12,36 +12,71 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
from enum import IntEnum
|
16
|
+
from typing import NamedTuple, Optional, Sequence, Tuple, Union
|
17
|
+
|
15
18
|
import torch
|
16
19
|
|
17
20
|
from tico.utils.errors import InvalidArgumentError
|
18
21
|
|
19
|
-
SAME = 0
|
20
|
-
VALID = 1
|
21
22
|
|
23
|
+
PaddingValue = Union[str, Sequence[int]] # "same" | "valid" | [pad_h, pad_w]
|
22
24
|
|
23
|
-
def is_valid_padding(padding: str | list):
|
24
|
-
if isinstance(padding, str):
|
25
|
-
return padding == "valid"
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
class ConvPadding(IntEnum):
|
27
|
+
SAME = 0 # auto-pad, HW out == HW in
|
28
|
+
VALID = 1 # no implicit padding
|
29
|
+
|
30
30
|
|
31
|
-
|
31
|
+
class ConvPaddingInfo(NamedTuple):
|
32
|
+
"""
|
33
|
+
Result of padding analysis.
|
34
|
+
"""
|
32
35
|
|
36
|
+
conv_padding_type: ConvPadding
|
37
|
+
explicit_pad_hw: Optional[Tuple[int, int]] # None -> no extra Pad() op needed
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
|
40
|
+
def identify_padding(
|
41
|
+
padding: PaddingValue,
|
42
|
+
input_shape: Sequence[int],
|
43
|
+
output_shape: Sequence[int],
|
44
|
+
stride: Sequence[int],
|
45
|
+
) -> ConvPaddingInfo:
|
46
|
+
"""
|
47
|
+
Normalizes all PyTorch `padding` variants to a single decision.
|
48
|
+
|
49
|
+
Rules
|
50
|
+
-----
|
51
|
+
1. "valid" or [0, 0] → VALID, no Pad().
|
52
|
+
2. "same" or the shapes already match (stride==1) → SAME, no Pad().
|
53
|
+
3. Any other 2-element list → VALID + explicit Pad().
|
54
|
+
"""
|
55
|
+
# ─── 1. String form ────────────────────────────────────────────────────
|
37
56
|
if isinstance(padding, str):
|
38
|
-
|
57
|
+
pad = padding.lower()
|
58
|
+
if pad == "valid":
|
59
|
+
return ConvPaddingInfo(ConvPadding.VALID, None)
|
60
|
+
if pad == "same":
|
61
|
+
return ConvPaddingInfo(ConvPadding.SAME, None)
|
62
|
+
raise InvalidArgumentError(f"Unknown padding string: {padding}")
|
63
|
+
|
64
|
+
# ─── 2. List / tuple form ─────────────────────────────────────────────
|
65
|
+
if not (isinstance(padding, (list, tuple)) and len(padding) == 2):
|
66
|
+
raise InvalidArgumentError(
|
67
|
+
"Padding must be 'valid', 'same', or a [pad_h, pad_w] list"
|
68
|
+
)
|
39
69
|
|
40
|
-
|
41
|
-
|
70
|
+
pad_h, pad_w = padding
|
71
|
+
# [0, 0] → VALID
|
72
|
+
if pad_h == 0 and pad_w == 0:
|
73
|
+
return ConvPaddingInfo(ConvPadding.VALID, None)
|
42
74
|
|
43
|
-
|
44
|
-
|
45
|
-
|
75
|
+
# SAME heuristic: output H/W already match input when stride is 1
|
76
|
+
hw_in = tuple(input_shape[1:3])
|
77
|
+
hw_out = tuple(output_shape[1:3])
|
78
|
+
if hw_in == hw_out and stride == [1, 1]:
|
79
|
+
return ConvPaddingInfo(ConvPadding.SAME, None)
|
46
80
|
|
47
|
-
|
81
|
+
# Anything else = explicit symmetric padding
|
82
|
+
return ConvPaddingInfo(ConvPadding.VALID, (pad_h, pad_w))
|
tico/utils/register_custom_op.py
CHANGED
@@ -371,6 +371,113 @@ def CircleDepthwiseConv2dPadding():
|
|
371
371
|
return NHWC_output
|
372
372
|
|
373
373
|
|
374
|
+
def CircleTransposeConv():
|
375
|
+
"""
|
376
|
+
Note that this op follows the input spec of `aten.conv_transpose2d.input` whose number
|
377
|
+
of arguments meets (2 <= node.args <= 8) condition.
|
378
|
+
[RESTRICTION]
|
379
|
+
Therefore, I tried to define a spec of it as transpose_conv(input, weight, *args).
|
380
|
+
But, custom operators in torch do not support positional-only args. So, I set it
|
381
|
+
them as None by default.
|
382
|
+
"""
|
383
|
+
|
384
|
+
@custom_op("circle_custom::transpose_conv", mutates_args=())
|
385
|
+
def transpose_conv(
|
386
|
+
input_: torch.Tensor,
|
387
|
+
weight: torch.Tensor,
|
388
|
+
bias: Optional[torch.Tensor] = None,
|
389
|
+
stride: Optional[List[int]] = None,
|
390
|
+
padding: Optional[List[int]] = None,
|
391
|
+
output_padding: Optional[List[int]] = None,
|
392
|
+
groups: Optional[int] = None,
|
393
|
+
dilation: Optional[List[int]] = None,
|
394
|
+
) -> torch.Tensor:
|
395
|
+
"""
|
396
|
+
Set default values.
|
397
|
+
Custom operators have limited types when it comes to default values.
|
398
|
+
So, let's set them by None in input specs, and then, set it by default values.
|
399
|
+
https://github.com/pytorch/pytorch/blob/6b05aafc/torch/_library/infer_schema.py#L131-L144
|
400
|
+
"""
|
401
|
+
stride = [1, 1] if stride is None else stride
|
402
|
+
padding = [0, 0] if padding is None else padding
|
403
|
+
output_padding = [0, 0] if output_padding is None else output_padding
|
404
|
+
groups = 1 if groups is None else groups
|
405
|
+
dilation = [1, 1] if dilation is None else dilation
|
406
|
+
if groups != 1:
|
407
|
+
raise RuntimeError(
|
408
|
+
f"CircleTransposeConv only supports 1 'groups'. the node's groups: {groups}"
|
409
|
+
)
|
410
|
+
|
411
|
+
NHWC_to_NCHW = [0, 3, 1, 2]
|
412
|
+
OHWI_to_IOHW = [3, 0, 1, 2]
|
413
|
+
NCHW_input = torch.ops.aten.permute.default(input_, NHWC_to_NCHW)
|
414
|
+
OIHW_weight = torch.ops.aten.permute.default(weight, OHWI_to_IOHW)
|
415
|
+
|
416
|
+
args = [
|
417
|
+
NCHW_input,
|
418
|
+
OIHW_weight,
|
419
|
+
bias,
|
420
|
+
stride,
|
421
|
+
padding,
|
422
|
+
output_padding,
|
423
|
+
groups,
|
424
|
+
dilation,
|
425
|
+
]
|
426
|
+
NCHW_output = torch.ops.aten.conv_transpose2d.input(*args)
|
427
|
+
NCHW_to_NHWC = [0, 2, 3, 1]
|
428
|
+
NHWC_output = torch.ops.aten.permute.default(NCHW_output, NCHW_to_NHWC)
|
429
|
+
|
430
|
+
return NHWC_output
|
431
|
+
|
432
|
+
@register_fake("circle_custom::transpose_conv")
|
433
|
+
def _(
|
434
|
+
input_: torch.Tensor,
|
435
|
+
weight: torch.Tensor,
|
436
|
+
bias: Optional[torch.Tensor] = None,
|
437
|
+
stride: Optional[List[int]] = None,
|
438
|
+
padding: Optional[List[int]] = None,
|
439
|
+
output_padding: Optional[List[int]] = None,
|
440
|
+
groups: Optional[int] = None,
|
441
|
+
dilation: Optional[List[int]] = None,
|
442
|
+
):
|
443
|
+
"""
|
444
|
+
Set default values.
|
445
|
+
Custom operators have limited types when it comes to default values.
|
446
|
+
So, let's set them by None in input specs, and then, set it by default values.
|
447
|
+
https://github.com/pytorch/pytorch/blob/6b05aafc/torch/_library/infer_schema.py#L131-L144
|
448
|
+
"""
|
449
|
+
stride = [1, 1] if stride is None else stride
|
450
|
+
padding = [0, 0] if padding is None else padding
|
451
|
+
output_padding = [0, 0] if output_padding is None else output_padding
|
452
|
+
groups = 1 if groups is None else groups
|
453
|
+
dilation = [1, 1] if dilation is None else dilation
|
454
|
+
if groups != 1:
|
455
|
+
raise RuntimeError(
|
456
|
+
f"CircleConv2d only supports 1 'groups'. the node's groups: {groups}"
|
457
|
+
)
|
458
|
+
|
459
|
+
NHWC_to_NCHW = [0, 3, 1, 2]
|
460
|
+
OHWI_to_IOHW = [3, 0, 1, 2]
|
461
|
+
NCHW_input = torch.ops.aten.permute.default(input_, NHWC_to_NCHW)
|
462
|
+
OIHW_weight = torch.ops.aten.permute.default(weight, OHWI_to_IOHW)
|
463
|
+
|
464
|
+
args = [
|
465
|
+
NCHW_input,
|
466
|
+
OIHW_weight,
|
467
|
+
bias,
|
468
|
+
stride,
|
469
|
+
padding,
|
470
|
+
output_padding,
|
471
|
+
groups,
|
472
|
+
dilation,
|
473
|
+
]
|
474
|
+
NCHW_output = torch.ops.aten.conv_transpose2d.input(*args)
|
475
|
+
NCHW_to_NHWC = [0, 2, 3, 1]
|
476
|
+
NHWC_output = torch.ops.aten.permute.default(NCHW_output, NCHW_to_NHWC)
|
477
|
+
|
478
|
+
return NHWC_output
|
479
|
+
|
480
|
+
|
374
481
|
def CircleMaxPool2D():
|
375
482
|
"""
|
376
483
|
Note that this op follows the input spec of `aten.max_pool2d_with_indices.default` whose number
|
@@ -603,6 +710,7 @@ def RegisterOps():
|
|
603
710
|
CircleDepthwiseConv2dPadding()
|
604
711
|
CircleConv2d()
|
605
712
|
CircleConv2dPadding()
|
713
|
+
CircleTransposeConv()
|
606
714
|
CircleMaxPool2D()
|
607
715
|
CircleAvgPool2D()
|
608
716
|
CircleInstanceNorm()
|
@@ -208,6 +208,45 @@ class ConstantPadNdArgs:
|
|
208
208
|
value: int | float
|
209
209
|
|
210
210
|
|
211
|
+
@enforce_type
|
212
|
+
@dataclass
|
213
|
+
class ConvArgs:
|
214
|
+
"""
|
215
|
+
convolution(Tensor input, Tensor weight, Tensor? bias, SymInt[] stride, SymInt[] padding, SymInt[] dilation, bool transposed, SymInt[] output_padding, SymInt groups) -> Tensor
|
216
|
+
"""
|
217
|
+
|
218
|
+
input: torch.fx.Node
|
219
|
+
weight: torch.fx.Node
|
220
|
+
bias: Union[torch.fx.Node, None]
|
221
|
+
stride: List[int]
|
222
|
+
padding: List[int]
|
223
|
+
dilation: List[int]
|
224
|
+
transposed: bool
|
225
|
+
output_padding: List[int]
|
226
|
+
groups: int
|
227
|
+
|
228
|
+
|
229
|
+
@enforce_type
|
230
|
+
@dataclass
|
231
|
+
class ConvTranspose2DArgs:
|
232
|
+
"""
|
233
|
+
conv_transpose2d.input(Tensor input, Tensor weight, Tensor? bias=None, SymInt[2] stride=1, SymInt[2] padding=0, SymInt[2] output_padding=0, SymInt groups=1, SymInt[2] dilation=1) -> Tensor
|
234
|
+
"""
|
235
|
+
|
236
|
+
input: torch.fx.Node
|
237
|
+
weight: torch.fx.Node
|
238
|
+
bias: Union[torch.fx.Node, None] = None
|
239
|
+
stride: List[int] = field(default_factory=lambda: [1, 1])
|
240
|
+
padding: List[int] = field(default_factory=lambda: [0, 0])
|
241
|
+
output_padding: List[int] = field(default_factory=lambda: [0, 0])
|
242
|
+
groups: int = 1
|
243
|
+
dilation: List[int] = field(default_factory=lambda: [1, 1])
|
244
|
+
|
245
|
+
def __post_init__(self):
|
246
|
+
assert len(self.stride) == 2, len(self.stride)
|
247
|
+
assert len(self.dilation) == 2, len(self.dilation)
|
248
|
+
|
249
|
+
|
211
250
|
@enforce_type
|
212
251
|
@dataclass
|
213
252
|
class Conv2DArgs:
|
@@ -1,4 +1,4 @@
|
|
1
|
-
tico/__init__.py,sha256=
|
1
|
+
tico/__init__.py,sha256=OwKeuduBe-XLK_9XzKLwmCWJd6kRwEZ2xiY8RnRGnCA,1743
|
2
2
|
tico/pt2_to_circle.py,sha256=gu3MD4Iqc0zMZcCZ2IT8oGbyj21CTSbT3Rgd9s2B_9A,2767
|
3
3
|
tico/config/__init__.py,sha256=xZzCXjZ84qE-CsBi-dfaL05bqpQ3stKKfTXhnrJRyVs,142
|
4
4
|
tico/config/base.py,sha256=anwOiJFkUxUi7Cef573JgQcjk6S-FSi6O_TLjYASW-g,1244
|
@@ -57,7 +57,7 @@ tico/experimental/quantization/passes/propagate_qparam_forward.py,sha256=RhUHGCR
|
|
57
57
|
tico/experimental/quantization/passes/quantize_bias.py,sha256=ZQ3rETYStpW28JUbODRixbq5sDEOiIOB_qWA-Jzuu-Y,4337
|
58
58
|
tico/experimental/quantization/passes/remove_weight_dequant_op.py,sha256=Klc_9-94tl0_AuAToKOjsWED_YPk5RB67eum0ddPX7o,6588
|
59
59
|
tico/interpreter/__init__.py,sha256=IO6FP_xYbGy0dW0HL26GXD3ouxARaxCK7bz9dn4blPQ,26
|
60
|
-
tico/interpreter/infer.py,sha256=
|
60
|
+
tico/interpreter/infer.py,sha256=1ZFe3DVMR2mlwBosoedqoL0-CGN_01CKLgMgxuw62KA,4861
|
61
61
|
tico/interpreter/interpreter.py,sha256=tGbluCbrehTCqBu8mtGDNzby_ieJ2ry8_RH_eC0CQxk,3828
|
62
62
|
tico/passes/__init__.py,sha256=IO6FP_xYbGy0dW0HL26GXD3ouxARaxCK7bz9dn4blPQ,26
|
63
63
|
tico/passes/cast_aten_where_arg_type.py,sha256=ybtGj1L7_2zGyfb_G-_y1N1mRgKHVq6fBZc-9-fH9sA,7229
|
@@ -79,7 +79,7 @@ tico/passes/fill_meta_val.py,sha256=Xbam6Aq90ZfWItZw1dgLIwH_q8RCiU5JodKNqkj-ink,
|
|
79
79
|
tico/passes/fuse_leading_unsqueeze_reshape.py,sha256=88jwTP35yRyXOk9xdO6YW2OEfdKAws3KFRT16WQz0RI,4291
|
80
80
|
tico/passes/fuse_redundant_reshape_to_mean.py,sha256=GhJS1ZKB6Ns4AhwcW3uUQ6q-0N-AzlD32B2EwusUJHg,3761
|
81
81
|
tico/passes/legalize_causal_mask_value.py,sha256=xKdFwwMaSFCSQpSk8xISOAqFpZ1jIhgbBIqf7KTSGuk,4017
|
82
|
-
tico/passes/legalize_predefined_layout_operators.py,sha256=
|
82
|
+
tico/passes/legalize_predefined_layout_operators.py,sha256=MNx7L2dAlsxSazb-F7c0onPqHleI17zAc7AzQAa9aJ4,18934
|
83
83
|
tico/passes/lower_pow2_to_mul.py,sha256=nfJXa9ZTZMiLg6ownSyvkM4KF2z9tZW34Q3CCWI_vmQ,2402
|
84
84
|
tico/passes/lower_to_resize_nearest_neighbor.py,sha256=N6F56Of8Aiv-KIiYLHnh33WX72W60ZVQSBEYWHdYqNQ,9005
|
85
85
|
tico/passes/lower_to_slice.py,sha256=0qAX3WzZdyMFDW4DiO9b5JFXd4rL1-0doBT6lJvaw_I,7260
|
@@ -115,11 +115,11 @@ tico/serialize/operators/op_cat.py,sha256=XDYOh0XAyrM0TlxVm6Sa0OFFGrKk7aSDcGXC-h
|
|
115
115
|
tico/serialize/operators/op_clamp.py,sha256=ZRAsXLGsZqJEh4wXxESEpRJkRtUuJWTDgAem6lr9_5I,4298
|
116
116
|
tico/serialize/operators/op_clone.py,sha256=vzDYJ8TS3tc2BAyd_z8nt5VqT1inpymSseMEhd9dva0,2394
|
117
117
|
tico/serialize/operators/op_constant_pad_nd.py,sha256=OpP4AP-d1IFcWZolNa-o9ZxzXJQkMdG9WQ66soX3s-E,2675
|
118
|
-
tico/serialize/operators/op_conv2d.py,sha256=
|
118
|
+
tico/serialize/operators/op_conv2d.py,sha256=UfYk5xnA9PqVYyjU9dUCSW0CiCmcEK3LnlnFh0WY4Gg,6599
|
119
119
|
tico/serialize/operators/op_copy.py,sha256=vaianLQ19-2ZQZ-MdQ07YuOPeFeo_HAx2a0Qfn7I5Kk,6122
|
120
120
|
tico/serialize/operators/op_cos.py,sha256=N12bNyuTQIxRnD0eHRPdFVzRQPMy1NFM4iM8oQ4lYzw,2034
|
121
121
|
tico/serialize/operators/op_cumsum.py,sha256=3fmOf1mIeCX1uhTBcSJmRGXejzLtO8UwaI1eEQDC6nA,3798
|
122
|
-
tico/serialize/operators/op_depthwise_conv2d.py,sha256=
|
122
|
+
tico/serialize/operators/op_depthwise_conv2d.py,sha256=wH1SFjhWJdJrb8xi2qCiCeSWNxlL8IjEwALGCxTQxbc,7034
|
123
123
|
tico/serialize/operators/op_dequantize_per_channel.py,sha256=aPcVxjdgvfSFoLnv9NL-RxO5vZYj8ulqriMP5LHIWs0,3133
|
124
124
|
tico/serialize/operators/op_dequantize_per_tensor.py,sha256=u9aK_Xle9rDN0EHLE0YrCTlXY4Q53Ch9Di4qmx7ynps,2304
|
125
125
|
tico/serialize/operators/op_div.py,sha256=WjeM2Ux7TyGlSNx2aVC783JvcL0xnY6FBYo1Q_kdb5Q,2201
|
@@ -175,32 +175,34 @@ tico/serialize/operators/op_sub.py,sha256=yZskQJF0ylXVk02Uid8djPNIWDJ-0uHJar4UYh
|
|
175
175
|
tico/serialize/operators/op_sum.py,sha256=B5aSwQMhyoBe2JYdE5nVQ3QeVDSzL-yuZZujsG08OdQ,2294
|
176
176
|
tico/serialize/operators/op_tanh.py,sha256=rs7FsbQeUQ7Ak8RoQV9ymNGXHXRObojfY_SiqJiyqdA,1846
|
177
177
|
tico/serialize/operators/op_to_copy.py,sha256=a8T0uPMavMO_md1a-4_0dlvDHyZS_xew0qB6xjf69rI,3934
|
178
|
+
tico/serialize/operators/op_transpose_conv.py,sha256=YDObXXaHNOD7yjO1ccaB_NCfc5-L76ClvT3pduL8E90,5631
|
178
179
|
tico/serialize/operators/op_unsqueeze.py,sha256=ZHhfVXSWEiwb2VDYX5uhxbGQyzZjKT7CrbBpVGxVHBU,2310
|
179
180
|
tico/serialize/operators/op_view.py,sha256=5EMww-ve17Vm9XPuV03Tn7vJsjpU2J8U4d_FOrlm9_o,2546
|
180
181
|
tico/serialize/operators/op_where.py,sha256=doE81GSwygrPBm3JIfN9w7kKXxeIYKxgk0eoY22QIcg,2845
|
181
182
|
tico/serialize/operators/utils.py,sha256=lXGpEJW1h8U_-gfc6EWjvvSiq3yJ9P-v1v3EMRT_pSk,2954
|
182
183
|
tico/utils/__init__.py,sha256=IO6FP_xYbGy0dW0HL26GXD3ouxARaxCK7bz9dn4blPQ,26
|
183
|
-
tico/utils/convert.py,sha256=
|
184
|
+
tico/utils/convert.py,sha256=5C8Z2ia2XN4k3XgtJrFZYJSEejoeMllyr8YW6gwu9mw,12763
|
184
185
|
tico/utils/define.py,sha256=Ypgp7YffM4pgPl4Zh6TmogSn1OxGBMRw_e09qYGflZk,1467
|
185
186
|
tico/utils/diff_graph.py,sha256=_eDGGPDPYQD4b--MXX0DLoVgSt_wLfNPt47UlolLLR4,5272
|
186
187
|
tico/utils/errors.py,sha256=f3csJjgbXG9W1aHhqEcou008Aor19W57X8oT5Hx8w1M,954
|
187
188
|
tico/utils/graph.py,sha256=Y6aODsnc_-9l61oanknb7K1jqJ8B35iPypOKkM0Qkk0,9149
|
189
|
+
tico/utils/installed_packages.py,sha256=J0FTwnkCGs0MxRWoCMYAqiwH7Z0GWFDLV--x-IndSp4,1017
|
188
190
|
tico/utils/logging.py,sha256=IlbBWscsaHidI0dNqro1HEXAbIcbkR3BD5ukLy2m95k,1286
|
189
191
|
tico/utils/model.py,sha256=Uqc92AnJXQ2pbvctS2z2F3Ku3yNrwXZ9O33hZVis7is,1250
|
190
|
-
tico/utils/padding.py,sha256=
|
192
|
+
tico/utils/padding.py,sha256=qk6eh295msjDl3yFRg2OAjF-p6q0B8U2u_rnB2odT2A,3024
|
191
193
|
tico/utils/passes.py,sha256=kGmDe__5cPaO6i5EDAoXSVe6yXEoX9hAny4ROb3ZEmQ,2409
|
192
|
-
tico/utils/register_custom_op.py,sha256=
|
194
|
+
tico/utils/register_custom_op.py,sha256=3-Yl6iYmx1qQA2igNHt4hYhQhQMkdPb7gF50LIY8yvc,27350
|
193
195
|
tico/utils/serialize.py,sha256=AQXMBOLu-Kg2Rn-qbqsAtHndjZAZIavlKA0QFgJREHM,1420
|
194
196
|
tico/utils/trace_decorators.py,sha256=ddLIiKQfSaQrxgF1kNpwjFTQnXENzeSfcr1kuAW4jGI,3221
|
195
197
|
tico/utils/utils.py,sha256=fnbZ2RLH6-J-wqb32O4qsR1ce4BJU0wYNrk84QXa6_E,13158
|
196
|
-
tico/utils/validate_args_kwargs.py,sha256=
|
198
|
+
tico/utils/validate_args_kwargs.py,sha256=cJAK6aqdzK3_Xccu6K1FQ32WGdmwWA_SqJ--TPavIuk,26614
|
197
199
|
tico/utils/mx/__init__.py,sha256=IO6FP_xYbGy0dW0HL26GXD3ouxARaxCK7bz9dn4blPQ,26
|
198
200
|
tico/utils/mx/elemwise_ops.py,sha256=V6glyAHsVR1joqpsgnNytatCD_ew92xNWZ19UFDoMTA,10281
|
199
201
|
tico/utils/mx/formats.py,sha256=uzNWyu-1onUlwQfX5cZ6fZSUfHMRqorper7_T1k3jfk,3404
|
200
202
|
tico/utils/mx/mx_ops.py,sha256=RcfUTYVi-wilGB2sC35OeARdwDqnixv7dG5iyZ-fQT8,8555
|
201
|
-
tico-0.1.0.
|
202
|
-
tico-0.1.0.
|
203
|
-
tico-0.1.0.
|
204
|
-
tico-0.1.0.
|
205
|
-
tico-0.1.0.
|
206
|
-
tico-0.1.0.
|
203
|
+
tico-0.1.0.dev250702.dist-info/LICENSE,sha256=kp4JLII7bzRhPb0CPD5XTDZMh22BQ7h3k3B7t8TiSbw,12644
|
204
|
+
tico-0.1.0.dev250702.dist-info/METADATA,sha256=y6E2HN1pWGO-n-xqv9GGXkNHhNbvY7d9iIA-lWVlaZE,8846
|
205
|
+
tico-0.1.0.dev250702.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
206
|
+
tico-0.1.0.dev250702.dist-info/entry_points.txt,sha256=kBKYSS_IYrSXmUYevmmepqIVPScq5vF8ulQRu3I_Zf0,59
|
207
|
+
tico-0.1.0.dev250702.dist-info/top_level.txt,sha256=oqs7UPoNSKZEwqsX8B-KAWdQwfAa7i60pbxW_Jk7P3w,5
|
208
|
+
tico-0.1.0.dev250702.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|