1dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung#!/usr/bin/python3
2dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
3dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Copyright 2017, The Android Open Source Project
4dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung#
5dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Licensed under the Apache License, Version 2.0 (the "License");
6dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# you may not use this file except in compliance with the License.
7dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# You may obtain a copy of the License at
8dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung#
9dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# http://www.apache.org/licenses/LICENSE-2.0
10dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung#
11dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Unless required by applicable law or agreed to in writing, software
12dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# distributed under the License is distributed on an "AS IS" BASIS,
13dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# See the License for the specific language governing permissions and
15dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# limitations under the License.
16dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
17dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung"""NN model compiler
18dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
19dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) SungCompile models and examples into NDK-based CTS unit tests
20dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung"""
21dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
22dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungfrom __future__ import absolute_import
23dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungfrom __future__ import division
24dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungfrom __future__ import print_function
25dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungimport argparse
264c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungfrom functools import reduce
273ed926a99e4057d573807e5fc4eb8acc6295f635Dong Chenimport math
28dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungimport os
294c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungimport struct
30dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungimport sys
31dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungimport contextlib
324062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sungimport pprint
33dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
34dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung@contextlib.contextmanager
35dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungdef smart_open(filename=None):
36dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  if filename and filename != '-':
37dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    fh = open(filename, 'w')
38dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  else:
39dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    fh = sys.stdout
40dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
41dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  try:
42dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    yield fh
43dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  finally:
44dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if fh is not sys.stdout:
45dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      fh.close()
46dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
47dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Phase(object):
48dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self):
494c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    self.__objects = []
50dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__contents = []
516a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    self.__dict_of_objects = {}
52dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
534c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def append(self, obj, x):
544c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    self.__objects.append(obj)
55dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__contents.append(x)
566a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    self.__dict_of_objects[obj.ID()] = obj
57dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
58dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump(self, filename):
59dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for x in self.__contents:
60dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ("  " + x + ";", file=filename)
61dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
624c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def objects(self):
634c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return self.__objects
644c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
656a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  def search(self, i):
666a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    return self.__dict_of_objects[i]
676a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung
68dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Tracking objects inside a model with a not necessarily unique name and
69dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# an unique number
70dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass NamedObject(object):
71dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __serial = 0
72dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
73dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name = "NamedObject"):
74dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__name = name
75dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__id = NamedObject.serial()
76dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    NamedObject.__serial += 1
77dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
78dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def ID(self):
79dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__id
80dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
81dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def serial():
82dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return NamedObject.__serial
83dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
84dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_name(self):
85dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__name
86dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
87dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __str__(self):
88dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.get_name()
89dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
90dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __hash__(self):
91dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__id
92dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
93dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Object that can be traversed during topological sorting phase
94dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Traversable(object):
95dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def traversable(self):
96dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return True
97dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
98dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Nontraversable(object):
99dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def traversable(self):
100dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return False
101dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
102dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Object that can take input from other objects
103dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Uses(object):
104dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  all_uses = set()
105dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, ins = []):
106dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.ins = ins.copy()
107dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.all_uses.add(self)
108dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for i in ins:
10997c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung      i.outs.append(self)
110dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
111dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Object that other objects takes its definition from
112dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Definitions(object):
113dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, outs = []):
11497c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung    self.outs = outs.copy()
115dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for o in outs:
116dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      o.ins.append(self)
117dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
1184c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungclass TypeLookup:
1194c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  __type_lookup = {
1204c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "INT32": "int32_t",
1210231b5bff82575668f8cf6e3d19207dd68a77ac9I-Jui (Ray) Sung      "UINT32": "uint32_t",
1224c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "FLOAT32": "float",
1234c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "TENSOR_INT32": "int32_t",
1244c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "TENSOR_FLOAT32": "float",
1254c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "TENSOR_QUANT8_ASYMM": "uint8_t",
1260231b5bff82575668f8cf6e3d19207dd68a77ac9I-Jui (Ray) Sung#     "OEM_SCALAR": this is service-defined.
1270231b5bff82575668f8cf6e3d19207dd68a77ac9I-Jui (Ray) Sung      "TENSOR_OEM_BYTE": "uint8_t",
1284c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }
1294c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1304c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def get_cpptype(nnapi_type):
1314c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return TypeLookup.__type_lookup[nnapi_type]
1324c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1334c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def is_float(nnapi_type):
1344c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return TypeLookup.get_cpptype(nnapi_type) == "float"
1354c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1364c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def get_size(nnapi_type):
1374c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return 1 if TypeLookup.get_cpptype(nnapi_type) == "uint8_t" else 4
1384c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1394c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
140dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Type(object):
141dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __types =  {}
142dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __type_serial = 0 # types have their own numbering
143dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, vt = None, shape = None):
144dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__vt = vt
145dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__shape = shape
146dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if vt is None or shape is None:
147dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__name = None
148dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      return
149dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
150dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    key = str(self)
151dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if key not in Type.__types:
152dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__id = Type.__type_serial
153dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      Type.__types[str(self)] = self
154dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      Type.__type_serial += 1
155dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    else:
156dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__id = Type.__types[key].__id
157dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__name = "type" + str(self.__id)
158dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
1594c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def get_shape(self):
1604c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return self.__shape
1614c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
162ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung  def get_element_type(self):
163ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung    return self.__vt
164ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
165dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_name(self):
166dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__name
167dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
168dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __str__(self):
169dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return (", ".join([self.__vt, self.__shape]))
170dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
171dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __hash__(self):
172dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__id
173dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
174dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump(filename):
175dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for key, value in sorted(Type.__types.items()):
176dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ("  OperandType " + str(value.__name) + "(Type::" + str(key) + ");", file=filename)
177dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
1784062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  def get_raw_shape(self):
1794062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    return self.__shape
1804062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung
181420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung  def get_parsed_shape(self):
1824c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    # Parse shape
1834c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    if (self.__shape != "" and self.__shape != "{}"):
1844c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      left, sep, right = self.__shape.partition('{')
1854c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      real_shape, sep, right = right.partition('}')
1864c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      shape = [int(x) for x in real_shape.split(",")]
187420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung      # left now looks like "0.0f, 127.5f, "
1889fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang      scale, sep, zero_point = right.rpartition(',')
1899fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang      if scale == "":
1909fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang        if zero_point == "":
1919fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang          return real_shape, "0", "0"
1929fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang        return real_shape, zero_point, "0"
1939fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang      left, sep, scale = scale.partition(',')
1949fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang      return real_shape, scale.replace("f", ""), zero_point
195420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung    else:
1969fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang      return "", "0", "0"
197420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung
1984062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  def get_nr_elements(self):
199420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung    # Parse shape
200420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung    nr_elements = 1
2019fd99905f7dcb2cd4195d2670aded45fc49cc1cbMiao Wang    real_shape, scale, zero_point = self.get_parsed_shape()
202420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung
203420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung    if (real_shape != "" and real_shape != "{}"):
204420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung      shape = [int(x) for x in real_shape.split(",")]
2054c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      nr_elements = reduce((lambda x, y: x*y), shape)
2064062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    return nr_elements
2074062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung
2084062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  def get_size(self):
2094062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    element_size = TypeLookup.get_size(self.__vt)
2104062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    return self.get_nr_elements() * element_size
211dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
212dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A value is a typed, named object
213dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Value(NamedObject):
214dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt):
215dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    NamedObject.__init__(self, name)
216dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.type = vt
217dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
218dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# An operand that can be fed into operations. Also, an operand is always
219dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# declared before operations.
220dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Operand(Value):
221dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # All operand declarations in string
222dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  operands = Phase()
223dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
224dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt):
225dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Value.__init__(self, name, vt)
226dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    def_string = (
227dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung        "auto " + self.get_name() + " = "\
228dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung            "model->addOperand(&" + vt.get_name() + ")")
2294c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    Operand.operands.append(self, def_string)
230dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
231dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # By default, produce nothing (when asked by the Topological Sort phase)
232dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Definition(self):
233dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    pass
234dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
235dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Reference(self):
236dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return NamedObject.__str__(self)
237dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
238dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # Print a set of operands in curly braces
239dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def print_operands(operands):
240dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return [ x.Reference() for x in operands ]
241dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
2424c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  # Defined with the model or not
2434c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def is_weight(self):
2444c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return False
2454c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
246dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A user-declared input operand
247dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Input(Operand, Definitions, Traversable):
248cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  # for enumerating inputs
249cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  __next_number = 0
250dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # Holds reference to all Inputs; used by Topoligcal sort as starting nodes.
251dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __inputs = set()
252dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
253297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung  def __init__(self, name, vt, shape, increase_next_number=True):
254dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, name, Type(vt, shape))
255dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self)
256dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Input.__inputs.add(self)
257cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung    self.number = Input.__next_number
258297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung    if increase_next_number is True:
259297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung      Input.__next_number += 1
260dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
261a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet  def lifetime(self):
262a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    return "MODEL_INPUT"
263a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet
264dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def is_internal(self):
265dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return False
266dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
267dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_inputs(exclude_internal = None):
268dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if exclude_internal is not None:
269dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      external = { x for x in Input.__inputs if not x.is_internal() }
270dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      return external
271dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    else:
272dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      return Input.__inputs
273dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
274dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A user-declared output operand
275dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Output(Operand, Uses, Nontraversable):
276cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  # for enumerating outputs
277cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  __next_number = 0
27897c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung  __outputs = []
279dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
280dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt, shape):
281dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, name, Type(vt, shape))
282dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self)
28397c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung    Output.__outputs.append(self)
284cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung    self.number = Output.__next_number
285cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung    Output.__next_number += 1
286dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
287a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet  def lifetime(self):
288a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    return "MODEL_OUTPUT"
289a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet
29097c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung  # return all unique outputs in the original order
291dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_outputs():
29297c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung    saw = set()
29397c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung    unique = [x for x in Output.__outputs if x not in saw and (saw.add(x) or True)]
29497c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung    return unique
295dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
296ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung# An output that we don't want to compare the results
297ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sungclass IgnoredOutput(Output):
298ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung  __ignored = set()
299ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung  def __init__(self, name, vt, shape):
300ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung    Output.__init__(self, name, vt, shape)
301ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung    IgnoredOutput.__ignored.add(self)
302ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung  def gen_ignored():
303ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung    ignored_func = """
304ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sungbool is_ignored(int i) {
305ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung  static std::set<int> ignore = {%s};
306ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung  return ignore.find(i) != ignore.end();
307ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung}""" % ", ".join([str(x.number) for x in IgnoredOutput.__ignored])
308ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung    return ignored_func
309ec8e1c71d11f7b5abe306e0c9c6af7da755bd46bI-Jui (Ray) Sung
310dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass ModelArgument:
311dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __arguments = []
312dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
313dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, arg_type, arg_name):
314dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__arg_type = arg_type
315dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__arg_name = arg_name
316dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ModelArgument.__arguments.append(" ".join([arg_type, arg_name]))
317dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
318dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_arg_type(self):
319dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__arg_type
320dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
321dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_arg_name(self):
322dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__arg_name
323dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
324dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_arguments():
325dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return ModelArgument.__arguments
326dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
327a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet  def lifetime(self):
328a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    return "CONSTANT_COPY"
329ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
330297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung# Print in C float literal format
331297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sungdef pretty_print_as_float(x):
332297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung  s = str(float(x))
333297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung  if s.find(".") >= 0 or s.find("e") >= 0:
334297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung    return s + "f"
335297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung  else:
336297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung    return s + ".0f"
337297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung
338ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sungclass Parameter(Input):
339a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet  # TODO seems wrong that's an Input.
340dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt, shape, initializer):
341297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung    Input.__init__(self, name, vt, shape, False)
342dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.initializer = initializer
343ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung    self.cpptype = TypeLookup.get_cpptype(vt)
344dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def is_internal(self):
345dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return True
346dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Definition(self):
347dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    init_name = self.get_name() + "_init"
348dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    initializer = [str(x) for x in self.initializer]
349dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if self.cpptype == "float":
350297c580a2d2da2839d936437bf4e3a4c64034950I-Jui (Ray) Sung      initializer = [ pretty_print_as_float(x) for x in initializer]
351dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    init = self.cpptype + " " + init_name + "[]"
352dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    init = "static " + init + " = {" + ", ".join(initializer) + "};"
353dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    args = [ self.get_name(), init_name,
354dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung            "sizeof(" + self.cpptype + ") * " + str(len(self.initializer)) ]
355dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    stmt = "\n  ".join([init,
356dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung                      "model->setOperandValue(" + ", ".join(args)+");"])
357dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return stmt
3584c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def is_weight(self):
3594c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return True
360a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet  def lifetime(self):
361dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    if Configuration.useSHM():
362dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung      return "CONSTANT_REFERENCE"
363dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    else:
364dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung      return "CONSTANT_COPY"
365dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
366cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sungclass Int32Scalar(Parameter):
367dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, value):
3684c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    Parameter.__init__(self, name, "INT32", "{}", [value])
369dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
370cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sungclass Float32Scalar(Parameter):
371dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, value):
3724c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    Parameter.__init__(self, name, "FLOAT32", "{}", [value])
373dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
374dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A compiler-generated intermediate result from an operation
375dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass IntermediateResult(Operand, Definitions, Uses, Traversable):
376dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, src: Value):
377dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    tmp_name = "tmp" + str(NamedObject.serial())
378dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, tmp_name, src.type)
379dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self)
380dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self, [src])
381dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
382a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet  def lifetime(self):
383a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    return "TEMPORARY_VARIABLE"
384a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet
385dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# An explicitly declared intermediate result
386dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Internal(Operand, Definitions, Uses, Traversable):
387dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt, shape):
388dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, name, Type(vt, shape))
389dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self)
390dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self)
391dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
392a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet  def lifetime(self):
393a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    return "TEMPORARY_VARIABLE"
394a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet
395dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# An operation in a model
3964c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungclass Operation(Definitions, Uses, Traversable):
397dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, optype, ins, outs):
3984c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    self.type = ins[0].type
399dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self, outs)
400dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self, ins)
401dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.optype = optype
402dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
403dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __str__(self):
404dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    inputs = [ str(x) for x in self.ins ]
405dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return "Operation:" + self.optype + " " + ", ".join(inputs)
406dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
407dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Reference(self):
408dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return "operation" + str(self.ID());
409dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
410dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Definition(self):
411dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    inputs = Operand.print_operands(self.ins);
412dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outputs = Operand.print_operands(self.outs);
413dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return "model->addOperation(ANEURALNETWORKS_"+self.optype+", " + \
414dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung        "{"+", ".join(inputs)+"}, {" + ", ".join(outputs) + "});"
415dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
4164062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  # Get Python-ish dump for the op
4174062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  def PyDefinition(self):
4184062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    py_op_string = """Operation("{optype}", {inputs}).To({outputs})"""
4194062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    inputs = [str(x) for x in Operand.print_operands(self.ins)]
4204062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    inputs = ", ".join(inputs)
4214062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    assert len(self.outs) <= 1
4224062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    outputs = str(Operand.print_operands(self.outs)[0])
4234062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    ops = {"optype": self.optype, "inputs": inputs, "outputs": outputs}
4244062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    return py_op_string.format(**ops)
4254062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung
426dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Main interface
427dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Model(object):
428b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang  __isRelaxed = False
429b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang
430dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self):
431dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = None
432dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
433dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # TODO turn this into generic binary operations
434dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Add(self, i1: Value, i2 = None) -> Operation:
435dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i1]
436dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if i2 is not None:
437dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      ins.append(i2)
438dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if self.__currentOp is not None:
439dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      ir = IntermediateResult(self.__currentOp)
440dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__currentOp = ir
441dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      ins.append(self.__currentOp)
442dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
443dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("ADD", ins, [])
444dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
445dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
446dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
447dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
448dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Operation(self, op_name, *args):
449dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i for i in args]
450dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
451dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation(op_name, ins, outs)
452dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
453dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
454dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
455dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def RawAdd(self, i1: Value, i2: Value, o = None) -> Operation:
456dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i1, i2]
457dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
458dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if o is not None:
459dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      outs = [o]
460dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("ADD", ins, outs)
461dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
462dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
463dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
464dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
465dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # See CpuExecutor::executeOperation() for the arguments of each op
466dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def AveragePool(self, input, padding, stride_width, stride_height, filter_width, filter_height, activation):
467dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, padding, stride_width,
468dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, filter_width, filter_height, activation]
469dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
47055cef2193279a646292fdeb355399627dd8990c8Miao Wang    op = Operation("AVERAGE_POOL_2D", ins, outs)
471dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
472dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
473dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
474dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Concatenation(self, *args):
475dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i for i in args]
476dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
477dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("CONCATENATION", ins, outs)
478dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
479dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
480dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
481dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Conv(self, filter, bias, input, padding, stride_width, stride_height, activation):
482dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [filter, bias, input, padding, stride_width,
483dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, activation]
484dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
48555cef2193279a646292fdeb355399627dd8990c8Miao Wang    op = Operation("CONV_2D", ins, outs)
486dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
487dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
488dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
489dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def DepthWiseConv(self, filter, bias, input, padding, stride_width, stride_height, depth_multiplier, activation):
490dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [filter, bias, input, padding, stride_width,
491dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, depth_multiplier, activation]
492dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
49355cef2193279a646292fdeb355399627dd8990c8Miao Wang    op = Operation("DEPTHWISE_CONV_2D", ins, outs)
494dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
495dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
496dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
497dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def FullyConnected(self, input, weights, bias, activation):
498dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, weights, bias, activation]
499dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
500dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("FULLY_CONNECTED", ins, outs)
501dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
502dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
503dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
504dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Logistic(self, input):
505dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input]
506dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
507dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("LOGISTIC", ins, outs)
508dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
509dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
510dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
511dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def L2Pool(self, input, padding, stride_width, stride_height, filter_width, filter_height, activation):
512dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, padding, stride_width,
513dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, filter_width, filter_height, activation]
514dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
51555cef2193279a646292fdeb355399627dd8990c8Miao Wang    op = Operation("L2_POOL_2D", ins, outs)
516dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
517dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
518dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
519dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def MaxPool(self, input, padding, stride_width, stride_height, filter_width, filter_height, activation):
520dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, padding, stride_width,
521dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, filter_width, filter_height, activation]
522dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
52355cef2193279a646292fdeb355399627dd8990c8Miao Wang    op = Operation("MAX_POOL_2D", ins, outs)
524dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
525dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
526dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
527dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def SoftMax(self, input, beta):
528dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, beta]
529dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
530dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("SOFTMAX", ins, outs)
531dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
532dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
533dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
534b3ea13a8e7b607d78cceae07a000df073e1520eaMiao Wang  def Reshape(self, input, shape):
535b3ea13a8e7b607d78cceae07a000df073e1520eaMiao Wang    ins = [input, shape]
536b3ea13a8e7b607d78cceae07a000df073e1520eaMiao Wang    outs = []
537b3ea13a8e7b607d78cceae07a000df073e1520eaMiao Wang    op = Operation("RESHAPE", ins, outs)
538b3ea13a8e7b607d78cceae07a000df073e1520eaMiao Wang    self.__currentOp = op
539b3ea13a8e7b607d78cceae07a000df073e1520eaMiao Wang    return self
540b3ea13a8e7b607d78cceae07a000df073e1520eaMiao Wang
5416a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  def Out(self, o):
5426a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    if (type(o) is list or type(o) is tuple):
5436a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      for i in o:
54497c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung        self.__currentOp.outs.append(i)
5456a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        i.ins.append(self.__currentOp)
5466a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    else:
54797c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung      self.__currentOp.outs.append(o)
5486a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      o.ins.append(self.__currentOp)
549dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
550dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
551dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def To(self, o:Value):
552dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ret = Model.Out(self, o)
553dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = None
554dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
555dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
556b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang  def RelaxedExecution(self, isRelaxed):
557b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang    Model.__isRelaxed = isRelaxed
558b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang    return self
559b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang
560b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang  def isRelaxed():
561b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang    return Model.__isRelaxed
562b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang
563b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang
564ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sungclass FileNames:
565ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung  SpecFile = ""
566ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
567dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Example():
568dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __examples = []
569dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, list_of_examples):
570dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Example.__examples.append(list_of_examples)
571dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
572dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump_dict(d):
573dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ret = []
574dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for k, v in d.items():
575cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung      key = str(k)
576ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung      suffix = "f"
577cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung      if type(k) is not int:
578cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung        key = str(k.number)
579ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung        if not TypeLookup.is_float(k.type.get_element_type()):
580ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung          suffix = ""
5816a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      init = ", ".join(
5826a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung          [str(i) + (suffix if str(i).find(".") != -1 else "") for i in v])
5836a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      ret.append("{%s, {%s}}" % (key, init))
584dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return ", ".join(ret)
585dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
5866a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  def dump_mixed_types(d):
5876a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    ret = []
5886a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung
5896a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    float32_dict = {}
5906a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    int32_dict = {}
5916a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    uint8_dict = {}
5926a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung
5936a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    for k, v in d.items():
5944062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      key_id = k.ID() if type(k) is not int else k
5954062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      ty = Operand.operands.search(key_id).type.get_element_type()
5966a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      # find out type of the operand addressed by the key
5976a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      if (ty == "TENSOR_FLOAT32"):
5986a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        float32_dict[k] = v
5996a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      elif (ty == "TENSOR_INT32"):
6006a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        int32_dict[k] = v
601b69da689183dd8258461d3c4326ddfa2d12cdc07I-Jui (Ray) Sung      elif (ty == "TENSOR_OEM_BYTE"):
602b69da689183dd8258461d3c4326ddfa2d12cdc07I-Jui (Ray) Sung        uint8_dict[k] = v
6036a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      elif (ty == "TENSOR_QUANT8_ASYMM"):
6046a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        uint8_dict[k] = v
6056a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      else:
6066a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        print ("Unhandled type %s"%ty,  file = sys.stderr)
6076a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        assert 0 and "unsupported example type"
6086a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung
6096a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    tuple_init = """\
6106a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung{{ // See tools/test_generator/include/TestHarness.h:MixedTyped
6116a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  // int -> FLOAT32 map
6126a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  {{{float32_dict}}},
6136a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  // int -> INT32 map
6146a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  {{{int32_dict}}},
6156a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  // int -> QUANT8_ASYMM map
6166a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung  {{{uint8_dict}}}
6176a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung}}"""
6186a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    tuple_contents = {
6196a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        'float32_dict': Example.dump_dict(float32_dict),
6206a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        'int32_dict': Example.dump_dict(int32_dict),
6216a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung        'uint8_dict': Example.dump_dict(uint8_dict)
6226a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    }
6236a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung    return tuple_init.format(**tuple_contents)
6246a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung
6256a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung
626dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump(example_file):
627dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if len(Example.__examples) > 0:
628ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung      spec_file = " (from: %s)" % (FileNames.SpecFile)
629ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung      print ('// Generated file%s. Do not edit' % (spec_file),
630ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung             file = example_file)
631dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for i, o in Example.__examples:
632dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('// Begin of an example', file = example_file)
633dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('{', file = example_file)
6346a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      inputs = Example.dump_mixed_types(i)
6356a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      outputs = Example.dump_mixed_types(o)
6366a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      print ('//Input(s)\n%s,' % inputs , file = example_file)
6376a0d306cf902e13ab147c7533b2cb02540ee66d5I-Jui (Ray) Sung      print ('//Output(s)\n%s' % outputs, file = example_file)
638dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('}, // End of an example', file = example_file)
639dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
6404062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  # Similar to dump_dict, but in python. Used by the slicing tool
6414062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  # if referenced is not None, only print operands that are present there
6424062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  def py_dump_dict(d, referenced):
6434062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    ret = []
6444062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    for k, v in d.items():
6454062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      if referenced != None and k not in referenced:
6464062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        continue
6474062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      key = str(k)
6484062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      init = pprint.pformat(v)
6494062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      ret.append("%s: %s" % (key, init))
6504062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    return ", ".join(ret)
6514062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung
6524062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  # similar to dump, but in python. Used by the slicing tool
6534062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  # if referenced is not None, only print operands that are present there
6544062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  def py_dump(example_file, override, referenced):
6554062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    if len(Example.__examples) > 0:
6564062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      example_no = 0
6574062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      example_template = """\
6584062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sunginput{no} = {{{inputs}}}
6594062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung# Only executed during data collection phase
6604062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sungif collecting_data is True:
6614062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  Example((input{no}, {{{outputs}}}))
6624062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung"""
6634062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      for i, o in Example.__examples:
6644062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        print ('# Begin of an example', file = example_file)
6654062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        inputs = Example.py_dump_dict(i, referenced)
6664062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        output_list = []
6674062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        for k, v in override.items():
6684062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung          output_list.append("%s: [0] * %d" % (k, v))
6694062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        outputs = ",".join(output_list)
6704062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung
6714062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        # TODO: handle >1 outputs
6724062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        for k, v in o.items():
6734062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung          assert k.number == 0
6744062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        example_contents = {
6754062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung            'no': example_no,
6764062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung            'inputs': inputs,
6774062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung            'outputs': outputs
6784062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        }
6794062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung        print (example_template.format(**example_contents), file = example_file)
6804062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung
6814062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung
6824c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef TopologicalSort(format_op):
683dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  start = Input.get_inputs().copy()
684dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  deps = { x: set(x.ins) for x in Uses.all_uses }
685dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
686dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  while len(start) > 0:
687dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    cur = start.pop()
6884062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung    if format_op(cur) is False:
6894062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung      return
69097c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung    distinct_outs = set(cur.outs)
69197c70d256b07031a8dc2e7f074249dda17b8c78eI-Jui (Ray) Sung    for o in distinct_outs:
692dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      deps[o].remove(cur)
693dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      if len(deps[o]) == 0 and o.traversable():
694dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung        start.add(o)
695dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
6964c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungclass Configuration:
697dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung  use_shm_for_weights = False
698dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung  def useSHM():
699dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    return Configuration.use_shm_for_weights
700ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
701dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Take a model from command line
702dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungdef import_source():
703dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  parser = argparse.ArgumentParser()
7044c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  parser.add_argument("spec", help="the spec file")
7054c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  parser.add_argument(
7064c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "-m", "--model", help="the output model file", default="-")
7074c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  parser.add_argument(
7084c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "-e", "--example", help="the output example file", default="-")
709dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  args = parser.parse_args()
710dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
711dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  if os.path.exists(args.spec):
712ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung    FileNames.SpecFile = os.path.basename(args.spec)
7134c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    exec (open(args.spec).read())
714dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
715dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  return (args.model, args.example)
716dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
717420cf7bdb689bc53b2a4e8c5f9eca42f7a06c1c0I-Jui (Ray) Sung
7184c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef print_cts_op(model_file, op):
7194c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  fmt = op.Definition()
7204c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  if fmt is not None:
7214c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    print ("  %s" % fmt, file = model_file)
7224062279c74f2c995349b7ff04f22feb89eb81e47I-Jui (Ray) Sung  return True
7234c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
724dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungif __name__ == '__main__':
725dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  (model, example) = import_source()
726dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # Boilerplate
727dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  args = ""
728dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  if len(ModelArgument.get_arguments()) > 0:
729dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    args = ", " + ", ".join(ModelArgument.get_arguments())
730dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
731dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung  print("Output CTS model: %s" % model, file=sys.stderr)
732dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung  print("Output example:" + example, file=sys.stderr)
733dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung
734dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung  with smart_open(model) as model_file:
735dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    spec_file = " (from: %s)" % (FileNames.SpecFile)
736dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung
737dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ('// Generated file%s. Do not edit'%(spec_file), file = model_file)
738dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ("void CreateModel(Model *model" + args + ") {", file=model_file)
739dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung
740dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    # Phase 0: types
741dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    Type.dump(model_file)
742dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    # Phase 1: add operands
743dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ("  // Phase 1, operands", file=model_file)
744dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    Operand.operands.dump(model_file)
745dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung
746dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    # Phase 2: operations
747dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ("  // Phase 2, operations", file=model_file)
748dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    TopologicalSort(lambda x: print_cts_op(model_file, x))
749dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung
750dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    # Phase 3: add inputs and outputs
751dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ("  // Phase 3, inputs and outputs", file=model_file)
752dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    inputs = Operand.print_operands(Input.get_inputs(True));
753dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    outputs = Operand.print_operands(Output.get_outputs());
754dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ("  model->identifyInputsAndOutputs(\n" +
755dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung           "    {"+", ".join(inputs)+"},\n    {" + ", ".join(outputs) + "});",
756dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung           file=model_file)
757b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang
758b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang    # Phase 4: set relaxed execution if needed
759b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang    if (Model.isRelaxed()):
760b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang      print ("  // Phase 4: set relaxed execution", file=model_file)
761b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang      print ("  model->relaxComputationFloat32toFloat16(true);", file=model_file)
762b74d2837ab1687c1a4f913aa5f90a9838efe0addMiao Wang
763dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    # Boilerplate
764dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ("  assert(model->isValid());", file=model_file);
765dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print ("}", file=model_file)
766dd5cd91c89da2e5f44a8fd422e46ff24ffb872e0I-Jui (Ray) Sung    print (IgnoredOutput.gen_ignored(), file=model_file)
767dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
768dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  with smart_open(example) as example_file:
769dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Example.dump(example_file)
770