test_generator.py revision 4c7a55a8c2d7da34c3c2df27508a043a957b1c0c
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
19dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) SungCompile models and examples into NDK-based 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
27dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungimport os
284c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungimport struct
29dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungimport sys
30dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungimport contextlib
31dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
32dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung@contextlib.contextmanager
33dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungdef smart_open(filename=None):
34dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  if filename and filename != '-':
35dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    fh = open(filename, 'w')
36dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  else:
37dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    fh = sys.stdout
38dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
39dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  try:
40dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    yield fh
41dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  finally:
42dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if fh is not sys.stdout:
43dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      fh.close()
44dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
45dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Phase(object):
46dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self):
474c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    self.__objects = []
48dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__contents = []
49dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
504c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def append(self, obj, x):
514c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    self.__objects.append(obj)
52dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__contents.append(x)
53dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
54dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump(self, filename):
55dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for x in self.__contents:
56dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ("  " + x + ";", file=filename)
57dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
584c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def objects(self):
594c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return self.__objects
604c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
61dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Tracking objects inside a model with a not necessarily unique name and
62dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# an unique number
63dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass NamedObject(object):
64dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __serial = 0
65dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
66dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name = "NamedObject"):
67dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__name = name
68dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__id = NamedObject.serial()
69dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    NamedObject.__serial += 1
70dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
71dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def ID(self):
72dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__id
73dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
74dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def serial():
75dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return NamedObject.__serial
76dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
77dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_name(self):
78dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__name
79dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
80dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __str__(self):
81dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.get_name()
82dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
83dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __hash__(self):
84dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__id
85dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
86dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Object that can be traversed during topological sorting phase
87dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Traversable(object):
88dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def traversable(self):
89dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return True
90dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
91dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Nontraversable(object):
92dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def traversable(self):
93dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return False
94dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
95dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Object that can take input from other objects
96dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Uses(object):
97dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  all_uses = set()
98dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, ins = []):
99dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.ins = ins.copy()
100dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.all_uses.add(self)
101dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for i in ins:
102dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      i.outs.add(self)
103dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
104dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Object that other objects takes its definition from
105dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Definitions(object):
106dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, outs = []):
107dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.outs = set(outs)
108dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for o in outs:
109dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      o.ins.append(self)
110dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
1114c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungclass TypeLookup:
1124c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  __type_lookup = {
1134c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "INT32": "int32_t",
1144c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "FLOAT32": "float",
1154c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "TENSOR_INT32": "int32_t",
1164c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "TENSOR_FLOAT32": "float",
1174c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "TENSOR_QUANT8_ASYMM": "uint8_t",
1184c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }
1194c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1204c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def get_cpptype(nnapi_type):
1214c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return TypeLookup.__type_lookup[nnapi_type]
1224c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1234c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def is_float(nnapi_type):
1244c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return TypeLookup.get_cpptype(nnapi_type) == "float"
1254c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1264c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def get_size(nnapi_type):
1274c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return 1 if TypeLookup.get_cpptype(nnapi_type) == "uint8_t" else 4
1284c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
1294c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
130dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Type(object):
131dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __types =  {}
132dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __type_serial = 0 # types have their own numbering
133dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, vt = None, shape = None):
134dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__vt = vt
135dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__shape = shape
136dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if vt is None or shape is None:
137dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__name = None
138dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      return
139dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
140dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    key = str(self)
141dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if key not in Type.__types:
142dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__id = Type.__type_serial
143dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      Type.__types[str(self)] = self
144dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      Type.__type_serial += 1
145dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    else:
146dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__id = Type.__types[key].__id
147dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__name = "type" + str(self.__id)
148dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
1494c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def get_shape(self):
1504c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return self.__shape
1514c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
152ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung  def get_element_type(self):
153ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung    return self.__vt
154ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
155dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_name(self):
156dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__name
157dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
158dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __str__(self):
159dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return (", ".join([self.__vt, self.__shape]))
160dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
161dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __hash__(self):
162dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__id
163dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
164dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump(filename):
165dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for key, value in sorted(Type.__types.items()):
166dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ("  OperandType " + str(value.__name) + "(Type::" + str(key) + ");", file=filename)
167dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
1684c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def get_size(self):
1694c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    element_size = TypeLookup.get_size(self.__vt)
1704c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    # Parse shape
1714c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    nr_elements = 1
1724c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    if (self.__shape != "" and self.__shape != "{}"):
1734c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      left, sep, right = self.__shape.partition('{')
1744c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      real_shape, sep, right = right.partition('}')
1754c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      assert left == ""
1764c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      assert right == ""
1774c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      shape = [int(x) for x in real_shape.split(",")]
1784c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      nr_elements = reduce((lambda x, y: x*y), shape)
1794c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return element_size * nr_elements
180dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
181dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A value is a typed, named object
182dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Value(NamedObject):
183dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt):
184dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    NamedObject.__init__(self, name)
185dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.type = vt
186dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
187dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# An operand that can be fed into operations. Also, an operand is always
188dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# declared before operations.
189dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Operand(Value):
190dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # All operand declarations in string
191dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  operands = Phase()
192dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
193dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt):
194dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Value.__init__(self, name, vt)
195dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    def_string = (
196dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung        "auto " + self.get_name() + " = "\
197dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung            "model->addOperand(&" + vt.get_name() + ")")
1984c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    Operand.operands.append(self, def_string)
199dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
200dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # By default, produce nothing (when asked by the Topological Sort phase)
201dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Definition(self):
202dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    pass
203dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
204dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Reference(self):
205dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return NamedObject.__str__(self)
206dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
207dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # Print a set of operands in curly braces
208dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def print_operands(operands):
209dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return [ x.Reference() for x in operands ]
210dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
2114c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  # Defined with the model or not
2124c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def is_weight(self):
2134c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return False
2144c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
215dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A user-declared input operand
216dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Input(Operand, Definitions, Traversable):
217cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  # for enumerating inputs
218cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  __next_number = 0
219dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # Holds reference to all Inputs; used by Topoligcal sort as starting nodes.
220dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __inputs = set()
221dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
222dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt, shape):
223dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, name, Type(vt, shape))
224dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self)
225dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Input.__inputs.add(self)
226cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung    self.number = Input.__next_number
227cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung    Input.__next_number += 1
228dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
229dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def is_internal(self):
230dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return False
231dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
232dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_inputs(exclude_internal = None):
233dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if exclude_internal is not None:
234dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      external = { x for x in Input.__inputs if not x.is_internal() }
235dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      return external
236dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    else:
237dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      return Input.__inputs
238dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
239dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A user-declared output operand
240dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Output(Operand, Uses, Nontraversable):
241cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  # for enumerating outputs
242cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung  __next_number = 0
243dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __outputs = set()
244dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
245dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt, shape):
246dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, name, Type(vt, shape))
247dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self)
248dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Output.__outputs.add(self)
249cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung    self.number = Output.__next_number
250cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung    Output.__next_number += 1
251dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
252dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_outputs():
253dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return Output.__outputs
254dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
255dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass ModelArgument:
256dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __arguments = []
257dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
258dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, arg_type, arg_name):
259dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__arg_type = arg_type
260dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__arg_name = arg_name
261dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ModelArgument.__arguments.append(" ".join([arg_type, arg_name]))
262dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
263dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_arg_type(self):
264dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__arg_type
265dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
266dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_arg_name(self):
267dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self.__arg_name
268dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
269dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def get_arguments():
270dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return ModelArgument.__arguments
271dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
272ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
273ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sungclass Parameter(Input):
274dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt, shape, initializer):
275dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Input.__init__(self, name, vt, shape)
276dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.initializer = initializer
277ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung    self.cpptype = TypeLookup.get_cpptype(vt)
278dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def is_internal(self):
279dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return True
280dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Definition(self):
281dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    init_name = self.get_name() + "_init"
282dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    initializer = [str(x) for x in self.initializer]
283dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if self.cpptype == "float":
284dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      initializer = [ x+"f" for x in initializer]
285dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    init = self.cpptype + " " + init_name + "[]"
286dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    init = "static " + init + " = {" + ", ".join(initializer) + "};"
287dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    args = [ self.get_name(), init_name,
288dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung            "sizeof(" + self.cpptype + ") * " + str(len(self.initializer)) ]
289dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    stmt = "\n  ".join([init,
290dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung                      "model->setOperandValue(" + ", ".join(args)+");"])
291dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return stmt
2924c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def is_weight(self):
2934c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return True
294dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
295cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sungclass Int32Scalar(Parameter):
296dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, value):
2974c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    Parameter.__init__(self, name, "INT32", "{}", [value])
298dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
299cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sungclass Float32Scalar(Parameter):
300dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, value):
3014c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    Parameter.__init__(self, name, "FLOAT32", "{}", [value])
302dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
303dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# A compiler-generated intermediate result from an operation
304dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass IntermediateResult(Operand, Definitions, Uses, Traversable):
305dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, src: Value):
306dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    tmp_name = "tmp" + str(NamedObject.serial())
307dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, tmp_name, src.type)
308dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self)
309dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self, [src])
310dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
311dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# An explicitly declared intermediate result
312dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Internal(Operand, Definitions, Uses, Traversable):
313dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, name, vt, shape):
314dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Operand.__init__(self, name, Type(vt, shape))
315dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self)
316dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self)
317dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
318dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# An operation in a model
3194c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungclass Operation(Definitions, Uses, Traversable):
320dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, optype, ins, outs):
3214c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    self.type = ins[0].type
322dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Definitions.__init__(self, outs)
323dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Uses.__init__(self, ins)
324dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.optype = optype
325dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
326dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __str__(self):
327dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    inputs = [ str(x) for x in self.ins ]
328dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return "Operation:" + self.optype + " " + ", ".join(inputs)
329dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
330dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Reference(self):
331dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return "operation" + str(self.ID());
332dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
333dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Definition(self):
334dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    inputs = Operand.print_operands(self.ins);
335dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outputs = Operand.print_operands(self.outs);
336dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return "model->addOperation(ANEURALNETWORKS_"+self.optype+", " + \
337dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung        "{"+", ".join(inputs)+"}, {" + ", ".join(outputs) + "});"
338dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
339dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Main interface
340dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Model(object):
341dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self):
342dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = None
343dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
344dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # TODO turn this into generic binary operations
345dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Add(self, i1: Value, i2 = None) -> Operation:
346dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i1]
347dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if i2 is not None:
348dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      ins.append(i2)
349dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if self.__currentOp is not None:
350dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      ir = IntermediateResult(self.__currentOp)
351dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      self.__currentOp = ir
352dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      ins.append(self.__currentOp)
353dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
354dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("ADD", ins, [])
355dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
356dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
357dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
358dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
359dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Operation(self, op_name, *args):
360dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i for i in args]
361dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
362dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation(op_name, ins, outs)
363dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
364dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
365dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
366dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def RawAdd(self, i1: Value, i2: Value, o = None) -> Operation:
367dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i1, i2]
368dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
369dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if o is not None:
370dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      outs = [o]
371dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("ADD", ins, outs)
372dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
373dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
374dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
375dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
376dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # See CpuExecutor::executeOperation() for the arguments of each op
377dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def AveragePool(self, input, padding, stride_width, stride_height, filter_width, filter_height, activation):
378dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, padding, stride_width,
379dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, filter_width, filter_height, activation]
380dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
381dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("AVERAGE_POOL", ins, outs)
382dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
383dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
384dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
385dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Concatenation(self, *args):
386dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [i for i in args]
387dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
388dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("CONCATENATION", ins, outs)
389dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
390dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
391dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
392dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Conv(self, filter, bias, input, padding, stride_width, stride_height, activation):
393dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [filter, bias, input, padding, stride_width,
394dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, activation]
395dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
396dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("CONV", ins, outs)
397dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
398dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
399dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
400dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def DepthWiseConv(self, filter, bias, input, padding, stride_width, stride_height, depth_multiplier, activation):
401dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [filter, bias, input, padding, stride_width,
402dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, depth_multiplier, activation]
403dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
404dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("DEPTHWISE_CONV", ins, outs)
405dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
406dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
407dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
408dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def FullyConnected(self, input, weights, bias, activation):
409dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, weights, bias, activation]
410dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
411dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("FULLY_CONNECTED", ins, outs)
412dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
413dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
414dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
415dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Logistic(self, input):
416dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input]
417dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
418dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("LOGISTIC", ins, outs)
419dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
420dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
421dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
422dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def L2Pool(self, input, padding, stride_width, stride_height, filter_width, filter_height, activation):
423dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, padding, stride_width,
424dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, filter_width, filter_height, activation]
425dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
426dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("L2_POOL", ins, outs)
427dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
428dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
429dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
430dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def MaxPool(self, input, padding, stride_width, stride_height, filter_width, filter_height, activation):
431dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, padding, stride_width,
432dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung           stride_height, filter_width, filter_height, activation]
433dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
434dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("MAX_POOL", ins, outs)
435dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
436dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
437dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
438dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def SoftMax(self, input, beta):
439dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ins = [input, beta]
440dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    outs = []
441dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    op = Operation("SOFTMAX", ins, outs)
442dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = op
443dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
444dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
445dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def Out(self, o: Value) -> Operation:
446dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp.outs.add(o)
447dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    o.ins.append(self.__currentOp)
448dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
449dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
450dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def To(self, o:Value):
451dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ret = Model.Out(self, o)
452dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    self.__currentOp = None
453dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return self
454dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
455ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sungclass FileNames:
456ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung  SpecFile = ""
457ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
458dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungclass Example():
459dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  __examples = []
460dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def __init__(self, list_of_examples):
461dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Example.__examples.append(list_of_examples)
462dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
463dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump_dict(d):
464dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    ret = []
465dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for k, v in d.items():
466cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung      key = str(k)
467ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung      suffix = "f"
468cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung      if type(k) is not int:
469cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung        key = str(k.number)
470ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung        if not TypeLookup.is_float(k.type.get_element_type()):
471ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung          suffix = ""
472ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung      init = ", ".join([str(i)+suffix for i in v])
473cfe77f9ed8a14f97c7f18e4097492a2776a05d2aI-Jui (Ray) Sung      ret.append('{%s, {%s}}' %(key, init))
474dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    return ", ".join(ret)
475dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
476dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  def dump(example_file):
477dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    if len(Example.__examples) > 0:
478ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung      spec_file = " (from: %s)" % (FileNames.SpecFile)
479ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung      print ('// Generated file%s. Do not edit' % (spec_file),
480ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung             file = example_file)
481dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for i, o in Example.__examples:
482dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('// Begin of an example', file = example_file)
483dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('{', file = example_file)
484dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      inputs = Example.dump_dict(i)
485dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      outputs = Example.dump_dict(o)
486dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('//Input(s)\n{' + inputs + '},', file = example_file)
487dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('//Output(s)\n{' + outputs + '}', file = example_file)
488dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      print ('}, // End of an example', file = example_file)
489dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
4904c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef TopologicalSort(format_op):
491dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  start = Input.get_inputs().copy()
492dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  deps = { x: set(x.ins) for x in Uses.all_uses }
493dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
494dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  while len(start) > 0:
495dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    cur = start.pop()
4964c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    format_op(cur) #cur.Definition()
497dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    for o in cur.outs:
498dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      deps[o].remove(cur)
499dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung      if len(deps[o]) == 0 and o.traversable():
500dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung        start.add(o)
501dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
5024c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungclass Configuration:
5034c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  vts = False
504ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung
505dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung# Take a model from command line
506dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungdef import_source():
507dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  parser = argparse.ArgumentParser()
5084c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  parser.add_argument("spec", help="the spec file")
5094c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  parser.add_argument(
5104c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "-v",
5114c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "--vts",
5124c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      help="generate VTS model instead",
5134c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      default=False,
5144c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      action="store_true")
5154c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  parser.add_argument(
5164c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "-m", "--model", help="the output model file", default="-")
5174c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  parser.add_argument(
5184c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "-e", "--example", help="the output example file", default="-")
519dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  args = parser.parse_args()
520dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
5214c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  Configuration.vts = args.vts
5224c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
523dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  if os.path.exists(args.spec):
524ad36b7a0dd7468bbe6a0433a52cbf89561ff5538I-Jui (Ray) Sung    FileNames.SpecFile = os.path.basename(args.spec)
5254c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    exec (open(args.spec).read())
526dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
527dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  return (args.model, args.example)
528dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
5294c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung# Generate operands in VTS format
5304c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef generate_vts_operands():
5314c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  # Dump operand definitions
5324c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  op_def = """\
5334c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        {{
5344c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung            .type = OperandType::{operand_type},
5354c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung            .dimensions = {shape},
5364c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung            .numberOfConsumers = {no_consumers},
5374c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung            .scale = {scale},
5384c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung            .zeroPoint = {zero_point},
5394c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung            .location = {{.poolIndex = static_cast<uint32_t>(
5404c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung                              LocationValues::LOCATION_{location}),
5414c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung                         .offset = {offset},
5424c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung                         .length = {length}}},
5434c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        }}"""
5444c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  offset = 0
5454c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  op_definitions = []
5464c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  for o in Operand.operands.objects():
5474c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    ty = o.type
5484c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    no_consumers = len(o.outs) if o.traversable() else 0
5494c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    location = "SAME_BLOCK" if o.is_weight() else "AT_RUN_TIME"
5504c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    length = ty.get_size() if o.is_weight() else 0
5514c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
5524c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    op = {
5534c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "operand_type": ty.get_element_type(),
5544c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "shape": ty.get_shape(),
5554c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "no_consumers": no_consumers,
5564c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "scale": "0.0f",  #TODO
5574c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "zero_point": "0",  #TODO
5584c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "location": location,
5594c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "offset": offset if o.is_weight() else 0,
5604c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        "length": length
5614c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }
5624c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    offset += length
5634c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    op_definitions.append(op_def.format(**op))
5644c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
5654c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  op_vec = """\
5664c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    const std::vector<Operand> operands = {{
5674c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung{0}
5684c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }};""".format(",\n".join(op_definitions))
5694c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  return op_vec
5704c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
5714c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung# Generate VTS operand values
5724c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef generate_vts_operand_values():
5734c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  weights = [o for o in Operand.operands.objects() if o.is_weight()]
5744c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  binit = []
5754c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  for w in weights:
5764c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    ty = w.type.get_element_type()
5774c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    if ty == "TENSOR_QUANT8_ASYMM":
5784c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      binit += w.initializer
5794c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    elif ty in {"TENSOR_FLOAT32", "TENSOR_INT32", "INT32"}:
5804c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      fmt = "f" if ty == "TENSOR_FLOAT32" else "i"
5814c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      for f in w.initializer:
5824c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        binit += [int(x) for x in struct.pack(fmt, f)]
5834c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    else:
5844c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      assert 0 and "Unsupported VTS operand type"
5854c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
5864c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  init_defs = ", ".join([str(x) for x in binit])
5874c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  byte_vec_fmt = """\
5884c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    std::vector<uint8_t> operandValues = {
5894c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      %s
5904c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    };""" % init_defs
5914c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  return byte_vec_fmt
5924c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
5934c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung# Generate VTS operations
5944c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungclass VTSOps(object):
5954c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  vts_ops = []
5964c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  def generate_vts_operation(op):
5974c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    try:
5984c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      opcode =op.optype
5994c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    except AttributeError: # not an op, but things like weights
6004c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      return
6014c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    op_fmt = """\
6024c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    {{
6034c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .opTuple = {{OperationType::{op_code}, OperandType::{op_type}}},
6044c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .inputs = {{{ins}}},
6054c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .outputs = {{{outs}}},
6064c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }}"""
6074c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    op_content = {
6084c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        'op_code': op.optype,
6094c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        'op_type': 'TENSOR_FLOAT32', # TODO: support quantized
6104c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        'ins': ", ".join([str(x.ID()) for x in op.ins]),
6114c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        'outs': ", ".join([str(x.ID()) for x in op.outs]),
6124c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }
6134c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    VTSOps.vts_ops.append(op_fmt.format(**op_content))
6144c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6154c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef generate_vts_operations(model_file):
6164c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  TopologicalSort(lambda x: VTSOps.generate_vts_operation(x))
6174c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  return ",\n".join(VTSOps.vts_ops)
6184c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6194c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef generate_vts_model(model_file):
6204c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  model_fmt = """\
6214c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung// Generated code. Do not edit
6224c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung// Create the model
6234c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) SungModel createTestModel() {{
6244c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung{operand_decls}
6254c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6264c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    const std::vector<Operation> operations = {{
6274c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung{operations}
6284c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }};
6294c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6304c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    const std::vector<uint32_t> inputIndexes = {{{input_indices}}};
6314c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    const std::vector<uint32_t> outputIndexes = {{{output_indices}}};
6324c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung{operand_values}
6334c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    const std::vector<hidl_memory> pools = {{}};
6344c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6354c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    return {{
6364c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .operands = operands,
6374c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .operations = operations,
6384c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .inputIndexes = inputIndexes,
6394c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .outputIndexes = outputIndexes,
6404c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .operandValues = operandValues,
6414c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung        .pools = pools,
6424c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    }};
6434c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung}}"""
6444c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  model = {
6454c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "operations": generate_vts_operations(sys.stdout),
6464c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "operand_decls": generate_vts_operands(),
6474c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "operand_values": generate_vts_operand_values(),
6484c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "output_indices": ", ".join([str(i.ID()) for i in Output.get_outputs()]),
6494c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "input_indices": ", ".join([str(i.ID()) for i in Input.get_inputs(True)])
6504c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  }
6514c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  print(model_fmt.format(**model), file = model_file)
6524c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6534c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6544c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef generate_vts(model_file):
6554c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  generate_vts_model(model_file)
6564c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6574c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sungdef print_cts_op(model_file, op):
6584c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  fmt = op.Definition()
6594c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  if fmt is not None:
6604c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    print ("  %s" % fmt, file = model_file)
6614c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
662dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sungif __name__ == '__main__':
663dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  (model, example) = import_source()
664dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  # Boilerplate
665dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  args = ""
666dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  if len(ModelArgument.get_arguments()) > 0:
667dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    args = ", " + ", ".join(ModelArgument.get_arguments())
668dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
6694c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  print(
6704c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      "Output %s model: %s" % ("VTS" if Configuration.vts else "CTS", model),
6714c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      file=sys.stderr)
672dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  print ("Output example:" + example, file = sys.stderr)
673dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
6744c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  if Configuration.vts:
6754c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    with smart_open(model) as model_file:
6764c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      generate_vts(model_file)
6774c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung  else:
6784c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung    with smart_open(model) as model_file:
6794c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      spec_file = " (from: %s)" % (FileNames.SpecFile)
6804c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6814c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ('// Generated file%s. Do not edit'%(spec_file), file = model_file)
6824c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ("void CreateModel(Model *model" + args + ") {", file=model_file)
6834c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6844c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      # Phase 0: types
6854c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      Type.dump(model_file)
6864c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      # Phase 1: add operands
6874c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ("  // Phase 1, operands", file=model_file)
6884c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      Operand.operands.dump(model_file)
6894c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6904c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      # Phase 2: operations
6914c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ("  // Phase 2, operations", file=model_file)
6924c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      TopologicalSort(lambda x: print_cts_op(model_file, x))
6934c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung
6944c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      # Phase 3: add inputs and outputs
6954c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ("  // Phase 3, inputs and outputs", file=model_file)
6964c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      inputs = Operand.print_operands(Input.get_inputs(True));
6974c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      outputs = Operand.print_operands(Output.get_outputs());
6984c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ("  model->setInputsAndOutputs(\n" +
6994c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung             "    {"+", ".join(inputs)+"},\n    {" + ", ".join(outputs) + "});",
7004c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung             file=model_file)
7014c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      # Boilerplate
7024c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ("  assert(model->isValid());", file=model_file);
7034c7a55a8c2d7da34c3c2df27508a043a957b1c0cI-Jui (Ray) Sung      print ("}", file=model_file)
704dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung
705dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung  with smart_open(example) as example_file:
706dcd2fbf1da7ebdc1aa1b57c74db4fffd2911e3b8I-Jui (Ray) Sung    Example.dump(example_file)
707