1#!/usr/bin/env python3
2#
3# SPDX-FileCopyrightText: Copyright 2010-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
4#
5# SPDX-License-Identifier: Apache-2.0
6#
7# Licensed under the Apache License, Version 2.0 (the License); you may
8# not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an AS IS BASIS, WITHOUT
15# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19import os
20import sys
21import json
22import math
23import argparse
24import subprocess
25import numpy as np
26
27from packaging import version
28from abc import ABC, abstractmethod
29
30try:
31    import tensorflow as tf
32except Exception as e:
33    print(e)
34    sys.exit(1)
35
36REQUIRED_MINIMUM_TENSORFLOW_VERSION = version.parse("2.10")
37
38CLANG_FORMAT = 'clang-format-12 -i'  # For formatting generated headers.
39
40INT32_MAX = 2147483647
41INT32_MIN = -2147483648
42INT64_MAX = 9223372036854775807
43INT64_MIN = -9223372036854775808
44INT16_MAX = 32767
45INT16_MIN = -32768
46INT8_MAX = 127
47INT8_MIN = -128
48
49
50def parse_args() -> argparse.Namespace:
51    parser = argparse.ArgumentParser(description="Generate input and refererence output data for unittests."
52                                     " It can regenerate all data, load all stored data or a combination of it.")
53    parser.add_argument('--dataset', type=str, default=None, help="Name of generated test set.")
54    parser.add_argument('--regenerate-weights', action='store_true', help="Regenerate and store new weights.")
55    parser.add_argument('--regenerate-input', action='store_true', help="Regenerate and store new input.")
56    parser.add_argument('--regenerate-biases', action='store_true', help="Regenerate and store new biases.")
57    parser.add_argument('-a', '--regenerate-all', action='store_true', help="Regenerate and store all data.")
58    parser.add_argument('-t',
59                        '--testtype',
60                        type=str,
61                        default=None,
62                        choices=[
63                            'conv', 'depthwise_conv', 'avgpool', 'maxpool', 'fully_connected', 'softmax', 'svdf', 'add',
64                            'mul', 'lstm'
65                        ],
66                        help='Type of test. There are the operators that have unit tests.')
67    parser.add_argument('--run-all-testsets',
68                        action='store_true',
69                        help="Run the script for all existing test "
70                        "sets. Regenerate all, partially all or no input data (output may still change, depending on"
71                        " changes in script) depending on regenerate flags. If used together with the -t flag, only"
72                        " tests of that type will be run.")
73    parser.add_argument('--schema-file', type=str, help="Path to schema file. This may be needed for some tests.")
74
75    args = parser.parse_args()
76    return args
77
78
79# Use interpreter from tensorflow or tflite_runtime.
80# Set this to False to use the tflite_runtime instead.
81# See README for more info.
82default_interpreter = True
83
84if default_interpreter:
85    from tensorflow.lite.python.interpreter import Interpreter
86    from tensorflow.lite.python.interpreter import OpResolverType
87else:
88    from tflite_runtime.interpreter import Interpreter
89    from tflite_runtime.interpreter import OpResolverType
90    import tflite_runtime as tfl_runtime
91
92
93class TestSettings(ABC):
94
95    # This is the generated test data used by the test cases.
96    OUTDIR = 'TestCases/TestData/'
97
98    # This is input to the data generation. If everything or something is regenerated then it is overwritten.
99    # So it always has the same data as the OUTDIR.
100    # The purpose of the pregen is primarily for debugging, as it is enabling to change a single parameter and see how
101    # output changes (or not changes), without regenerating all input data.
102    # It also convinient when testing changes in the script, to be able to run all test sets again.
103    PREGEN = 'PregeneratedData/'
104
105    def __init__(self,
106                 dataset,
107                 testtype,
108                 regenerate_weights,
109                 regenerate_input,
110                 regenerate_biases,
111                 schema_file,
112                 in_ch,
113                 out_ch,
114                 x_in,
115                 y_in,
116                 w_x,
117                 w_y,
118                 stride_x=1,
119                 stride_y=1,
120                 pad=False,
121                 randmin=INT8_MIN,
122                 randmax=INT8_MAX,
123                 batches=1,
124                 generate_bias=True,
125                 relu6=False,
126                 out_activation_min=None,
127                 out_activation_max=None,
128                 int16xint8=False,
129                 bias_min=INT32_MIN,
130                 bias_max=INT32_MAX,
131                 dilation_x=1,
132                 dilation_y=1):
133
134        self.tensor_flow_reference_version = (
135            "// Generated by {} using tensorflow version {} (Keras version {}).\n".format(
136                os.path.basename(__file__), tf.__version__, tf.keras.__version__))
137
138        if 'tflite_runtime' in sys.modules:
139            revision = tfl_runtime.__git_version__
140            version = tfl_runtime.__version__
141            interpreter = "tflite_runtime"
142        else:
143            revision = tf.__git_version__
144            version = tf.__version__
145            interpreter = "tensorflow"
146
147        self.tensor_flow_reference_version += ("// Interpreter from {} version {} and revision {}.\n".format(
148            interpreter, version, revision))
149
150        # Randomization interval
151        self.mins = randmin
152        self.maxs = randmax
153
154        self.bias_mins = bias_min
155        self.bias_maxs = bias_max
156
157        self.input_ch = in_ch
158        self.output_ch = out_ch
159        self.x_input = x_in
160        self.y_input = y_in
161        self.filter_x = w_x
162        self.filter_y = w_y
163        self.stride_x = stride_x
164        self.stride_y = stride_y
165        self.dilation_x = dilation_x
166        self.dilation_y = dilation_y
167        self.batches = batches
168        self.test_type = testtype
169        self.has_padding = pad
170
171        self.is_int16xint8 = int16xint8
172
173        if relu6:
174            self.out_activation_max = 6
175            self.out_activation_min = 0
176        else:
177            if out_activation_min is not None:
178                self.out_activation_min = out_activation_min
179            else:
180                self.out_activation_min = INT16_MIN if self.is_int16xint8 else INT8_MIN
181            if out_activation_max is not None:
182                self.out_activation_max = out_activation_max
183            else:
184                self.out_activation_max = INT16_MAX if self.is_int16xint8 else INT8_MAX
185
186        # Bias is optional.
187        self.generate_bias = generate_bias
188
189        self.generated_header_files = []
190        self.pregenerated_data_dir = self.PREGEN
191
192        self.config_data = "config_data.h"
193
194        self.testdataset = dataset
195
196        self.kernel_table_file = self.pregenerated_data_dir + self.testdataset + '/' + 'kernel.txt'
197        self.inputs_table_file = self.pregenerated_data_dir + self.testdataset + '/' + 'input.txt'
198        self.bias_table_file = self.pregenerated_data_dir + self.testdataset + '/' + 'bias.txt'
199
200        if self.has_padding:
201            self.padding = 'SAME'
202        else:
203            self.padding = 'VALID'
204
205        self.regenerate_new_weights = regenerate_weights
206        self.regenerate_new_input = regenerate_input
207        self.regenerate_new_bias = regenerate_biases
208        self.schema_file = schema_file
209
210        self.headers_dir = self.OUTDIR + self.testdataset + '/'
211        os.makedirs(self.headers_dir, exist_ok=True)
212
213        self.model_path = "{}model_{}".format(self.headers_dir, self.testdataset)
214        self.model_path_tflite = self.model_path + '.tflite'
215
216        self.input_data_file_prefix = "input"
217        self.weight_data_file_prefix = "weights"
218        self.bias_data_file_prefix = "biases"
219        self.output_data_file_prefix = "output_ref"
220
221    def save_multiple_dim_array_in_txt(self, file, data):
222        header = ','.join(map(str, data.shape))
223        np.savetxt(file, data.reshape(-1, data.shape[-1]), header=header, delimiter=',')
224
225    def load_multiple_dim_array_from_txt(self, file):
226        with open(file) as f:
227            shape = list(map(int, next(f)[1:].split(',')))
228            data = np.genfromtxt(f, delimiter=',').reshape(shape)
229        return data.astype(np.float32)
230
231    def convert_tensor_np(self, tensor_in, converter, *qminmax):
232        w = tensor_in.numpy()
233        shape = w.shape
234        w = w.ravel()
235        if len(qminmax) == 2:
236            fw = converter(w, qminmax[0], qminmax[1])
237        else:
238            fw = converter(w)
239        fw.shape = shape
240        return tf.convert_to_tensor(fw)
241
242    def convert_tensor(self, tensor_in, converter, *qminmax):
243        w = tensor_in.numpy()
244        shape = w.shape
245        w = w.ravel()
246        normal = np.array(w)
247        float_normal = []
248
249        for i in normal:
250            if len(qminmax) == 2:
251                float_normal.append(converter(i, qminmax[0], qminmax[1]))
252            else:
253                float_normal.append(converter(i))
254
255        np_float_array = np.asarray(float_normal)
256        np_float_array.shape = shape
257
258        return tf.convert_to_tensor(np_float_array)
259
260    def get_randomized_data(self, dims, npfile, regenerate, decimals=0, minrange=None, maxrange=None):
261        if not minrange:
262            minrange = self.mins
263        if not maxrange:
264            maxrange = self.maxs
265        if not os.path.exists(npfile) or regenerate:
266            regendir = os.path.dirname(npfile)
267            os.makedirs(regendir, exist_ok=True)
268            if decimals == 0:
269                data = tf.Variable(tf.random.uniform(dims, minval=minrange, maxval=maxrange, dtype=tf.dtypes.int64))
270                data = tf.cast(data, dtype=tf.float32)
271            else:
272                data = tf.Variable(tf.random.uniform(dims, minval=minrange, maxval=maxrange, dtype=tf.dtypes.float32))
273                data = np.around(data.numpy(), decimals)
274                data = tf.convert_to_tensor(data)
275
276            print("Saving data to {}".format(npfile))
277            self.save_multiple_dim_array_in_txt(npfile, data.numpy())
278        else:
279            print("Loading data from {}".format(npfile))
280            data = tf.convert_to_tensor(self.load_multiple_dim_array_from_txt(npfile))
281        return data
282
283    def get_randomized_input_data(self, input_data, input_shape=None):
284        # Generate or load saved input data unless hardcoded data provided
285        if input_shape is None:
286            input_shape = [self.batches, self.y_input, self.x_input, self.input_ch]
287        if input_data is not None:
288            input_data = tf.reshape(input_data, input_shape)
289        else:
290            input_data = self.get_randomized_data(input_shape,
291                                                  self.inputs_table_file,
292                                                  regenerate=self.regenerate_new_input)
293        return input_data
294
295    def get_randomized_bias_data(self, biases):
296        # Generate or load saved bias data unless hardcoded data provided
297        if not self.generate_bias:
298            biases = tf.reshape(np.full([self.output_ch], 0), [self.output_ch])
299        elif biases is not None:
300            biases = tf.reshape(biases, [self.output_ch])
301        else:
302            biases = self.get_randomized_data([self.output_ch],
303                                              self.bias_table_file,
304                                              regenerate=self.regenerate_new_bias,
305                                              minrange=self.bias_mins,
306                                              maxrange=self.bias_maxs)
307        return biases
308
309    def format_output_file(self, file):
310        command_list = CLANG_FORMAT.split(' ')
311        command_list.append(file)
312        try:
313            process = subprocess.run(command_list)
314            if process.returncode != 0:
315                print(f"ERROR: {command_list = }")
316                sys.exit(1)
317        except Exception as e:
318            raise RuntimeError(f"{e} from: {command_list = }")
319
320    def write_c_header_wrapper(self):
321        filename = "test_data.h"
322        filepath = self.headers_dir + filename
323
324        print("Generating C header wrapper {}...".format(filepath))
325        with open(filepath, 'w+') as f:
326            f.write(self.tensor_flow_reference_version)
327            while len(self.generated_header_files) > 0:
328                f.write('#include "{}"\n'.format(self.generated_header_files.pop()))
329        self.format_output_file(filepath)
330
331    def write_common_config(self, f, prefix):
332        """
333        Shared by conv/depthwise_conv and pooling
334        """
335        f.write("#define {}_FILTER_X {}\n".format(prefix, self.filter_x))
336        f.write("#define {}_FILTER_Y {}\n".format(prefix, self.filter_y))
337        f.write("#define {}_STRIDE_X {}\n".format(prefix, self.stride_x))
338        f.write("#define {}_STRIDE_Y {}\n".format(prefix, self.stride_y))
339        f.write("#define {}_PAD_X {}\n".format(prefix, self.pad_x))
340        f.write("#define {}_PAD_Y {}\n".format(prefix, self.pad_y))
341        f.write("#define {}_OUTPUT_W {}\n".format(prefix, self.x_output))
342        f.write("#define {}_OUTPUT_H {}\n".format(prefix, self.y_output))
343
344    def write_c_common_header(self, f):
345        f.write(self.tensor_flow_reference_version)
346        f.write("#pragma once\n")
347
348    def write_c_config_header(self, write_common_parameters=True) -> None:
349        filename = self.config_data
350
351        self.generated_header_files.append(filename)
352        filepath = self.headers_dir + filename
353
354        prefix = self.testdataset.upper()
355
356        print("Writing C header with config data {}...".format(filepath))
357        with open(filepath, "w+") as f:
358            self.write_c_common_header(f)
359            if (write_common_parameters):
360                f.write("#define {}_OUT_CH {}\n".format(prefix, self.output_ch))
361                f.write("#define {}_IN_CH {}\n".format(prefix, self.input_ch))
362                f.write("#define {}_INPUT_W {}\n".format(prefix, self.x_input))
363                f.write("#define {}_INPUT_H {}\n".format(prefix, self.y_input))
364                f.write("#define {}_DST_SIZE {}\n".format(prefix, self.x_output * self.y_output * self.output_ch *
365                                                          self.batches))
366                f.write("#define {}_INPUT_SIZE {}\n".format(prefix, self.x_input * self.y_input * self.input_ch))
367                f.write("#define {}_OUT_ACTIVATION_MIN {}\n".format(prefix, self.out_activation_min))
368                f.write("#define {}_OUT_ACTIVATION_MAX {}\n".format(prefix, self.out_activation_max))
369                f.write("#define {}_INPUT_BATCHES {}\n".format(prefix, self.batches))
370        self.format_output_file(filepath)
371
372    def get_data_file_name_info(self, name_prefix) -> (str, str):
373        filename = name_prefix + "_data.h"
374        filepath = self.headers_dir + filename
375        return filename, filepath
376
377    def generate_c_array(self, name, array, datatype="int8_t", const="const ") -> None:
378        w = None
379
380        if type(array) is list:
381            w = array
382            size = len(array)
383        elif type(array) is np.ndarray:
384            w = array
385            w = w.ravel()
386            size = w.size
387        else:
388            w = array.numpy()
389            w = w.ravel()
390            size = tf.size(array)
391
392        filename, filepath = self.get_data_file_name_info(name)
393        self.generated_header_files.append(filename)
394
395        print("Generating C header {}...".format(filepath))
396        with open(filepath, "w+") as f:
397            self.write_c_common_header(f)
398            f.write("#include <stdint.h>\n\n")
399            if size > 0:
400                f.write(const + datatype + " " + self.testdataset + '_' + name + "[%d] =\n{\n" % size)
401                for i in range(size - 1):
402                    f.write("  %d,\n" % w[i])
403                f.write("  %d\n" % w[size - 1])
404                f.write("};\n")
405            else:
406                f.write(const + datatype + " *" + self.testdataset + '_' + name + " = NULL;\n")
407        self.format_output_file(filepath)
408
409    def set_output_dims_and_padding(self, output_x, output_y):
410        self.x_output = output_x
411        self.y_output = output_y
412        if self.has_padding:
413            # Take dilation into account.
414            filter_x = (self.filter_x - 1) * self.dilation_x + 1
415            filter_y = (self.filter_y - 1) * self.dilation_y + 1
416
417            pad_along_width = max((self.x_output - 1) * self.stride_x + filter_x - self.x_input, 0)
418            pad_along_height = max((self.y_output - 1) * self.stride_y + filter_y - self.y_input, 0)
419            pad_top = pad_along_height // 2
420            pad_left = pad_along_width // 2
421            self.pad_x = pad_left
422            self.pad_y = pad_top
423        else:
424            self.pad_x = 0
425            self.pad_y = 0
426
427    @abstractmethod
428    def generate_data(self, input_data=None, weights=None, biases=None) -> None:
429        ''' Must be overriden '''
430
431    def quantize_scale(self, scale):
432        significand, shift = math.frexp(scale)
433        significand_q31 = round(significand * (1 << 31))
434        return significand_q31, shift
435
436    def get_calib_data_func(self, n_inputs, shape):
437
438        def representative_data_gen():
439            representative_testsets = []
440            if n_inputs > 0:
441                for i in range(n_inputs):
442                    representative_testsets.append(np.ones(shape, dtype=np.float32))
443                yield representative_testsets
444            else:
445                raise RuntimeError("Invalid number of representative test sets: {}. Must be more than 0".format(
446                    self.test_type))
447
448        return representative_data_gen
449
450    def convert_and_interpret(self, model, inttype, input_data=None, dataset_shape=None) -> Interpreter:
451        """
452        Compile and convert a model to Tflite format, run interpreter and allocate tensors.
453        """
454        model.compile(loss=tf.keras.losses.categorical_crossentropy,
455                      optimizer=tf.keras.optimizers.Adam(),
456                      metrics=['accuracy'])
457        n_inputs = len(model.inputs)
458
459        if dataset_shape:
460            representative_dataset_shape = dataset_shape
461        else:
462            representative_dataset_shape = (self.batches, self.y_input, self.x_input, self.input_ch)
463
464        converter = tf.lite.TFLiteConverter.from_keras_model(model)
465
466        representative_dataset = self.get_calib_data_func(n_inputs, representative_dataset_shape)
467
468        converter.optimizations = [tf.lite.Optimize.DEFAULT]
469        converter.representative_dataset = representative_dataset
470        if self.is_int16xint8:
471            converter.target_spec.supported_ops = [
472                tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8
473            ]
474        else:
475            converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
476        converter.inference_input_type = inttype
477        converter.inference_output_type = inttype
478        tflite_model = converter.convert()
479
480        os.makedirs(os.path.dirname(self.model_path_tflite), exist_ok=True)
481        with open(self.model_path_tflite, "wb") as model:
482            model.write(tflite_model)
483
484        interpreter = Interpreter(model_path=str(self.model_path_tflite),
485                                  experimental_op_resolver_type=OpResolverType.BUILTIN_REF)
486        interpreter.allocate_tensors()
487
488        output_details = interpreter.get_output_details()
489        (self.output_scale, self.output_zero_point) = output_details[0]['quantization']
490
491        if input_data is not None:
492            input_details = interpreter.get_input_details()
493            (self.input_scale, self.input_zero_point) = input_details[0]['quantization']
494
495            # Set input tensors
496            interpreter.set_tensor(input_details[0]["index"], tf.cast(input_data, inttype))
497
498        return interpreter
499
500    def generate_json_from_template(self,
501                                    weights_feature_data=None,
502                                    weights_time_data=None,
503                                    bias_data=None,
504                                    int8_time_weights=False):
505        """
506        Takes a json template and parameters as input and creates a new json file.
507        """
508        generated_json_file = self.model_path + '.json'
509
510        with open(self.json_template, 'r') as in_file, open(generated_json_file, 'w') as out_file:
511            # Update shapes, scales and zero points
512            data = in_file.read()
513            for item, to_replace in self.json_replacements.items():
514                data = data.replace(item, str(to_replace))
515
516            data = json.loads(data)
517
518            # Update weights and bias data
519            if weights_feature_data is not None:
520                w_1_buffer_index = 1
521                data["buffers"][w_1_buffer_index]["data"] = self.to_bytes(weights_feature_data.numpy().ravel(), 1)
522            if weights_time_data is not None:
523                w_2_buffer_index = 2
524                if int8_time_weights:
525                    data["buffers"][w_2_buffer_index]["data"] = self.to_bytes(weights_time_data.numpy().ravel(), 1)
526                else:
527                    data["buffers"][w_2_buffer_index]["data"] = self.to_bytes(weights_time_data.numpy().ravel(), 2)
528            if bias_data is not None:
529                bias_buffer_index = 3
530                data["buffers"][bias_buffer_index]["data"] = self.to_bytes(bias_data.numpy().ravel(), 4)
531
532            json.dump(data, out_file, indent=2)
533
534        return generated_json_file
535
536    def flatc_generate_tflite(self, json_input, schema):
537        flatc = 'flatc'
538        if schema is None:
539            raise RuntimeError("A schema file is required.")
540        command = "{} -o {} -c -b {} {}".format(flatc, self.headers_dir, schema, json_input)
541        command_list = command.split(' ')
542        try:
543            process = subprocess.run(command_list)
544            if process.returncode != 0:
545                print(f"ERROR: {command = }")
546                sys.exit(1)
547        except Exception as e:
548            raise RuntimeError(f"{e} from: {command = }. Did you install flatc?")
549
550    def to_bytes(self, tensor_data, type_size) -> bytes:
551        result_bytes = []
552
553        if type_size == 1:
554            tensor_type = np.uint8
555        elif type_size == 2:
556            tensor_type = np.uint16
557        elif type_size == 4:
558            tensor_type = np.uint32
559        else:
560            raise RuntimeError("Size not supported: {}".format(type_size))
561
562        for val in tensor_data:
563            for byte in int(tensor_type(val)).to_bytes(type_size, 'little'):
564                result_bytes.append(byte)
565
566        return result_bytes
567
568
569class ConvSettings(TestSettings):
570
571    def __init__(self,
572                 dataset,
573                 testtype,
574                 regenerate_weights,
575                 regenerate_input,
576                 regenerate_biases,
577                 schema_file,
578                 in_ch=1,
579                 out_ch=1,
580                 x_in=7,
581                 y_in=7,
582                 w_x=3,
583                 w_y=3,
584                 stride_x=2,
585                 stride_y=2,
586                 pad=True,
587                 randmin=INT8_MIN,
588                 randmax=INT8_MAX,
589                 batches=1,
590                 generate_bias=True,
591                 relu6=False,
592                 out_activation_min=None,
593                 out_activation_max=None,
594                 int16xint8=False,
595                 bias_min=INT32_MIN,
596                 bias_max=INT32_MAX,
597                 dilation_x=1,
598                 dilation_y=1):
599        super().__init__(dataset,
600                         testtype,
601                         regenerate_weights,
602                         regenerate_input,
603                         regenerate_biases,
604                         schema_file,
605                         in_ch,
606                         out_ch,
607                         x_in,
608                         y_in,
609                         w_x,
610                         w_y,
611                         stride_x,
612                         stride_y,
613                         pad,
614                         randmin,
615                         randmax,
616                         batches,
617                         generate_bias=generate_bias,
618                         relu6=relu6,
619                         out_activation_min=out_activation_min,
620                         out_activation_max=out_activation_max,
621                         int16xint8=int16xint8,
622                         bias_min=bias_min,
623                         bias_max=bias_max,
624                         dilation_x=dilation_x,
625                         dilation_y=dilation_y)
626
627        self.scaling_factors = []
628
629        if self.test_type == 'depthwise_conv':
630            self.channel_multiplier = self.output_ch // self.input_ch
631            if self.output_ch % self.input_ch != 0:
632                raise RuntimeError("out channel ({}) is not multiple of in channel ({})".format(out_ch, in_ch))
633
634    def write_c_config_header(self) -> None:
635        super().write_c_config_header()
636
637        filename = self.config_data
638        filepath = self.headers_dir + filename
639        prefix = self.testdataset.upper()
640
641        with open(filepath, "a") as f:
642            self.write_common_config(f, prefix)
643            if self.test_type == 'depthwise_conv':
644                f.write("#define {}_CH_MULT {}\n".format(prefix, self.channel_multiplier))
645            f.write("#define {}_INPUT_OFFSET {}\n".format(prefix, -self.input_zero_point))
646            f.write("#define {}_OUTPUT_OFFSET {}\n".format(prefix, self.output_zero_point))
647            f.write("#define {}_DILATION_X {}\n".format(prefix, self.dilation_x))
648            f.write("#define {}_DILATION_Y {}\n".format(prefix, self.dilation_y))
649
650    def generate_quantize_per_channel_multiplier(self):
651        num_channels = self.output_ch
652        per_channel_multiplier = []
653        per_channel_shift = []
654
655        if len(self.scaling_factors) != num_channels:
656            raise RuntimeError("Missing scaling factors")
657
658        for i in range(num_channels):
659            effective_output_scale = self.input_scale * self.scaling_factors[i] / self.output_scale
660            (quantized_multiplier, shift) = self.quantize_scale(effective_output_scale)
661
662            per_channel_multiplier.append(quantized_multiplier)
663            per_channel_shift.append(shift)
664
665        return per_channel_multiplier, per_channel_shift
666
667    def generate_data(self, input_data=None, weights=None, biases=None) -> None:
668        if self.is_int16xint8:
669            inttype = tf.int16
670            datatype = "int16_t"
671            bias_datatype = "int64_t"
672        else:
673            inttype = tf.int8
674            datatype = "int8_t"
675            bias_datatype = "int32_t"
676
677        input_data = self.get_randomized_input_data(input_data)
678
679        if self.test_type == 'conv':
680            out_channel = self.output_ch
681        elif self.test_type == 'depthwise_conv':
682            out_channel = self.channel_multiplier
683
684        if weights is not None:
685            weights = tf.reshape(weights, [self.filter_y, self.filter_x, self.input_ch, out_channel])
686        else:
687            weights = self.get_randomized_data([self.filter_y, self.filter_x, self.input_ch, out_channel],
688                                               self.kernel_table_file,
689                                               minrange=INT32_MIN,
690                                               maxrange=INT32_MAX,
691                                               decimals=1,
692                                               regenerate=self.regenerate_new_weights)
693
694        biases = self.get_randomized_bias_data(biases)
695
696        # Create a one layer Keras model.
697        model = tf.keras.models.Sequential()
698        input_shape = (self.batches, self.y_input, self.x_input, self.input_ch)
699        model.add(tf.keras.layers.InputLayer(input_shape=input_shape[1:], batch_size=self.batches))
700        if self.test_type == 'conv':
701            conv_layer = tf.keras.layers.Conv2D(self.output_ch,
702                                                kernel_size=(self.filter_y, self.filter_x),
703                                                strides=(self.stride_y, self.stride_x),
704                                                padding=self.padding,
705                                                input_shape=input_shape[1:],
706                                                dilation_rate=(self.dilation_y, self.dilation_x))
707            model.add(conv_layer)
708            conv_layer.set_weights([weights, biases])
709        elif self.test_type == 'depthwise_conv':
710            depthwise_layer = tf.keras.layers.DepthwiseConv2D(kernel_size=(self.filter_y, self.filter_x),
711                                                              strides=(self.stride_y, self.stride_x),
712                                                              padding=self.padding,
713                                                              depth_multiplier=self.channel_multiplier,
714                                                              input_shape=input_shape[1:],
715                                                              dilation_rate=(self.dilation_y, self.dilation_x))
716            model.add(depthwise_layer)
717            depthwise_layer.set_weights([weights, biases])
718        interpreter = self.convert_and_interpret(model, inttype, input_data)
719
720        all_layers_details = interpreter.get_tensor_details()
721        filter_layer = all_layers_details[2]
722        bias_layer = all_layers_details[1]
723        if weights.numpy().size != interpreter.get_tensor(filter_layer['index']).size or \
724           (self.generate_bias and biases.numpy().size != interpreter.get_tensor(bias_layer['index']).size):
725            raise RuntimeError(f"Dimension mismatch for {self.testdataset}")
726
727        output_details = interpreter.get_output_details()
728        self.set_output_dims_and_padding(output_details[0]['shape'][2], output_details[0]['shape'][1])
729
730        self.generate_c_array(self.input_data_file_prefix, input_data, datatype=datatype)
731        self.generate_c_array(self.weight_data_file_prefix, interpreter.get_tensor(filter_layer['index']))
732
733        self.scaling_factors = filter_layer['quantization_parameters']['scales']
734        per_channel_multiplier, per_channel_shift = self.generate_quantize_per_channel_multiplier()
735        self.generate_c_array("output_mult", per_channel_multiplier, datatype='int32_t')
736        self.generate_c_array("output_shift", per_channel_shift, datatype='int32_t')
737
738        self.generate_c_array(self.bias_data_file_prefix, interpreter.get_tensor(bias_layer['index']), bias_datatype)
739
740        # Generate reference
741        interpreter.invoke()
742        output_data = interpreter.get_tensor(output_details[0]["index"])
743        self.generate_c_array(self.output_data_file_prefix,
744                              np.clip(output_data, self.out_activation_min, self.out_activation_max),
745                              datatype=datatype)
746
747        self.write_c_config_header()
748        self.write_c_header_wrapper()
749
750
751class PoolingSettings(TestSettings):
752
753    def __init__(self,
754                 dataset,
755                 testtype,
756                 regenerate_weights,
757                 regenerate_input,
758                 regenerate_biases,
759                 schema_file,
760                 channels=8,
761                 x_in=4,
762                 y_in=4,
763                 w_x=4,
764                 w_y=4,
765                 stride_x=1,
766                 stride_y=1,
767                 randmin=INT8_MIN,
768                 randmax=INT8_MAX,
769                 bias_min=INT32_MIN,
770                 bias_max=INT32_MAX,
771                 batches=1,
772                 pad=False,
773                 relu6=False,
774                 out_activation_min=None,
775                 out_activation_max=None,
776                 int16xint8=False):
777        super().__init__(dataset,
778                         testtype,
779                         regenerate_weights,
780                         regenerate_input,
781                         regenerate_biases,
782                         schema_file,
783                         channels,
784                         channels,
785                         x_in,
786                         y_in,
787                         w_x,
788                         w_y,
789                         stride_x,
790                         stride_y,
791                         pad,
792                         randmin=randmin,
793                         randmax=randmax,
794                         relu6=relu6,
795                         out_activation_min=out_activation_min,
796                         out_activation_max=out_activation_max,
797                         int16xint8=int16xint8)
798
799    def generate_data(self, input_data=None) -> None:
800        if self.is_int16xint8:
801            datatype = "int16_t"
802            inttype = tf.int16
803        else:
804            datatype = "int8_t"
805            inttype = tf.int8
806
807        input_data = self.get_randomized_input_data(input_data)
808        self.generate_c_array(self.input_data_file_prefix, input_data, datatype=datatype)
809
810        input_data = tf.cast(input_data, tf.float32)
811
812        # Create a one-layer Keras model
813        model = tf.keras.models.Sequential()
814        input_shape = (self.batches, self.y_input, self.x_input, self.input_ch)
815        model.add(tf.keras.layers.InputLayer(input_shape=input_shape[1:], batch_size=self.batches))
816        if self.test_type == 'avgpool':
817            model.add(
818                tf.keras.layers.AveragePooling2D(pool_size=(self.filter_y, self.filter_x),
819                                                 strides=(self.stride_y, self.stride_x),
820                                                 padding=self.padding,
821                                                 input_shape=input_shape[1:]))
822        elif self.test_type == 'maxpool':
823            model.add(
824                tf.keras.layers.MaxPooling2D(pool_size=(self.filter_y, self.filter_x),
825                                             strides=(self.stride_y, self.stride_x),
826                                             padding=self.padding,
827                                             input_shape=input_shape[1:]))
828        else:
829            raise RuntimeError("Wrong test type")
830
831        interpreter = self.convert_and_interpret(model, inttype, input_data)
832
833        output_details = interpreter.get_output_details()
834        self.set_output_dims_and_padding(output_details[0]['shape'][2], output_details[0]['shape'][1])
835
836        # Generate reference
837        interpreter.invoke()
838        output_data = interpreter.get_tensor(output_details[0]["index"])
839        self.generate_c_array(self.output_data_file_prefix,
840                              np.clip(output_data, self.out_activation_min, self.out_activation_max),
841                              datatype=datatype)
842
843        self.write_c_config_header()
844        self.write_c_header_wrapper()
845
846    def write_c_config_header(self) -> None:
847        super().write_c_config_header()
848
849        filename = self.config_data
850        filepath = self.headers_dir + filename
851        prefix = self.testdataset.upper()
852
853        with open(filepath, "a") as f:
854            self.write_common_config(f, prefix)
855
856
857class FullyConnectedSettings(TestSettings):
858
859    def __init__(self,
860                 dataset,
861                 testtype,
862                 regenerate_weights,
863                 regenerate_input,
864                 regenerate_biases,
865                 schema_file,
866                 in_ch=1,
867                 out_ch=1,
868                 x_in=1,
869                 y_in=1,
870                 w_x=1,
871                 w_y=1,
872                 stride_x=1,
873                 stride_y=1,
874                 pad=False,
875                 randmin=INT8_MIN,
876                 randmax=INT8_MAX,
877                 batches=1,
878                 generate_bias=True,
879                 out_activation_min=None,
880                 out_activation_max=None,
881                 int16xint8=False,
882                 bias_min=INT32_MIN,
883                 bias_max=INT32_MAX):
884        super().__init__(dataset,
885                         testtype,
886                         regenerate_weights,
887                         regenerate_input,
888                         regenerate_biases,
889                         schema_file,
890                         in_ch,
891                         out_ch,
892                         x_in,
893                         y_in,
894                         x_in,
895                         y_in,
896                         stride_x,
897                         stride_y,
898                         pad,
899                         randmin,
900                         randmax,
901                         batches,
902                         generate_bias=generate_bias,
903                         out_activation_min=out_activation_min,
904                         out_activation_max=out_activation_max,
905                         int16xint8=int16xint8,
906                         bias_min=bias_min,
907                         bias_max=bias_max)
908
909    def write_c_config_header(self) -> None:
910        super().write_c_config_header()
911
912        filename = self.config_data
913        filepath = self.headers_dir + filename
914        prefix = self.testdataset.upper()
915
916        with open(filepath, "a") as f:
917            f.write("#define {}_OUTPUT_MULTIPLIER {}\n".format(prefix, self.quantized_multiplier))
918            f.write("#define {}_OUTPUT_SHIFT {}\n".format(prefix, self.quantized_shift))
919            f.write("#define {}_ACCUMULATION_DEPTH {}\n".format(prefix, self.input_ch * self.x_input * self.y_input))
920            f.write("#define {}_INPUT_OFFSET {}\n".format(prefix, -self.input_zero_point))
921            f.write("#define {}_OUTPUT_OFFSET {}\n".format(prefix, self.output_zero_point))
922
923    def quantize_multiplier(self):
924        input_product_scale = self.input_scale * self.weights_scale
925        if input_product_scale < 0:
926            raise RuntimeError("negative input product scale")
927        real_multipler = input_product_scale / self.output_scale
928        (self.quantized_multiplier, self.quantized_shift) = self.quantize_scale(real_multipler)
929
930    def generate_data(self, input_data=None, weights=None, biases=None) -> None:
931        input_data = self.get_randomized_input_data(input_data,
932                                                    [self.batches, self.input_ch * self.x_input * self.y_input])
933
934        if self.is_int16xint8:
935            inttype = tf.int16
936            datatype = "int16_t"
937            bias_datatype = "int64_t"
938        else:
939            inttype = tf.int8
940            datatype = "int8_t"
941            bias_datatype = "int32_t"
942
943        fc_weights_format = [self.input_ch * self.y_input * self.x_input, self.output_ch]
944
945        if weights is not None:
946            weights = tf.reshape(weights, fc_weights_format)
947        else:
948            weights = self.get_randomized_data(fc_weights_format,
949                                               self.kernel_table_file,
950                                               minrange=INT32_MIN,
951                                               maxrange=INT32_MAX,
952                                               regenerate=self.regenerate_new_weights)
953
954        biases = self.get_randomized_bias_data(biases)
955
956        # Create model with one fully_connected layer.
957        model = tf.keras.models.Sequential()
958        model.add(
959            tf.keras.layers.InputLayer(input_shape=(self.y_input * self.x_input * self.input_ch, ),
960                                       batch_size=self.batches))
961        fully_connected_layer = tf.keras.layers.Dense(self.output_ch, activation=None)
962        model.add(fully_connected_layer)
963        fully_connected_layer.set_weights([weights, biases])
964
965        interpreter = self.convert_and_interpret(model, inttype, input_data)
966
967        all_layers_details = interpreter.get_tensor_details()
968        if self.generate_bias:
969            filter_layer = all_layers_details[2]
970            bias_layer = all_layers_details[1]
971        else:
972            filter_layer = all_layers_details[1]
973        if weights.numpy().size != interpreter.get_tensor(filter_layer['index']).size or \
974           (self.generate_bias and biases.numpy().size != interpreter.get_tensor(bias_layer['index']).size):
975            raise RuntimeError(f"Dimension mismatch for {self.testdataset}")
976
977        # The generic destination size calculation for these tests are: self.x_output * self.y_output * self.output_ch
978        # * self.batches.
979        self.x_output = 1
980        self.y_output = 1
981        output_details = interpreter.get_output_details()
982        if self.output_ch != output_details[0]['shape'][1] or self.batches != output_details[0]['shape'][0]:
983            raise RuntimeError("Fully connected out dimension mismatch")
984
985        self.weights_scale = filter_layer['quantization_parameters']['scales'][0]
986        self.quantize_multiplier()
987
988        self.generate_c_array(self.input_data_file_prefix, input_data, datatype=datatype)
989        self.generate_c_array(self.weight_data_file_prefix, interpreter.get_tensor(filter_layer['index']))
990
991        if self.generate_bias:
992            self.generate_c_array(self.bias_data_file_prefix, interpreter.get_tensor(bias_layer['index']),
993                                  bias_datatype)
994        else:
995            self.generate_c_array(self.bias_data_file_prefix, biases, bias_datatype)
996
997        # Generate reference
998        interpreter.invoke()
999        output_data = interpreter.get_tensor(output_details[0]["index"])
1000        self.generate_c_array(self.output_data_file_prefix,
1001                              np.clip(output_data, self.out_activation_min, self.out_activation_max),
1002                              datatype=datatype)
1003
1004        self.write_c_config_header()
1005        self.write_c_header_wrapper()
1006
1007
1008class SoftmaxSettings(TestSettings):
1009    softmax_input_integer_bits = 5
1010
1011    def __init__(self,
1012                 dataset,
1013                 testtype,
1014                 regenerate_weights,
1015                 regenerate_input,
1016                 regenerate_biases,
1017                 schema_file,
1018                 x_in=5,
1019                 y_in=1,
1020                 randmin=INT8_MIN,
1021                 randmax=INT8_MAX,
1022                 int16xint8=False,
1023                 inInt8outInt16=False,
1024                 input_scale=0.003922,
1025                 input_zp=-128):
1026        super().__init__(dataset,
1027                         testtype,
1028                         regenerate_weights,
1029                         regenerate_input,
1030                         regenerate_biases,
1031                         schema_file,
1032                         1,
1033                         1,
1034                         x_in,
1035                         y_in,
1036                         1,
1037                         1,
1038                         1,
1039                         1,
1040                         False,
1041                         randmin,
1042                         randmax,
1043                         int16xint8=int16xint8)
1044        self.x_input = self.x_output = x_in
1045        self.y_input = self.y_output = y_in
1046        self.inInt8outInt16 = inInt8outInt16
1047
1048        if self.inInt8outInt16 and self.is_int16xint8:
1049            raise RuntimeError("Specify input as either s8 or s16")
1050
1051        if self.inInt8outInt16:
1052            self.input_scale = input_scale
1053            self.json_template = "TestCases/Common/Softmax/softmax_int8_to_int16_template.json"
1054            self.json_replacements = {
1055                "num_rows": self.y_input,
1056                "row_size": self.x_input,
1057                "input_scale": input_scale,
1058                "input_zp": input_zp
1059            }
1060
1061    def calc_softmax_params(self):
1062        if self.is_int16xint8:
1063            input_scale_beta_rescale = self.input_scale / (10.0 / 65535.0)
1064            (self.input_multiplier, self.input_left_shift) = self.quantize_scale(input_scale_beta_rescale)
1065        else:
1066            input_real_multiplier = min(self.input_scale * (1 << (31 - self.softmax_input_integer_bits)), (1 << 31) - 1)
1067            (self.input_multiplier, self.input_left_shift) = self.quantize_scale(input_real_multiplier)
1068
1069            self.diff_min = ((1 << self.softmax_input_integer_bits) - 1) * \
1070                            (1 << (31 - self.softmax_input_integer_bits)) / \
1071                            (1 << self.input_left_shift)
1072            self.diff_min = math.floor(self.diff_min)
1073
1074    def write_c_config_header(self) -> None:
1075        super().write_c_config_header(write_common_parameters=False)
1076
1077        filename = self.config_data
1078        filepath = self.headers_dir + filename
1079        prefix = self.testdataset.upper()
1080
1081        with open(filepath, "a") as f:
1082            f.write("#define {}_NUM_ROWS {}\n".format(prefix, self.y_input))
1083            f.write("#define {}_ROW_SIZE {}\n".format(prefix, self.x_input))
1084            f.write("#define {}_INPUT_MULT {}\n".format(prefix, self.input_multiplier))
1085            f.write("#define {}_INPUT_LEFT_SHIFT {}\n".format(prefix, self.input_left_shift))
1086            if not self.is_int16xint8:
1087                f.write("#define {}_DIFF_MIN {}\n".format(prefix, -self.diff_min))
1088            f.write("#define {}_DST_SIZE {}\n".format(prefix, self.x_output * self.y_output))
1089
1090    def get_softmax_randomized_input_data(self, input_data, input_shape):
1091        # Generate or load saved input data unless hardcoded data provided.
1092        if input_data is not None:
1093            input_data = tf.reshape(input_data, input_shape)
1094        else:
1095            input_data = self.get_randomized_data(input_shape,
1096                                                  self.inputs_table_file,
1097                                                  regenerate=self.regenerate_new_input)
1098        return input_data
1099
1100    def generate_data(self, input_data=None, weights=None, biases=None) -> None:
1101        input_data = self.get_softmax_randomized_input_data(input_data, [self.y_input, self.x_input])
1102
1103        if self.is_int16xint8:
1104            inttype = tf.int16
1105            datatype = "int16_t"
1106        else:
1107            inttype = tf.int8
1108            datatype = "int8_t"
1109
1110        self.generate_c_array(self.input_data_file_prefix, input_data, datatype=datatype)
1111
1112        # Generate reference.
1113        if self.inInt8outInt16:
1114            # Output is int16.
1115            datatype = "int16_t"
1116
1117            # Keras does not support int8 input and int16 output for Softmax.
1118            # Using a template json instead.
1119            generated_json = self.generate_json_from_template()
1120            self.flatc_generate_tflite(generated_json, self.schema_file)
1121
1122            interpreter = Interpreter(model_path=str(self.model_path_tflite),
1123                                      experimental_op_resolver_type=OpResolverType.BUILTIN_REF)
1124            interpreter.allocate_tensors()
1125            all_layers_details = interpreter.get_tensor_details()
1126            input_layer = all_layers_details[0]
1127            output_layer = all_layers_details[1]
1128
1129            interpreter.set_tensor(input_layer["index"], tf.cast(input_data, tf.int8))
1130            interpreter.invoke()
1131            output_data = interpreter.get_tensor(output_layer["index"])
1132        else:
1133            # Create a one-layer Keras model.
1134            model = tf.keras.models.Sequential()
1135            input_shape = (self.y_input, self.x_input)
1136            model.add(tf.keras.layers.Softmax(input_shape=input_shape))
1137
1138            interpreter = self.convert_and_interpret(model, inttype, tf.expand_dims(input_data, axis=0))
1139            output_details = interpreter.get_output_details()
1140            interpreter.invoke()
1141            output_data = interpreter.get_tensor(output_details[0]["index"])
1142
1143        self.calc_softmax_params()
1144        self.generate_c_array(self.output_data_file_prefix, output_data, datatype=datatype)
1145
1146        self.write_c_config_header()
1147        self.write_c_header_wrapper()
1148
1149
1150class SVDFSettings(TestSettings):
1151
1152    def __init__(self,
1153                 dataset,
1154                 testtype,
1155                 regenerate_weights,
1156                 regenerate_input,
1157                 regenerate_biases,
1158                 schema_file,
1159                 batches=2,
1160                 number_inputs=2,
1161                 rank=8,
1162                 memory_size=10,
1163                 randmin=INT8_MIN,
1164                 randmax=INT8_MAX,
1165                 input_size=3,
1166                 number_units=4,
1167                 generate_bias=True,
1168                 int8_time_weights=False,
1169                 input_scale=0.1,
1170                 input_zp=0,
1171                 w_1_scale=0.005,
1172                 w_1_zp=0,
1173                 w_2_scale=0.005,
1174                 w_2_zp=0,
1175                 bias_scale=0.000001,
1176                 bias_zp=0,
1177                 state_scale=0.005,
1178                 state_zp=0,
1179                 output_scale=0.1,
1180                 output_zp=0):
1181        super().__init__(dataset,
1182                         testtype,
1183                         regenerate_weights,
1184                         regenerate_input,
1185                         regenerate_biases,
1186                         schema_file,
1187                         1,
1188                         1,
1189                         1,
1190                         1,
1191                         1,
1192                         1,
1193                         1,
1194                         1,
1195                         False,
1196                         randmin,
1197                         randmax,
1198                         generate_bias=generate_bias)
1199        self.batches = batches
1200        self.number_units = number_units
1201        self.input_size = input_size
1202        self.memory_size = memory_size
1203        self.rank = rank
1204        self.number_filters = self.number_units * self.rank
1205        self.time_table_file = self.pregenerated_data_dir + self.testdataset + '/' + 'time_data.txt'
1206
1207        self.number_inputs = number_inputs
1208        self.input_sequence_length = self.number_inputs * self.input_size * self.batches
1209
1210        self.in_activation_max = INT16_MAX
1211        self.in_activation_min = INT16_MIN
1212
1213        self.int8_time_weights = int8_time_weights
1214
1215        if self.int8_time_weights:
1216            self.json_template = "TestCases/Common/svdf_s8_weights_template.json"
1217        else:
1218            self.json_template = "TestCases/Common/svdf_template.json"
1219
1220        self.json_replacements = {
1221            "memory_sizeXnumber_filters": self.memory_size * self.number_filters,
1222            "batches": self.batches,
1223            "input_size": self.input_size,
1224            "number_filters": self.number_filters,
1225            "memory_size": self.memory_size,
1226            "number_units": self.number_units,
1227            "rank_value": self.rank,
1228            "input_scale": input_scale,
1229            "input_zp": input_zp,
1230            "w_1_scale": w_1_scale,
1231            "w_1_zp": w_1_zp,
1232            "w_2_scale": w_2_scale,
1233            "w_2_zp": w_2_zp,
1234            "bias_scale": bias_scale,
1235            "bias_zp": bias_zp,
1236            "state_scale": state_scale,
1237            "state_zp": state_zp,
1238            "output_scale": output_scale,
1239            "output_zp": output_zp
1240        }
1241
1242    def calc_multipliers_and_shifts(self, input_scale, weights_1_scale, weights_2_scale, state_scale, output_scale):
1243        effective_scale_1 = weights_1_scale * input_scale / state_scale
1244        effective_scale_2 = state_scale * weights_2_scale / output_scale
1245        (self.multiplier_in, self.shift_1) = self.quantize_scale(effective_scale_1)
1246        (self.multiplier_out, self.shift_2) = self.quantize_scale(effective_scale_2)
1247
1248    def write_c_config_header(self) -> None:
1249        super().write_c_config_header(write_common_parameters=False)
1250
1251        filename = self.config_data
1252        filepath = self.headers_dir + filename
1253        prefix = self.testdataset.upper()
1254
1255        with open(filepath, "a") as f:
1256            f.write("#define {}_MULTIPLIER_IN {}\n".format(prefix, self.multiplier_in))
1257            f.write("#define {}_MULTIPLIER_OUT {}\n".format(prefix, self.multiplier_out))
1258            f.write("#define {}_SHIFT_1 {}\n".format(prefix, self.shift_1))
1259            f.write("#define {}_SHIFT_2 {}\n".format(prefix, self.shift_2))
1260            f.write("#define {}_IN_ACTIVATION_MIN {}\n".format(prefix, self.in_activation_min))
1261            f.write("#define {}_IN_ACTIVATION_MAX {}\n".format(prefix, self.in_activation_max))
1262            f.write("#define {}_RANK {}\n".format(prefix, self.rank))
1263            f.write("#define {}_FEATURE_BATCHES {}\n".format(prefix, self.number_filters))
1264            f.write("#define {}_TIME_BATCHES {}\n".format(prefix, self.memory_size))
1265            f.write("#define {}_INPUT_SIZE {}\n".format(prefix, self.input_size))
1266            f.write("#define {}_DST_SIZE {}\n".format(prefix, self.number_units * self.batches))
1267            f.write("#define {}_OUT_ACTIVATION_MIN {}\n".format(prefix, self.out_activation_min))
1268            f.write("#define {}_OUT_ACTIVATION_MAX {}\n".format(prefix, self.out_activation_max))
1269            f.write("#define {}_INPUT_BATCHES {}\n".format(prefix, self.batches))
1270            f.write("#define {}_INPUT_OFFSET {}\n".format(prefix, self.input_zero_point))
1271            f.write("#define {}_OUTPUT_OFFSET {}\n".format(prefix, self.output_zero_point))
1272
1273    def generate_data(self, input_data=None, weights=None, biases=None, time_data=None, state_data=None) -> None:
1274        if input_data is not None:
1275            input_data = tf.reshape(input_data, [self.input_sequence_length])
1276        else:
1277            input_data = self.get_randomized_data([self.input_sequence_length],
1278                                                  self.inputs_table_file,
1279                                                  regenerate=self.regenerate_new_input)
1280        self.generate_c_array("input_sequence", input_data)
1281
1282        if weights is not None:
1283            weights_feature_data = tf.reshape(weights, [self.number_filters, self.input_size])
1284        else:
1285            weights_feature_data = self.get_randomized_data([self.number_filters, self.input_size],
1286                                                            self.kernel_table_file,
1287                                                            regenerate=self.regenerate_new_weights)
1288
1289        if time_data is not None:
1290            weights_time_data = tf.reshape(time_data, [self.number_filters, self.memory_size])
1291        else:
1292            weights_time_data = self.get_randomized_data([self.number_filters, self.memory_size],
1293                                                         self.time_table_file,
1294                                                         regenerate=self.regenerate_new_weights)
1295
1296        if not self.generate_bias:
1297            biases = [0] * self.number_units
1298        if biases is not None:
1299            biases = tf.reshape(biases, [self.number_units])
1300        else:
1301            biases = self.get_randomized_data([self.number_units],
1302                                              self.bias_table_file,
1303                                              regenerate=self.regenerate_new_weights)
1304
1305        # Generate tflite model
1306        generated_json = self.generate_json_from_template(weights_feature_data,
1307                                                          weights_time_data,
1308                                                          biases,
1309                                                          self.int8_time_weights)
1310        self.flatc_generate_tflite(generated_json, self.schema_file)
1311
1312        # Run TFL interpreter
1313        interpreter = Interpreter(model_path=str(self.model_path_tflite),
1314                                  experimental_op_resolver_type=OpResolverType.BUILTIN_REF)
1315        interpreter.allocate_tensors()
1316
1317        # Read back scales and zero points from tflite model
1318        all_layers_details = interpreter.get_tensor_details()
1319        input_layer = all_layers_details[0]
1320        weights_1_layer = all_layers_details[1]
1321        weights_2_layer = all_layers_details[2]
1322        bias_layer = all_layers_details[3]
1323        state_layer = all_layers_details[4]
1324        output_layer = all_layers_details[5]
1325        (input_scale, self.input_zero_point) = self.get_scale_and_zp(input_layer)
1326        (weights_1_scale, zero_point) = self.get_scale_and_zp(weights_1_layer)
1327        (weights_2_scale, zero_point) = self.get_scale_and_zp(weights_2_layer)
1328        (bias_scale, zero_point) = self.get_scale_and_zp(bias_layer)
1329        (state_scale, zero_point) = self.get_scale_and_zp(state_layer)
1330        (output_scale, self.output_zero_point) = self.get_scale_and_zp(output_layer)
1331
1332        self.calc_multipliers_and_shifts(input_scale, weights_1_scale, weights_2_scale, state_scale, output_scale)
1333
1334        # Generate unit test C headers
1335        self.generate_c_array("weights_feature", interpreter.get_tensor(weights_1_layer['index']))
1336        self.generate_c_array(self.bias_data_file_prefix, interpreter.get_tensor(bias_layer['index']), "int32_t")
1337
1338        if self.int8_time_weights:
1339            self.generate_c_array("weights_time", interpreter.get_tensor(weights_2_layer['index']), datatype='int8_t')
1340            self.generate_c_array("state", interpreter.get_tensor(state_layer['index']), "int8_t")
1341        else:
1342            self.generate_c_array("weights_time", interpreter.get_tensor(weights_2_layer['index']), datatype='int16_t')
1343            self.generate_c_array("state", interpreter.get_tensor(state_layer['index']), "int16_t")
1344
1345        # TODO: generate output reference with int8 time weights.
1346        if self.int8_time_weights:
1347            self.write_c_config_header()
1348            self.write_c_header_wrapper()
1349            return
1350
1351        # Generate reference output
1352        svdf_ref = None
1353        for i in range(self.number_inputs):
1354            start = i * self.input_size * self.batches
1355            end = i * self.input_size * self.batches + self.input_size * self.batches
1356            input_sequence = input_data[start:end]
1357            input_sequence = tf.reshape(input_sequence, [self.batches, self.input_size])
1358            interpreter.set_tensor(input_layer["index"], tf.cast(input_sequence, tf.int8))
1359            interpreter.invoke()
1360            svdf_ref = interpreter.get_tensor(output_layer["index"])
1361        self.generate_c_array(self.output_data_file_prefix, svdf_ref)
1362
1363        self.write_c_config_header()
1364        self.write_c_header_wrapper()
1365
1366    def get_scale_and_zp(self, layer):
1367        return (layer['quantization_parameters']['scales'][0], layer['quantization_parameters']['zero_points'][0])
1368
1369
1370class AddMulSettings(TestSettings):
1371
1372    def __init__(self,
1373                 dataset,
1374                 testtype,
1375                 regenerate_weights,
1376                 regenerate_input,
1377                 regenerate_biases,
1378                 schema_file,
1379                 channels=1,
1380                 x_in=4,
1381                 y_in=4,
1382                 decimal_input=6,
1383                 randmin=INT8_MIN,
1384                 randmax=INT8_MAX,
1385                 out_activation_min=INT8_MIN,
1386                 out_activation_max=INT8_MAX,
1387                 int16xint8=False):
1388        super().__init__(dataset,
1389                         testtype,
1390                         regenerate_weights,
1391                         regenerate_input,
1392                         regenerate_biases,
1393                         schema_file,
1394                         in_ch=channels,
1395                         out_ch=channels,
1396                         x_in=x_in,
1397                         y_in=y_in,
1398                         w_x=1,
1399                         w_y=1,
1400                         stride_x=1,
1401                         stride_y=1,
1402                         pad=False,
1403                         randmin=randmin,
1404                         randmax=randmax,
1405                         batches=1,
1406                         generate_bias=False,
1407                         relu6=False,
1408                         out_activation_min=out_activation_min,
1409                         out_activation_max=out_activation_max,
1410                         int16xint8=int16xint8)
1411
1412        self.x_input = self.x_output = x_in
1413        self.y_input = self.y_output = y_in
1414        self.decimal_input = decimal_input
1415
1416        self.left_shift = 15 if self.is_int16xint8 else 20
1417
1418    def generate_data(self, input_data1=None, input_data2=None) -> None:
1419        input_shape = (1, self.y_input, self.x_input, self.input_ch)
1420
1421        input_data1 = self.get_randomized_data(list(input_shape),
1422                                               self.inputs_table_file,
1423                                               regenerate=self.regenerate_new_input,
1424                                               decimals=self.decimal_input)
1425        input_data2 = self.get_randomized_data(list(input_shape),
1426                                               self.kernel_table_file,
1427                                               regenerate=self.regenerate_new_weights,
1428                                               decimals=self.decimal_input)
1429
1430        if self.is_int16xint8:
1431            inttype = "int16_t"
1432            inttype_tf = tf.int16
1433        else:
1434            inttype = "int8_t"
1435            inttype_tf = tf.int8
1436
1437        # Create a one-layer functional Keras model as add/mul cannot use a sequntial Keras model.
1438        input1 = tf.keras.layers.Input(shape=input_shape[1:])
1439        input2 = tf.keras.layers.Input(shape=input_shape[1:])
1440        if self.test_type == 'add':
1441            layer = tf.keras.layers.Add()([input1, input2])
1442        elif self.test_type == 'mul':
1443            layer = tf.keras.layers.Multiply()([input1, input2])
1444        else:
1445            raise RuntimeError("Wrong test type")
1446        out = tf.keras.layers.Lambda(function=lambda x: x)(layer)
1447        model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)
1448
1449        interpreter = self.convert_and_interpret(model, inttype_tf)
1450
1451        input_details = interpreter.get_input_details()
1452        interpreter.set_tensor(input_details[0]["index"], tf.cast(input_data1, inttype_tf))
1453        interpreter.set_tensor(input_details[1]["index"], tf.cast(input_data2, inttype_tf))
1454
1455        # Calculate multipliers, shifts and offsets.
1456        (input1_scale, self.input1_zero_point) = input_details[0]['quantization']
1457        (input2_scale, self.input2_zero_point) = input_details[1]['quantization']
1458        self.input1_zero_point = -self.input1_zero_point
1459        self.input2_zero_point = -self.input2_zero_point
1460        double_max_input_scale = max(input1_scale, input2_scale) * 2
1461        (self.input1_mult, self.input1_shift) = self.quantize_scale(input1_scale / double_max_input_scale)
1462        (self.input2_mult, self.input2_shift) = self.quantize_scale(input2_scale / double_max_input_scale)
1463
1464        if self.test_type == 'add':
1465            actual_output_scale = double_max_input_scale / ((1 << self.left_shift) * self.output_scale)
1466        elif self.test_type == 'mul':
1467            actual_output_scale = input1_scale * input2_scale / self.output_scale
1468        (self.output_mult, self.output_shift) = self.quantize_scale(actual_output_scale)
1469
1470        # Generate reference.
1471        interpreter.invoke()
1472        output_details = interpreter.get_output_details()
1473        output_data = interpreter.get_tensor(output_details[0]["index"])
1474        self.generate_c_array("input1", input_data1, datatype=inttype)
1475        self.generate_c_array("input2", input_data2, datatype=inttype)
1476        self.generate_c_array(self.output_data_file_prefix,
1477                              np.clip(output_data, self.out_activation_min, self.out_activation_max),
1478                              datatype=inttype)
1479
1480        self.write_c_config_header()
1481        self.write_c_header_wrapper()
1482
1483    def write_c_config_header(self) -> None:
1484        super().write_c_config_header(write_common_parameters=False)
1485
1486        filename = self.config_data
1487        filepath = self.headers_dir + filename
1488        prefix = self.testdataset.upper()
1489
1490        with open(filepath, "a") as f:
1491            f.write("#define {}_DST_SIZE {}\n".format(prefix,
1492                                                      self.batches * self.y_input * self.x_input * self.input_ch))
1493            f.write("#define {}_OUT_ACTIVATION_MIN {}\n".format(prefix, self.out_activation_min))
1494            f.write("#define {}_OUT_ACTIVATION_MAX {}\n".format(prefix, self.out_activation_max))
1495            f.write("#define {}_INPUT1_OFFSET {}\n".format(prefix, self.input1_zero_point))
1496            f.write("#define {}_INPUT2_OFFSET {}\n".format(prefix, self.input2_zero_point))
1497            f.write("#define {}_OUTPUT_MULT {}\n".format(prefix, self.output_mult))
1498            f.write("#define {}_OUTPUT_SHIFT {}\n".format(prefix, self.output_shift))
1499            f.write("#define {}_OUTPUT_OFFSET {}\n".format(prefix, self.output_zero_point))
1500            if self.test_type == 'add':
1501                f.write("#define {}_LEFT_SHIFT {}\n".format(prefix, self.left_shift))
1502                f.write("#define {}_INPUT1_SHIFT {}\n".format(prefix, self.input1_shift))
1503                f.write("#define {}_INPUT2_SHIFT {}\n".format(prefix, self.input2_shift))
1504                f.write("#define {}_INPUT1_MULT {}\n".format(prefix, self.input1_mult))
1505                f.write("#define {}_INPUT2_MULT {}\n".format(prefix, self.input2_mult))
1506
1507
1508class LSTMSettings(TestSettings):
1509
1510    def __init__(self,
1511                 dataset,
1512                 testtype,
1513                 regenerate_weights,
1514                 regenerate_input,
1515                 regenerate_biases,
1516                 schema_file,
1517                 batches=2,
1518                 time_steps=2,
1519                 number_inputs=3,
1520                 number_units=4,
1521                 time_major=True,
1522                 randmin=INT8_MIN,
1523                 randmax=INT8_MAX,
1524                 generate_bias=True):
1525        super().__init__(dataset,
1526                         testtype,
1527                         regenerate_weights,
1528                         regenerate_input,
1529                         regenerate_biases,
1530                         schema_file,
1531                         1,
1532                         1,
1533                         1,
1534                         1,
1535                         1,
1536                         1,
1537                         1,
1538                         1,
1539                         False,
1540                         randmin,
1541                         randmax,
1542                         generate_bias=generate_bias)
1543
1544        self.batches = batches
1545        self.time_steps = time_steps
1546        self.number_units = number_units
1547        self.number_inputs = number_inputs
1548
1549        self.kernel_hidden_table_file = self.pregenerated_data_dir + self.testdataset + '/' + 'kernel_hidden.txt'
1550
1551        self.time_major = time_major
1552
1553        self.in_activation_max = INT16_MAX
1554        self.in_activation_min = INT16_MIN
1555
1556        self.lstm_scales = []
1557
1558        # Layer indexes. Works with tensorflow 2.10 and 2.11.
1559        self.output_gate_bias_index = 1
1560        self.cell_gate_bias_index = 2
1561        self.forget_gate_bias_index = 3
1562        self.input_gate_bias_index = 4
1563        self.recurrent_input_to_output_w_index = 5
1564        self.recurrent_input_to_cell_w_index = 6
1565        self.recurrent_input_to_forget_w_index = 7
1566        self.recurrent_input_to_input_w_index = 8
1567        self.input_to_output_w_index = 9
1568        self.input_to_cell_w_index = 10
1569        self.input_to_forget_w_index = 11
1570        self.input_to_input_w_index = 12
1571        self.output_state_index = 13
1572        self.cell_state_index = 14
1573        self.input_norm_coeff_index = 15
1574        self.forget_norm_coeff_index = 16
1575        self.cell_norm_coeff_index = 17
1576        self.output_norm_coeff_index = 18
1577        self.effective_hidden_scale_intermediate_index = 20
1578
1579    def generate_data(self, input_data=None, weights=None, hidden_weights=None, biases=None) -> None:
1580
1581        input_dims = [self.batches, self.time_steps, self.number_inputs]
1582        if input_data is not None:
1583            input_data = tf.reshape(input_data, input_dims)
1584        else:
1585            input_data = self.get_randomized_data(input_dims,
1586                                                  self.inputs_table_file,
1587                                                  regenerate=self.regenerate_new_input)
1588
1589        # This will be the same size when there is no projection.
1590        number_cells = self.number_units
1591
1592        # Each LSTM cell has 4 input weights, 4 hidden (recurrent or cell state) weights and 4 biases.
1593        number_w_b = 4
1594
1595        if weights is not None:
1596            weights = tf.reshape(weights, [self.number_inputs, number_cells * number_w_b])
1597        else:
1598            weights = self.get_randomized_data([self.number_inputs, number_cells * number_w_b],
1599                                               self.kernel_table_file,
1600                                               regenerate=self.regenerate_new_weights,
1601                                               decimals=8,
1602                                               minrange=-1.0,
1603                                               maxrange=1.0)
1604
1605        if hidden_weights is not None:
1606            hidden_weights = tf.reshape(hidden_weights, [number_cells, number_cells * number_w_b])
1607        else:
1608            hidden_weights = self.get_randomized_data([number_cells, number_cells * number_w_b],
1609                                                      self.kernel_hidden_table_file,
1610                                                      regenerate=self.regenerate_new_weights,
1611                                                      decimals=8,
1612                                                      minrange=-1.0,
1613                                                      maxrange=1.0)
1614        if not self.generate_bias:
1615            biases = [0] * number_cells * number_w_b
1616        if biases is not None:
1617            biases = tf.reshape(biases, [number_cells * number_w_b])
1618        else:
1619            biases = self.get_randomized_data([number_cells * number_w_b],
1620                                              self.bias_table_file,
1621                                              regenerate=self.regenerate_new_bias,
1622                                              decimals=8,
1623                                              minrange=-1.0,
1624                                              maxrange=1.0)
1625
1626        # Create a Keras based LSTM model.
1627        input_layer = tf.keras.layers.Input(shape=(self.time_steps, self.number_inputs),
1628                                            batch_size=self.batches,
1629                                            name='input')
1630        if self.time_major:
1631            input_layer_transposed = tf.transpose(input_layer, perm=[1, 0, 2])
1632            lstm_layer = tf.keras.layers.LSTM(units=self.number_units,
1633                                              time_major=self.time_major,
1634                                              return_sequences=True)(input_layer_transposed)
1635        else:
1636            lstm_layer = tf.keras.layers.LSTM(units=self.number_units,
1637                                              time_major=self.time_major,
1638                                              return_sequences=True)(input_layer)
1639        model = tf.keras.Model(input_layer, lstm_layer, name="LSTM")
1640
1641        if self.time_major:
1642            time_major_offset = 1
1643            shape = (self.time_steps, self.batches, self.number_inputs)
1644        else:
1645            time_major_offset = 0
1646            shape = (self.batches, self.time_steps, self.number_inputs)
1647
1648        # Writing weight and bias to model.
1649        print("Updating weights", model.layers[1 + time_major_offset].weights[0].name)
1650        model.layers[1 + time_major_offset].weights[0].assign(weights)
1651        print("Updating hidden weights", model.layers[1 + time_major_offset].weights[1].name)
1652        model.layers[1 + time_major_offset].weights[1].assign(hidden_weights)
1653        print("Updating bias", model.layers[1 + time_major_offset].weights[2].name)
1654        model.layers[1 + time_major_offset].weights[2].assign(biases)
1655
1656        interpreter = self.convert_and_interpret(model, tf.int8, input_data, dataset_shape=shape)
1657
1658        all_layers_details = interpreter.get_tensor_details()
1659
1660        for i in all_layers_details:
1661            self.lstm_scales.append(i['quantization_parameters']['scales'])
1662
1663        input_data_for_index = all_layers_details[0]
1664
1665        input_gate_bias = all_layers_details[self.input_gate_bias_index + time_major_offset]
1666        forget_gate_bias = all_layers_details[self.forget_gate_bias_index + time_major_offset]
1667        cell_gate_bias = all_layers_details[self.cell_gate_bias_index + time_major_offset]
1668        output_gate_bias = all_layers_details[self.output_gate_bias_index + time_major_offset]
1669
1670        input_to_input_w = all_layers_details[self.input_to_input_w_index + time_major_offset]
1671        input_to_forget_w = all_layers_details[self.input_to_forget_w_index + time_major_offset]
1672        input_to_cell_w = all_layers_details[self.input_to_cell_w_index + time_major_offset]
1673        input_to_output_w = all_layers_details[self.input_to_output_w_index + time_major_offset]
1674
1675        recurrent_input_to_input_w = all_layers_details[self.recurrent_input_to_input_w_index + time_major_offset]
1676        recurrent_input_to_forget_w = all_layers_details[self.recurrent_input_to_forget_w_index + time_major_offset]
1677        recurrent_input_to_cell_w = all_layers_details[self.recurrent_input_to_cell_w_index + time_major_offset]
1678        recurrent_input_to_output_w = all_layers_details[self.recurrent_input_to_output_w_index + time_major_offset]
1679
1680        if self.time_major:
1681            time_major_offset = 2
1682
1683        output_state = all_layers_details[self.output_state_index + time_major_offset]
1684        cell_state = all_layers_details[self.cell_state_index + time_major_offset]
1685
1686        input_norm_coeff = all_layers_details[self.input_norm_coeff_index + time_major_offset]
1687        forget_norm_coeff = all_layers_details[self.forget_norm_coeff_index + time_major_offset]
1688        cell_norm_coeff = all_layers_details[self.cell_norm_coeff_index + time_major_offset]
1689        output_norm_coeff = all_layers_details[self.output_norm_coeff_index + time_major_offset]
1690
1691        # For scale and zero point.
1692        effective_hidden_scale_intermediate = all_layers_details[self.effective_hidden_scale_intermediate_index +
1693                                                                 time_major_offset]
1694
1695        input_details = interpreter.get_input_details()
1696        output_details = interpreter.get_output_details()
1697        actual_input_data = interpreter.get_tensor(input_details[0]["index"])
1698        if (input_data.numpy().shape != actual_input_data.shape) or \
1699           not ((input_data.numpy().astype(int) == actual_input_data).all().astype(int)):
1700            raise RuntimeError("Input data mismatch")
1701
1702        self.generate_c_array(self.input_data_file_prefix, interpreter.get_tensor(input_data_for_index['index']))
1703        self.generate_c_array("input_to_input_w", interpreter.get_tensor(input_to_input_w['index']))
1704        self.generate_c_array("input_to_forget_w", interpreter.get_tensor(input_to_forget_w['index']))
1705        self.generate_c_array("input_to_cell_w", interpreter.get_tensor(input_to_cell_w['index']))
1706        self.generate_c_array("input_to_output_w", interpreter.get_tensor(input_to_output_w['index']))
1707        self.generate_c_array("recurrent_input_to_input_w", interpreter.get_tensor(recurrent_input_to_input_w['index']))
1708        self.generate_c_array("recurrent_input_to_forget_w",
1709                              interpreter.get_tensor(recurrent_input_to_forget_w['index']))
1710        self.generate_c_array("recurrent_input_to_cell_w", interpreter.get_tensor(recurrent_input_to_cell_w['index']))
1711        self.generate_c_array("recurrent_input_to_output_w",
1712                              interpreter.get_tensor(recurrent_input_to_output_w['index']))
1713
1714        # Peephole not supported so these are nullptrs.
1715        self.generate_c_array("cell_to_input", [], datatype='int16_t')
1716        self.generate_c_array("cell_to_forget", [], datatype='int16_t')
1717        self.generate_c_array("cell_to_output", [], datatype='int16_t')
1718
1719        self.generate_c_array("input_gate_bias", interpreter.get_tensor(input_gate_bias['index']), datatype='int32_t')
1720        self.generate_c_array("cell_gate_bias", interpreter.get_tensor(cell_gate_bias['index']), datatype='int32_t')
1721        self.generate_c_array("forget_gate_bias", interpreter.get_tensor(forget_gate_bias['index']), datatype='int32_t')
1722        self.generate_c_array("output_gate_bias", interpreter.get_tensor(output_gate_bias['index']), datatype='int32_t')
1723
1724        # Projection not supported so these are nullptrs.
1725        self.generate_c_array("projection_weights", [])
1726        self.generate_c_array("projection_bias", [], datatype='int32_t')
1727
1728        self.generate_c_array("output_state", interpreter.get_tensor(output_state['index']), const="")
1729        self.generate_c_array("cell_state", interpreter.get_tensor(cell_state['index']), datatype='int16_t', const="")
1730
1731        self.generate_c_array("input_norm_coeff", interpreter.get_tensor(input_norm_coeff['index']))
1732        self.generate_c_array("forget_norm_coeff", interpreter.get_tensor(forget_norm_coeff['index']))
1733        self.generate_c_array("cell_norm_coeff", interpreter.get_tensor(cell_norm_coeff['index']))
1734        self.generate_c_array("output_norm_coeff", interpreter.get_tensor(output_norm_coeff['index']))
1735
1736        input_scale = input_data_for_index['quantization_parameters']['scales'][0]
1737        cell_scale = cell_state['quantization_parameters']['scales'][0]
1738        output_state_scale = output_state['quantization_parameters']['scales'][0]
1739        input_zp = input_data_for_index['quantization_parameters']['zero_points'][0]
1740        output_zp = output_details[0]['quantization_parameters']['zero_points'][0]
1741        output_state_zp = output_state['quantization_parameters']['zero_points'][0]
1742        self.hidden_zp = effective_hidden_scale_intermediate['quantization_parameters']['zero_points'][0]
1743        self.output_state_offset = output_state_zp
1744
1745        tmp = math.log(cell_scale) * (1 / math.log(2))
1746        self.cell_state_shift = int(round(tmp))
1747
1748        self.calc_scales(input_scale, output_state_scale)
1749
1750        # Calculate effective biases.
1751        input_zp = -input_zp
1752        output_zp = -output_zp
1753        output_state_zp = -output_state_zp
1754        input_to_forget_eff_bias = self.calc_effective_bias(interpreter, input_zp, input_to_forget_w, forget_gate_bias)
1755        recurrent_to_forget_eff_bias = self.calc_effective_bias(interpreter, output_state_zp,
1756                                                                recurrent_input_to_forget_w, None, False)
1757        input_to_cell_eff_bias = self.calc_effective_bias(interpreter, input_zp, input_to_cell_w, cell_gate_bias)
1758        recurrent_to_cell_eff_bias = self.calc_effective_bias(interpreter, output_state_zp, recurrent_input_to_cell_w,
1759                                                              None, False)
1760        input_to_output_eff_bias = self.calc_effective_bias(interpreter, input_zp, input_to_output_w, output_gate_bias)
1761        recurrent_to_output_eff_bias = self.calc_effective_bias(interpreter, output_state_zp,
1762                                                                recurrent_input_to_output_w, None, False)
1763        input_to_input_eff_bias = self.calc_effective_bias(interpreter, input_zp, input_to_input_w, input_gate_bias)
1764
1765        recurrent_to_input_eff_bias = self.calc_effective_bias(interpreter, output_state_zp, recurrent_input_to_input_w,
1766                                                               None, False)
1767
1768        self.generate_c_array("input_to_input_eff_bias", input_to_input_eff_bias, datatype='int32_t')
1769        self.generate_c_array("input_to_forget_eff_bias", input_to_forget_eff_bias, datatype='int32_t')
1770        self.generate_c_array("input_to_cell_eff_bias", input_to_cell_eff_bias, datatype='int32_t')
1771        self.generate_c_array("input_to_output_eff_bias", input_to_output_eff_bias, datatype='int32_t')
1772        self.generate_c_array("recurrent_to_input_eff_bias", recurrent_to_input_eff_bias, datatype='int32_t')
1773        self.generate_c_array("recurrent_to_cell_eff_bias", recurrent_to_cell_eff_bias, datatype='int32_t')
1774        self.generate_c_array("recurrent_to_forget_eff_bias", recurrent_to_forget_eff_bias, datatype='int32_t')
1775        self.generate_c_array("recurrent_to_output_eff_bias", recurrent_to_output_eff_bias, datatype='int32_t')
1776
1777        # Generate reference
1778        interpreter.invoke()
1779        output_data = interpreter.get_tensor(output_details[0]["index"])
1780        self.generate_c_array(self.output_data_file_prefix, output_data, datatype='int8_t')
1781
1782        self.write_c_config_header()
1783        self.write_c_header_wrapper()
1784
1785    def calc_scales(self, input_scale, output_state_scale):
1786        intermediate_scale = pow(2, -12)
1787
1788        if self.time_major:
1789            time_major_offset = 1
1790        else:
1791            time_major_offset = 0
1792
1793        self.effective_hidden_scale = pow(2, -15) / output_state_scale * pow(2, -15)
1794
1795        self.i2i_effective_scale = input_scale * self.lstm_scales[self.input_to_input_w_index + time_major_offset][0] \
1796            / intermediate_scale
1797        self.i2f_effective_scale = input_scale * self.lstm_scales[self.input_to_forget_w_index + time_major_offset][0] \
1798            / intermediate_scale
1799        self.i2c_effective_scale = input_scale * self.lstm_scales[self.input_to_cell_w_index + time_major_offset][0] \
1800            / intermediate_scale
1801        self.i2o_effective_scale = input_scale * self.lstm_scales[self.input_to_output_w_index + time_major_offset][0] \
1802            / intermediate_scale
1803
1804        self.r2i_effective_scale = output_state_scale * self.lstm_scales[self.recurrent_input_to_input_w_index +
1805                                                                         time_major_offset][0] / intermediate_scale
1806        self.r2f_effective_scale = output_state_scale * self.lstm_scales[self.recurrent_input_to_forget_w_index +
1807                                                                         time_major_offset][0] / intermediate_scale
1808        self.r2c_effective_scale = output_state_scale * self.lstm_scales[self.recurrent_input_to_cell_w_index +
1809                                                                         time_major_offset][0] / intermediate_scale
1810        self.r2o_effective_scale = output_state_scale * self.lstm_scales[self.recurrent_input_to_output_w_index +
1811                                                                         time_major_offset][0] / intermediate_scale
1812
1813    def calc_effective_bias(self, interpreter, zero_point, weight_tensor, bias_tensor, has_bias=True) -> list:
1814
1815        weights = interpreter.get_tensor(weight_tensor['index'])
1816        dims = weight_tensor['shape']
1817        row = dims[0]
1818        col = dims[1]
1819
1820        if has_bias:
1821            bias_data = interpreter.get_tensor(bias_tensor['index'])
1822            output = bias_data
1823        else:
1824            output = np.zeros((row, ), dtype=np.int32)
1825
1826        for i_row in range(row):
1827            row_sum = 0
1828            for i_col in range(col):
1829                row_sum = row_sum + weights[i_row][i_col]
1830            output[i_row] = output[i_row] + row_sum * zero_point
1831
1832        return output
1833
1834    def write_c_config_header(self) -> None:
1835        super().write_c_config_header(write_common_parameters=False)
1836
1837        filename = self.config_data
1838        filepath = self.headers_dir + filename
1839        prefix = self.testdataset.upper()
1840
1841        with open(filepath, "a") as f:
1842            f.write("#define {}_BUFFER_SIZE {}\n".format(prefix, self.batches * self.number_units))
1843            f.write("#define {}_INPUT_BATCHES {}\n".format(prefix, self.batches))
1844            f.write("#define {}_DST_SIZE {}\n".format(prefix, self.batches * self.time_steps * self.number_units))
1845            f.write("#define {}_TIME_STEPS {}\n".format(prefix, self.time_steps))
1846            f.write("#define {}_NUMBER_UNITS {}\n".format(prefix, self.number_units))
1847            f.write("#define {}_NUMBER_INPUTS {}\n".format(prefix, self.number_inputs))
1848            f.write("#define {}_TIME_MAJOR {}\n".format(prefix, int(self.time_major)))
1849            f.write("#define {}_IN_ACTIVATION_MIN {}\n".format(prefix, self.in_activation_min))
1850            f.write("#define {}_IN_ACTIVATION_MAX {}\n".format(prefix, self.in_activation_max))
1851
1852            (multiplier, shift) = self.quantize_scale(self.i2i_effective_scale)
1853            f.write("#define {}_IN_TO_INPUT_MULTIPLIER {}\n".format(prefix, multiplier))
1854            f.write("#define {}_IN_TO_INPUT_SHIFT {}\n".format(prefix, shift))
1855            (multiplier, shift) = self.quantize_scale(self.i2f_effective_scale)
1856            f.write("#define {}_IN_TO_FORGET_MULTIPLIER {}\n".format(prefix, multiplier))
1857            f.write("#define {}_IN_TO_FORGET_SHIFT {}\n".format(prefix, shift))
1858            (multiplier, shift) = self.quantize_scale(self.i2c_effective_scale)
1859            f.write("#define {}_IN_TO_CELL_MULTIPLIER {}\n".format(prefix, multiplier))
1860            f.write("#define {}_IN_TO_CELL_SHIFT {}\n".format(prefix, shift))
1861            (multiplier, shift) = self.quantize_scale(self.i2o_effective_scale)
1862            f.write("#define {}_IN_TO_OUTPUT_MULTIPLIER {}\n".format(prefix, multiplier))
1863            f.write("#define {}_IN_TO_OUTPUT_SHIFT {}\n".format(prefix, shift))
1864
1865            (multiplier, shift) = self.quantize_scale(self.r2i_effective_scale)
1866            f.write("#define {}_RECURRENT_TO_INPUT_MULTIPLIER {}\n".format(prefix, multiplier))
1867            f.write("#define {}_RECURRENT_TO_INPUT_SHIFT {}\n".format(prefix, shift))
1868            (multiplier, shift) = self.quantize_scale(self.r2f_effective_scale)
1869            f.write("#define {}_RECURRENT_TO_FORGET_MULTIPLIER {}\n".format(prefix, multiplier))
1870            f.write("#define {}_RECURRENT_TO_FORGET_SHIFT {}\n".format(prefix, shift))
1871            (multiplier, shift) = self.quantize_scale(self.r2c_effective_scale)
1872            f.write("#define {}_RECURRENT_TO_CELL_MULTIPLIER {}\n".format(prefix, multiplier))
1873            f.write("#define {}_RECURRENT_TO_CELL_SHIFT {}\n".format(prefix, shift))
1874            (multiplier, shift) = self.quantize_scale(self.r2o_effective_scale)
1875            f.write("#define {}_RECURRENT_TO_OUTPUT_MULTIPLIER {}\n".format(prefix, multiplier))
1876            f.write("#define {}_RECURRENT_TO_OUTPUT_SHIFT {}\n".format(prefix, shift))
1877
1878            (multiplier, shift) = self.quantize_scale(self.effective_hidden_scale)
1879            f.write("#define {}_HIDDEN_MULTIPLIER {}\n".format(prefix, multiplier))
1880            f.write("#define {}_HIDDEN_SHIFT {}\n".format(prefix, shift))
1881
1882            f.write("#define {}_HIDDEN_OFFSET {}\n".format(prefix, self.hidden_zp))
1883
1884            f.write("#define {}_OUTPUT_STATE_OFFSET {}\n".format(prefix, self.output_state_offset))
1885            f.write("#define {}_CELL_STATE_SHIFT {}\n".format(prefix, self.cell_state_shift))
1886
1887            for i in range(len(self.lstm_scales)):
1888                if len(self.lstm_scales[i]) == 0:
1889                    continue
1890                (multiplier, shift) = self.quantize_scale(self.lstm_scales[i][0])
1891
1892
1893def load_testdata_sets() -> dict:
1894    """
1895    Add all new testdata sets here
1896    """
1897    testdata_sets = {}
1898
1899    regenerate_input = args.regenerate_input
1900    regenerate_weights = args.regenerate_weights
1901    regenerate_biases = args.regenerate_biases
1902
1903    if args.regenerate_all:
1904        regenerate_biases = True
1905        regenerate_weights = True
1906        regenerate_input = True
1907
1908    schema_file = args.schema_file
1909
1910    type_of_test = 'conv'
1911    dataset = 'basic'
1912    testdata_sets[dataset] = ConvSettings(dataset,
1913                                          type_of_test,
1914                                          regenerate_weights,
1915                                          regenerate_input,
1916                                          regenerate_biases,
1917                                          schema_file,
1918                                          in_ch=1,
1919                                          out_ch=1,
1920                                          x_in=5,
1921                                          y_in=8,
1922                                          w_x=2,
1923                                          w_y=4,
1924                                          stride_x=1,
1925                                          stride_y=1,
1926                                          pad=False)
1927    dataset = 'stride2pad1'
1928    testdata_sets[dataset] = ConvSettings(dataset,
1929                                          type_of_test,
1930                                          regenerate_weights,
1931                                          regenerate_input,
1932                                          regenerate_biases,
1933                                          schema_file,
1934                                          in_ch=1,
1935                                          out_ch=1,
1936                                          x_in=7,
1937                                          y_in=7,
1938                                          w_x=3,
1939                                          w_y=3,
1940                                          stride_x=2,
1941                                          stride_y=2,
1942                                          pad=True)
1943    dataset = 'kernel1x1'
1944    testdata_sets[dataset] = ConvSettings(dataset,
1945                                          type_of_test,
1946                                          regenerate_weights,
1947                                          regenerate_input,
1948                                          regenerate_biases,
1949                                          schema_file,
1950                                          in_ch=19,
1951                                          out_ch=7,
1952                                          x_in=7,
1953                                          y_in=5,
1954                                          w_x=1,
1955                                          w_y=1,
1956                                          stride_x=1,
1957                                          stride_y=1,
1958                                          pad=False,
1959                                          bias_min=INT8_MIN,
1960                                          bias_max=INT8_MAX,
1961                                          out_activation_min=-126,
1962                                          out_activation_max=127,
1963                                          batches=2)
1964    dataset = 'kernel1x1_stride_x'
1965    testdata_sets[dataset] = ConvSettings(dataset,
1966                                          type_of_test,
1967                                          regenerate_weights,
1968                                          regenerate_input,
1969                                          regenerate_biases,
1970                                          schema_file,
1971                                          in_ch=9,
1972                                          out_ch=5,
1973                                          x_in=7,
1974                                          y_in=4,
1975                                          w_x=1,
1976                                          w_y=1,
1977                                          stride_x=3,
1978                                          stride_y=1,
1979                                          pad=False,
1980                                          out_activation_min=-126,
1981                                          out_activation_max=127,
1982                                          batches=2)
1983    dataset = 'kernel1x1_stride_x_y'
1984    testdata_sets[dataset] = ConvSettings(dataset,
1985                                          type_of_test,
1986                                          regenerate_weights,
1987                                          regenerate_input,
1988                                          regenerate_biases,
1989                                          schema_file,
1990                                          in_ch=23,
1991                                          out_ch=15,
1992                                          randmin=0,
1993                                          x_in=7,
1994                                          y_in=6,
1995                                          w_x=1,
1996                                          w_y=1,
1997                                          stride_x=2,
1998                                          stride_y=2,
1999                                          pad=False,
2000                                          out_activation_min=-6,
2001                                          out_activation_max=127,
2002                                          batches=3)
2003    dataset = 'kernel1x1_stride_x_y_1'
2004    testdata_sets[dataset] = ConvSettings(dataset,
2005                                          type_of_test,
2006                                          regenerate_weights,
2007                                          regenerate_input,
2008                                          regenerate_biases,
2009                                          schema_file,
2010                                          in_ch=5,
2011                                          out_ch=5,
2012                                          x_in=4,
2013                                          y_in=4,
2014                                          w_x=1,
2015                                          w_y=1,
2016                                          stride_x=2,
2017                                          stride_y=2,
2018                                          pad=False,
2019                                          out_activation_min=-126,
2020                                          out_activation_max=127,
2021                                          batches=2)
2022    dataset = 'kernel1x1_stride_x_y_2'
2023    testdata_sets[dataset] = ConvSettings(dataset,
2024                                          type_of_test,
2025                                          regenerate_weights,
2026                                          regenerate_input,
2027                                          regenerate_biases,
2028                                          schema_file,
2029                                          in_ch=5,
2030                                          out_ch=5,
2031                                          x_in=4,
2032                                          y_in=4,
2033                                          w_x=1,
2034                                          w_y=1,
2035                                          stride_x=3,
2036                                          stride_y=3,
2037                                          pad=False,
2038                                          out_activation_min=-126,
2039                                          out_activation_max=127,
2040                                          batches=2)
2041    dataset = 'conv_3'
2042    testdata_sets[dataset] = ConvSettings(dataset,
2043                                          type_of_test,
2044                                          regenerate_weights,
2045                                          regenerate_input,
2046                                          regenerate_biases,
2047                                          schema_file,
2048                                          in_ch=3,
2049                                          out_ch=1,
2050                                          x_in=10,
2051                                          y_in=49,
2052                                          w_x=4,
2053                                          w_y=10,
2054                                          stride_x=1,
2055                                          stride_y=2,
2056                                          pad=True,
2057                                          out_activation_min=-127,
2058                                          out_activation_max=127)
2059    dataset = 'conv_1_x_n_1'  # left and right pad, no non-padded elements
2060    testdata_sets[dataset] = ConvSettings(dataset,
2061                                          type_of_test,
2062                                          regenerate_weights,
2063                                          regenerate_input,
2064                                          regenerate_biases,
2065                                          schema_file,
2066                                          in_ch=4,
2067                                          out_ch=3,
2068                                          x_in=2,
2069                                          y_in=1,
2070                                          w_x=3,
2071                                          w_y=1,
2072                                          stride_x=1,
2073                                          stride_y=1,
2074                                          pad=True,
2075                                          out_activation_min=-127,
2076                                          out_activation_max=127,
2077                                          batches=2)
2078    dataset = 'conv_1_x_n_2'  # no pad
2079    testdata_sets[dataset] = ConvSettings(dataset,
2080                                          type_of_test,
2081                                          regenerate_weights,
2082                                          regenerate_input,
2083                                          regenerate_biases,
2084                                          schema_file,
2085                                          in_ch=4,
2086                                          out_ch=3,
2087                                          x_in=296,
2088                                          y_in=1,
2089                                          w_x=48,
2090                                          w_y=1,
2091                                          stride_x=2,
2092                                          stride_y=1,
2093                                          pad=False,
2094                                          out_activation_min=-111,
2095                                          out_activation_max=127)
2096    dataset = 'conv_1_x_n_3'
2097    testdata_sets[dataset] = ConvSettings(dataset,
2098                                          type_of_test,
2099                                          regenerate_weights,
2100                                          regenerate_input,
2101                                          regenerate_biases,
2102                                          schema_file,
2103                                          in_ch=4,
2104                                          out_ch=1,
2105                                          x_in=296,
2106                                          y_in=1,
2107                                          w_x=48,
2108                                          w_y=1,
2109                                          stride_x=2,
2110                                          stride_y=1,
2111                                          pad=True,
2112                                          out_activation_min=-111,
2113                                          out_activation_max=127)
2114    dataset = 'conv_1_x_n_4'  # 0 left pad, 1 right pad
2115    testdata_sets[dataset] = ConvSettings(dataset,
2116                                          type_of_test,
2117                                          regenerate_weights,
2118                                          regenerate_input,
2119                                          regenerate_biases,
2120                                          schema_file,
2121                                          in_ch=4,
2122                                          out_ch=4,
2123                                          x_in=16,
2124                                          y_in=1,
2125                                          w_x=3,
2126                                          w_y=1,
2127                                          stride_x=2,
2128                                          stride_y=1,
2129                                          pad=True,
2130                                          out_activation_min=-88,
2131                                          out_activation_max=127)
2132    dataset = 'conv_1_x_n_5'
2133    testdata_sets[dataset] = ConvSettings(dataset,
2134                                          type_of_test,
2135                                          regenerate_weights,
2136                                          regenerate_input,
2137                                          regenerate_biases,
2138                                          schema_file,
2139                                          in_ch=4,
2140                                          out_ch=1,
2141                                          x_in=17,
2142                                          y_in=1,
2143                                          w_x=3,
2144                                          w_y=1,
2145                                          stride_x=3,
2146                                          stride_y=1,
2147                                          pad=True,
2148                                          out_activation_min=-88,
2149                                          out_activation_max=127)
2150    dataset = 'conv_2'
2151    testdata_sets[dataset] = ConvSettings(dataset,
2152                                          type_of_test,
2153                                          regenerate_weights,
2154                                          regenerate_input,
2155                                          regenerate_biases,
2156                                          schema_file,
2157                                          in_ch=2,
2158                                          out_ch=4,
2159                                          x_in=6,
2160                                          y_in=3,
2161                                          w_x=3,
2162                                          w_y=3,
2163                                          stride_x=1,
2164                                          stride_y=1,
2165                                          pad=True,
2166                                          out_activation_min=-101,
2167                                          out_activation_max=127)
2168    dataset = 'conv_4'  # batches > 2
2169    testdata_sets[dataset] = ConvSettings(dataset,
2170                                          type_of_test,
2171                                          regenerate_weights,
2172                                          regenerate_input,
2173                                          regenerate_biases,
2174                                          schema_file,
2175                                          in_ch=3,
2176                                          out_ch=3,
2177                                          x_in=5,
2178                                          y_in=5,
2179                                          w_x=2,
2180                                          w_y=3,
2181                                          stride_x=2,
2182                                          stride_y=2,
2183                                          pad=False,
2184                                          out_activation_min=-109,
2185                                          out_activation_max=127,
2186                                          batches=3)
2187    dataset = 'conv_5'
2188    testdata_sets[dataset] = ConvSettings(dataset,
2189                                          type_of_test,
2190                                          regenerate_weights,
2191                                          regenerate_input,
2192                                          regenerate_biases,
2193                                          schema_file,
2194                                          in_ch=128,
2195                                          out_ch=1,
2196                                          x_in=128,
2197                                          y_in=1,
2198                                          w_x=3,
2199                                          w_y=3,
2200                                          stride_x=4,
2201                                          stride_y=4,
2202                                          pad=True,
2203                                          out_activation_min=-88,
2204                                          out_activation_max=127)
2205    dataset = 'conv_out_activation'
2206    testdata_sets[dataset] = ConvSettings(dataset,
2207                                          type_of_test,
2208                                          regenerate_weights,
2209                                          regenerate_input,
2210                                          regenerate_biases,
2211                                          schema_file,
2212                                          in_ch=4,
2213                                          out_ch=2,
2214                                          x_in=3,
2215                                          y_in=3,
2216                                          w_x=3,
2217                                          w_y=3,
2218                                          stride_x=1,
2219                                          stride_y=1,
2220                                          pad=True,
2221                                          out_activation_min=-61,
2222                                          out_activation_max=107)
2223    dataset = 'conv_dilation_golden'
2224    testdata_sets[dataset] = ConvSettings(dataset,
2225                                          type_of_test,
2226                                          regenerate_weights,
2227                                          regenerate_input,
2228                                          regenerate_biases,
2229                                          schema_file,
2230                                          in_ch=1,
2231                                          batches=2,
2232                                          out_ch=3,
2233                                          x_in=6,
2234                                          y_in=4,
2235                                          w_x=2,
2236                                          w_y=2,
2237                                          stride_x=1,
2238                                          stride_y=1,
2239                                          pad=True,
2240                                          out_activation_min=-128,
2241                                          out_activation_max=127,
2242                                          dilation_x=3,
2243                                          dilation_y=2)
2244    dataset = 'conv_2x2_dilation'
2245    testdata_sets[dataset] = ConvSettings(dataset,
2246                                          type_of_test,
2247                                          regenerate_weights,
2248                                          regenerate_input,
2249                                          regenerate_biases,
2250                                          schema_file,
2251                                          in_ch=2,
2252                                          out_ch=2,
2253                                          x_in=10,
2254                                          y_in=10,
2255                                          w_x=3,
2256                                          w_y=3,
2257                                          stride_x=1,
2258                                          stride_y=1,
2259                                          pad=False,
2260                                          out_activation_min=-61,
2261                                          out_activation_max=107,
2262                                          dilation_x=2,
2263                                          dilation_y=2)
2264    dataset = 'conv_2x3_dilation'
2265    testdata_sets[dataset] = ConvSettings(dataset,
2266                                          type_of_test,
2267                                          regenerate_weights,
2268                                          regenerate_input,
2269                                          regenerate_biases,
2270                                          schema_file,
2271                                          in_ch=2,
2272                                          out_ch=2,
2273                                          x_in=3,
2274                                          y_in=3,
2275                                          w_x=3,
2276                                          w_y=3,
2277                                          stride_x=1,
2278                                          stride_y=1,
2279                                          pad=True,
2280                                          out_activation_min=-61,
2281                                          out_activation_max=107,
2282                                          dilation_x=2,
2283                                          dilation_y=2)
2284    dataset = 'conv_3x2_dilation'
2285    testdata_sets[dataset] = ConvSettings(dataset,
2286                                          type_of_test,
2287                                          regenerate_weights,
2288                                          regenerate_input,
2289                                          regenerate_biases,
2290                                          schema_file,
2291                                          in_ch=2,
2292                                          out_ch=2,
2293                                          x_in=3,
2294                                          y_in=3,
2295                                          w_x=3,
2296                                          w_y=3,
2297                                          stride_x=1,
2298                                          stride_y=1,
2299                                          pad=True,
2300                                          out_activation_min=-61,
2301                                          out_activation_max=107,
2302                                          dilation_x=3,
2303                                          dilation_y=2)
2304    dataset = 'conv_2x2_dilation_5x5_input'
2305    testdata_sets[dataset] = ConvSettings(dataset,
2306                                          type_of_test,
2307                                          regenerate_weights,
2308                                          regenerate_input,
2309                                          regenerate_biases,
2310                                          schema_file,
2311                                          in_ch=2,
2312                                          out_ch=2,
2313                                          x_in=5,
2314                                          y_in=5,
2315                                          w_x=3,
2316                                          w_y=3,
2317                                          stride_x=1,
2318                                          stride_y=1,
2319                                          pad=True,
2320                                          out_activation_min=-61,
2321                                          out_activation_max=107,
2322                                          dilation_x=2,
2323                                          dilation_y=2)
2324    dataset = 'conv_3x3_dilation_5x5_input'
2325    testdata_sets[dataset] = ConvSettings(dataset,
2326                                          type_of_test,
2327                                          regenerate_weights,
2328                                          regenerate_input,
2329                                          regenerate_biases,
2330                                          schema_file,
2331                                          in_ch=2,
2332                                          out_ch=2,
2333                                          x_in=9,
2334                                          y_in=11,
2335                                          w_x=3,
2336                                          w_y=3,
2337                                          stride_x=1,
2338                                          stride_y=1,
2339                                          pad=True,
2340                                          out_activation_min=-61,
2341                                          out_activation_max=107,
2342                                          dilation_x=2,
2343                                          dilation_y=2)
2344    dataset = 'int16xint8'
2345    testdata_sets[dataset] = ConvSettings(dataset,
2346                                          type_of_test,
2347                                          regenerate_weights,
2348                                          regenerate_input,
2349                                          regenerate_biases,
2350                                          schema_file,
2351                                          in_ch=3,
2352                                          out_ch=4,
2353                                          x_in=7,
2354                                          y_in=8,
2355                                          w_x=2,
2356                                          w_y=4,
2357                                          stride_x=2,
2358                                          stride_y=3,
2359                                          pad=True,
2360                                          randmin=INT16_MIN,
2361                                          randmax=INT16_MAX,
2362                                          out_activation_min=-13335,
2363                                          out_activation_max=32767,
2364                                          int16xint8=True)
2365    dataset = 'requantize_s64'
2366    testdata_sets[dataset] = ConvSettings(dataset,
2367                                          type_of_test,
2368                                          regenerate_weights,
2369                                          regenerate_input,
2370                                          regenerate_biases,
2371                                          schema_file,
2372                                          in_ch=2,
2373                                          out_ch=2,
2374                                          x_in=3,
2375                                          y_in=2,
2376                                          w_x=2,
2377                                          w_y=2,
2378                                          stride_x=1,
2379                                          stride_y=1,
2380                                          pad=False,
2381                                          out_activation_min=INT16_MIN,
2382                                          out_activation_max=INT16_MAX,
2383                                          int16xint8=True,
2384                                          bias_min=-0x300,
2385                                          bias_max=0x9fff)
2386    dataset = 'int16xint8_dilation_1'
2387    testdata_sets[dataset] = ConvSettings(dataset,
2388                                          type_of_test,
2389                                          regenerate_weights,
2390                                          regenerate_input,
2391                                          regenerate_biases,
2392                                          schema_file,
2393                                          in_ch=2,
2394                                          out_ch=2,
2395                                          x_in=32,
2396                                          y_in=32,
2397                                          w_x=2,
2398                                          w_y=2,
2399                                          stride_x=1,
2400                                          stride_y=1,
2401                                          pad=False,
2402                                          out_activation_min=INT16_MIN,
2403                                          out_activation_max=INT16_MAX,
2404                                          int16xint8=True,
2405                                          bias_min=-0x300,
2406                                          dilation_x=2,
2407                                          dilation_y=2)
2408    dataset = 'int16xint8_dilation_2'
2409    testdata_sets[dataset] = ConvSettings(dataset,
2410                                          type_of_test,
2411                                          regenerate_weights,
2412                                          regenerate_input,
2413                                          regenerate_biases,
2414                                          schema_file,
2415                                          in_ch=3,
2416                                          out_ch=4,
2417                                          x_in=7,
2418                                          y_in=8,
2419                                          w_x=2,
2420                                          w_y=4,
2421                                          stride_x=1,
2422                                          stride_y=1,
2423                                          pad=True,
2424                                          randmin=INT16_MIN,
2425                                          randmax=INT16_MAX,
2426                                          out_activation_min=-13335,
2427                                          out_activation_max=32767,
2428                                          int16xint8=True,
2429                                          dilation_x=2,
2430                                          dilation_y=2)
2431    dataset = 'int16xint8_dilation_3'
2432    testdata_sets[dataset] = ConvSettings(dataset,
2433                                          type_of_test,
2434                                          regenerate_weights,
2435                                          regenerate_input,
2436                                          regenerate_biases,
2437                                          schema_file,
2438                                          in_ch=3,
2439                                          out_ch=4,
2440                                          x_in=7,
2441                                          y_in=8,
2442                                          w_x=2,
2443                                          w_y=4,
2444                                          stride_x=1,
2445                                          stride_y=1,
2446                                          pad=True,
2447                                          randmin=INT16_MIN,
2448                                          randmax=INT16_MAX,
2449                                          out_activation_min=-13335,
2450                                          out_activation_max=32767,
2451                                          int16xint8=True,
2452                                          dilation_x=2)
2453
2454    type_of_test = 'depthwise_conv'
2455    dataset = 'depthwise_2'
2456    testdata_sets[dataset] = ConvSettings(dataset,
2457                                          type_of_test,
2458                                          regenerate_weights,
2459                                          regenerate_input,
2460                                          regenerate_biases,
2461                                          schema_file,
2462                                          in_ch=3,
2463                                          out_ch=9,
2464                                          x_in=6,
2465                                          y_in=5,
2466                                          w_x=3,
2467                                          w_y=4,
2468                                          stride_x=2,
2469                                          stride_y=2,
2470                                          pad=True,
2471                                          out_activation_min=-73,
2472                                          out_activation_max=127)
2473    dataset = 'depthwise_kernel_3x3'
2474    testdata_sets[dataset] = ConvSettings(dataset,
2475                                          type_of_test,
2476                                          regenerate_weights,
2477                                          regenerate_input,
2478                                          regenerate_biases,
2479                                          schema_file,
2480                                          in_ch=5,
2481                                          out_ch=5,
2482                                          x_in=4,
2483                                          y_in=5,
2484                                          w_x=3,
2485                                          w_y=3,
2486                                          stride_x=2,
2487                                          stride_y=2,
2488                                          pad=True,
2489                                          bias_min=INT8_MIN,
2490                                          bias_max=INT8_MAX,
2491                                          out_activation_min=-104,
2492                                          out_activation_max=127)
2493    dataset = 'depthwise_kernel_3x3_null_bias'
2494    testdata_sets[dataset] = ConvSettings(dataset,
2495                                          type_of_test,
2496                                          regenerate_weights,
2497                                          regenerate_input,
2498                                          regenerate_biases,
2499                                          schema_file,
2500                                          in_ch=5,
2501                                          out_ch=5,
2502                                          x_in=4,
2503                                          y_in=5,
2504                                          w_x=3,
2505                                          w_y=3,
2506                                          stride_x=2,
2507                                          stride_y=2,
2508                                          pad=True,
2509                                          generate_bias=False,
2510                                          out_activation_min=-104,
2511                                          out_activation_max=127)
2512    dataset = 'depthwise_eq_in_out_ch'
2513    testdata_sets[dataset] = ConvSettings(dataset,
2514                                          type_of_test,
2515                                          regenerate_weights,
2516                                          regenerate_input,
2517                                          regenerate_biases,
2518                                          schema_file,
2519                                          in_ch=250,
2520                                          out_ch=250,
2521                                          x_in=7,
2522                                          y_in=5,
2523                                          w_x=2,
2524                                          w_y=2,
2525                                          stride_x=1,
2526                                          stride_y=1,
2527                                          pad=True)
2528    dataset = 'depthwise_sub_block'
2529    testdata_sets[dataset] = ConvSettings(dataset,
2530                                          type_of_test,
2531                                          regenerate_weights,
2532                                          regenerate_input,
2533                                          regenerate_biases,
2534                                          schema_file,
2535                                          in_ch=9,
2536                                          out_ch=9,
2537                                          x_in=7,
2538                                          y_in=5,
2539                                          w_x=2,
2540                                          w_y=2,
2541                                          stride_x=1,
2542                                          stride_y=1,
2543                                          pad=False)
2544    dataset = 'depthwise_x_stride'
2545    testdata_sets[dataset] = ConvSettings(dataset,
2546                                          type_of_test,
2547                                          regenerate_weights,
2548                                          regenerate_input,
2549                                          regenerate_biases,
2550                                          schema_file,
2551                                          in_ch=9,
2552                                          out_ch=9,
2553                                          x_in=7,
2554                                          y_in=5,
2555                                          w_x=2,
2556                                          w_y=2,
2557                                          stride_x=2,
2558                                          stride_y=1,
2559                                          pad=False)
2560    dataset = 'depthwise_out_activation'
2561    testdata_sets[dataset] = ConvSettings(dataset,
2562                                          type_of_test,
2563                                          regenerate_weights,
2564                                          regenerate_input,
2565                                          regenerate_biases,
2566                                          schema_file,
2567                                          in_ch=3,
2568                                          out_ch=3,
2569                                          x_in=6,
2570                                          y_in=5,
2571                                          w_x=3,
2572                                          w_y=4,
2573                                          pad=False,
2574                                          out_activation_min=-45,
2575                                          out_activation_max=103)
2576    dataset = 'depthwise_mult_batches'
2577    testdata_sets[dataset] = ConvSettings(dataset,
2578                                          type_of_test,
2579                                          regenerate_weights,
2580                                          regenerate_input,
2581                                          regenerate_biases,
2582                                          schema_file,
2583                                          in_ch=3,
2584                                          out_ch=3,
2585                                          x_in=3,
2586                                          y_in=5,
2587                                          w_x=2,
2588                                          w_y=4,
2589                                          stride_x=2,
2590                                          stride_y=2,
2591                                          pad=True,
2592                                          batches=2)
2593    dataset = 'depthwise_null_bias_0'
2594    testdata_sets[dataset] = ConvSettings(dataset,
2595                                          type_of_test,
2596                                          regenerate_weights,
2597                                          regenerate_input,
2598                                          regenerate_biases,
2599                                          schema_file,
2600                                          in_ch=2,
2601                                          out_ch=2,
2602                                          x_in=4,
2603                                          y_in=5,
2604                                          w_x=2,
2605                                          w_y=2,
2606                                          stride_x=1,
2607                                          stride_y=1,
2608                                          pad=True,
2609                                          generate_bias=False,
2610                                          batches=1)
2611    dataset = 'depthwise_null_bias_1'
2612    testdata_sets[dataset] = ConvSettings(dataset,
2613                                          type_of_test,
2614                                          regenerate_weights,
2615                                          regenerate_input,
2616                                          regenerate_biases,
2617                                          schema_file,
2618                                          in_ch=2,
2619                                          out_ch=16,
2620                                          x_in=4,
2621                                          y_in=5,
2622                                          w_x=2,
2623                                          w_y=2,
2624                                          stride_x=1,
2625                                          stride_y=1,
2626                                          pad=True,
2627                                          generate_bias=False,
2628                                          batches=1)
2629    dataset = 'depthwise_dilation'
2630    testdata_sets[dataset] = ConvSettings(dataset,
2631                                          type_of_test,
2632                                          regenerate_weights,
2633                                          regenerate_input,
2634                                          regenerate_biases,
2635                                          schema_file,
2636                                          in_ch=3,
2637                                          out_ch=9,
2638                                          x_in=6,
2639                                          y_in=5,
2640                                          w_x=3,
2641                                          w_y=4,
2642                                          stride_x=2,
2643                                          stride_y=2,
2644                                          pad=True,
2645                                          out_activation_min=-70,
2646                                          out_activation_max=127,
2647                                          dilation_x=2,
2648                                          dilation_y=3)
2649    dataset = 'dw_int16xint8'
2650    testdata_sets[dataset] = ConvSettings(dataset,
2651                                          type_of_test,
2652                                          regenerate_weights,
2653                                          regenerate_input,
2654                                          regenerate_biases,
2655                                          schema_file,
2656                                          in_ch=4,
2657                                          out_ch=8,
2658                                          x_in=9,
2659                                          y_in=5,
2660                                          w_x=3,
2661                                          w_y=4,
2662                                          stride_x=3,
2663                                          stride_y=2,
2664                                          pad=True,
2665                                          randmin=INT16_MIN,
2666                                          randmax=INT16_MAX,
2667                                          out_activation_min=-21111,
2668                                          out_activation_max=32767,
2669                                          int16xint8=True)
2670    dataset = 'dw_int16xint8_dilation'
2671    testdata_sets[dataset] = ConvSettings(dataset,
2672                                          type_of_test,
2673                                          regenerate_weights,
2674                                          regenerate_input,
2675                                          regenerate_biases,
2676                                          schema_file,
2677                                          in_ch=4,
2678                                          out_ch=8,
2679                                          x_in=9,
2680                                          y_in=5,
2681                                          w_x=4,
2682                                          w_y=4,
2683                                          stride_x=1,
2684                                          stride_y=1,
2685                                          pad=True,
2686                                          randmin=INT16_MIN,
2687                                          randmax=INT16_MAX,
2688                                          out_activation_min=-32700,
2689                                          dilation_x=3,
2690                                          dilation_y=2,
2691                                          out_activation_max=32767,
2692                                          int16xint8=True)
2693    dataset = 'dw_int16xint8_mult4'
2694    testdata_sets[dataset] = ConvSettings(dataset,
2695                                          type_of_test,
2696                                          regenerate_weights,
2697                                          regenerate_input,
2698                                          regenerate_biases,
2699                                          schema_file,
2700                                          in_ch=2,
2701                                          out_ch=8,
2702                                          x_in=4,
2703                                          y_in=5,
2704                                          w_x=3,
2705                                          w_y=4,
2706                                          stride_x=3,
2707                                          stride_y=2,
2708                                          pad=False,
2709                                          randmin=INT16_MIN,
2710                                          randmax=INT16_MAX,
2711                                          out_activation_min=-32767,
2712                                          out_activation_max=32767,
2713                                          int16xint8=True)
2714    dataset = 'dw_int16xint8_fast'
2715    testdata_sets[dataset] = ConvSettings(dataset,
2716                                          type_of_test,
2717                                          regenerate_weights,
2718                                          regenerate_input,
2719                                          regenerate_biases,
2720                                          schema_file,
2721                                          in_ch=8,
2722                                          out_ch=8,
2723                                          x_in=4,
2724                                          y_in=4,
2725                                          w_x=2,
2726                                          w_y=2,
2727                                          stride_x=1,
2728                                          stride_y=1,
2729                                          pad=False,
2730                                          randmin=INT16_MIN,
2731                                          randmax=INT16_MAX,
2732                                          out_activation_min=-17000,
2733                                          out_activation_max=32767,
2734                                          int16xint8=True)
2735    dataset = 'dw_int16xint8_fast_multiple_batches_uneven_buffers'
2736    testdata_sets[dataset] = ConvSettings(dataset,
2737                                          type_of_test,
2738                                          regenerate_weights,
2739                                          regenerate_input,
2740                                          regenerate_biases,
2741                                          schema_file,
2742                                          in_ch=8,
2743                                          out_ch=8,
2744                                          x_in=5,
2745                                          y_in=5,
2746                                          w_x=3,
2747                                          w_y=3,
2748                                          stride_x=1,
2749                                          stride_y=1,
2750                                          pad=False,
2751                                          randmin=INT16_MIN,
2752                                          randmax=INT16_MAX,
2753                                          out_activation_min=-17000,
2754                                          out_activation_max=32767,
2755                                          int16xint8=True,
2756                                          batches=3)
2757    dataset = 'dw_int16xint8_fast_multiple_batches_uneven_buffers_null_bias'
2758    testdata_sets[dataset] = ConvSettings(dataset,
2759                                          type_of_test,
2760                                          regenerate_weights,
2761                                          regenerate_input,
2762                                          regenerate_biases,
2763                                          schema_file,
2764                                          in_ch=8,
2765                                          out_ch=8,
2766                                          x_in=4,
2767                                          y_in=4,
2768                                          w_x=3,
2769                                          w_y=2,
2770                                          stride_x=1,
2771                                          stride_y=1,
2772                                          pad=False,
2773                                          randmin=INT16_MIN,
2774                                          randmax=INT16_MAX,
2775                                          out_activation_min=-17000,
2776                                          out_activation_max=32767,
2777                                          int16xint8=True,
2778                                          batches=3,
2779                                          generate_bias=False)
2780
2781    dataset = 'dw_int16xint8_fast_test_bias'
2782    nbr_of_out_channels = 8
2783    bias = [i for i in range(nbr_of_out_channels)]
2784    testdata_sets[dataset] = ConvSettings(dataset,
2785                                          type_of_test,
2786                                          regenerate_weights,
2787                                          regenerate_input,
2788                                          regenerate_biases,
2789                                          schema_file,
2790                                          in_ch=8,
2791                                          out_ch=nbr_of_out_channels,
2792                                          x_in=4,
2793                                          y_in=4,
2794                                          w_x=2,
2795                                          w_y=2,
2796                                          stride_x=1,
2797                                          stride_y=1,
2798                                          pad=False,
2799                                          randmin=INT16_MIN,
2800                                          randmax=INT16_MAX,
2801                                          out_activation_min=-17000,
2802                                          out_activation_max=32767,
2803                                          int16xint8=True,
2804                                          generate_bias=bias)
2805
2806    dataset = 'dw_int16xint8_fast_null_bias'
2807    testdata_sets[dataset] = ConvSettings(dataset,
2808                                          type_of_test,
2809                                          regenerate_weights,
2810                                          regenerate_input,
2811                                          regenerate_biases,
2812                                          schema_file,
2813                                          in_ch=8,
2814                                          out_ch=8,
2815                                          x_in=4,
2816                                          y_in=4,
2817                                          w_x=2,
2818                                          w_y=2,
2819                                          stride_x=1,
2820                                          stride_y=1,
2821                                          pad=False,
2822                                          randmin=INT16_MIN,
2823                                          randmax=INT16_MAX,
2824                                          out_activation_min=-17000,
2825                                          out_activation_max=32767,
2826                                          int16xint8=True,
2827                                          generate_bias=False)
2828    dataset = 'dw_int16xint8_fast_stride'
2829    testdata_sets[dataset] = ConvSettings(dataset,
2830                                          type_of_test,
2831                                          regenerate_weights,
2832                                          regenerate_input,
2833                                          regenerate_biases,
2834                                          schema_file,
2835                                          in_ch=8,
2836                                          out_ch=8,
2837                                          x_in=4,
2838                                          y_in=4,
2839                                          w_x=2,
2840                                          w_y=2,
2841                                          stride_x=2,
2842                                          stride_y=2,
2843                                          pad=True,
2844                                          randmin=INT16_MIN,
2845                                          randmax=INT16_MAX,
2846                                          batches=2,
2847                                          out_activation_min=INT16_MIN,
2848                                          out_activation_max=16000,
2849                                          int16xint8=True)
2850    dataset = 'dw_int16xint8_fast_stride_null_bias'
2851    testdata_sets[dataset] = ConvSettings(dataset,
2852                                          type_of_test,
2853                                          regenerate_weights,
2854                                          regenerate_input,
2855                                          regenerate_biases,
2856                                          schema_file,
2857                                          in_ch=8,
2858                                          out_ch=8,
2859                                          x_in=4,
2860                                          y_in=4,
2861                                          w_x=2,
2862                                          w_y=2,
2863                                          stride_x=2,
2864                                          stride_y=2,
2865                                          pad=True,
2866                                          randmin=INT16_MIN,
2867                                          randmax=INT16_MAX,
2868                                          batches=2,
2869                                          out_activation_min=INT16_MIN,
2870                                          out_activation_max=16000,
2871                                          int16xint8=True,
2872                                          generate_bias=False)
2873    dataset = 'dw_int16xint8_fast_spill'
2874    testdata_sets[dataset] = ConvSettings(dataset,
2875                                          type_of_test,
2876                                          regenerate_weights,
2877                                          regenerate_input,
2878                                          regenerate_biases,
2879                                          schema_file,
2880                                          in_ch=5,
2881                                          out_ch=5,
2882                                          x_in=4,
2883                                          y_in=4,
2884                                          w_x=3,
2885                                          w_y=3,
2886                                          stride_x=2,
2887                                          stride_y=1,
2888                                          pad=True,
2889                                          randmin=INT16_MIN,
2890                                          randmax=INT16_MAX,
2891                                          batches=3,
2892                                          out_activation_min=-30000,
2893                                          out_activation_max=32767,
2894                                          int16xint8=True)
2895    dataset = 'dw_int16xint8_fast_spill_null_bias'
2896    testdata_sets[dataset] = ConvSettings(dataset,
2897                                          type_of_test,
2898                                          regenerate_weights,
2899                                          regenerate_input,
2900                                          regenerate_biases,
2901                                          schema_file,
2902                                          in_ch=5,
2903                                          out_ch=5,
2904                                          x_in=4,
2905                                          y_in=4,
2906                                          w_x=3,
2907                                          w_y=3,
2908                                          stride_x=2,
2909                                          stride_y=1,
2910                                          pad=True,
2911                                          randmin=INT16_MIN,
2912                                          randmax=INT16_MAX,
2913                                          batches=3,
2914                                          out_activation_min=-30000,
2915                                          out_activation_max=32767,
2916                                          int16xint8=True,
2917                                          generate_bias=False)
2918
2919    type_of_test = 'fully_connected'
2920    dataset = 'fully_connected'
2921    testdata_sets[dataset] = FullyConnectedSettings(dataset,
2922                                                    type_of_test,
2923                                                    regenerate_weights,
2924                                                    regenerate_input,
2925                                                    regenerate_biases,
2926                                                    schema_file,
2927                                                    in_ch=10,
2928                                                    out_ch=6,
2929                                                    x_in=2,
2930                                                    y_in=1,
2931                                                    batches=3)
2932    dataset = 'fully_connected_mve_0'
2933    testdata_sets[dataset] = FullyConnectedSettings(dataset,
2934                                                    type_of_test,
2935                                                    regenerate_weights,
2936                                                    regenerate_input,
2937                                                    regenerate_biases,
2938                                                    schema_file,
2939                                                    in_ch=16,
2940                                                    out_ch=9,
2941                                                    x_in=1,
2942                                                    y_in=1,
2943                                                    batches=1)
2944    dataset = 'fully_connected_mve_1'
2945    testdata_sets[dataset] = FullyConnectedSettings(dataset,
2946                                                    type_of_test,
2947                                                    regenerate_weights,
2948                                                    regenerate_input,
2949                                                    regenerate_biases,
2950                                                    schema_file,
2951                                                    in_ch=20,
2952                                                    out_ch=4,
2953                                                    x_in=1,
2954                                                    y_in=1,
2955                                                    batches=1)
2956    dataset = 'fully_connected_null_bias_0'
2957    testdata_sets[dataset] = FullyConnectedSettings(dataset,
2958                                                    type_of_test,
2959                                                    regenerate_weights,
2960                                                    regenerate_input,
2961                                                    regenerate_biases,
2962                                                    schema_file,
2963                                                    in_ch=33,
2964                                                    out_ch=5,
2965                                                    batches=2,
2966                                                    generate_bias=False)
2967    dataset = 'fully_connected_out_activation'
2968    testdata_sets[dataset] = FullyConnectedSettings(dataset,
2969                                                    type_of_test,
2970                                                    regenerate_weights,
2971                                                    regenerate_input,
2972                                                    regenerate_biases,
2973                                                    schema_file,
2974                                                    in_ch=10,
2975                                                    out_ch=4,
2976                                                    out_activation_min=-70,
2977                                                    out_activation_max=100)
2978    dataset = 'fully_connected_int16'
2979    testdata_sets[dataset] = FullyConnectedSettings(dataset,
2980                                                    type_of_test,
2981                                                    regenerate_weights,
2982                                                    regenerate_input,
2983                                                    regenerate_biases,
2984                                                    schema_file,
2985                                                    in_ch=7,
2986                                                    out_ch=11,
2987                                                    x_in=3,
2988                                                    y_in=3,
2989                                                    batches=2,
2990                                                    randmin=INT16_MIN,
2991                                                    randmax=INT16_MAX,
2992                                                    out_activation_min=-9999,
2993                                                    out_activation_max=32767,
2994                                                    int16xint8=True)
2995    dataset = 'fully_connected_int16_big'
2996    testdata_sets[dataset] = FullyConnectedSettings(dataset,
2997                                                    type_of_test,
2998                                                    regenerate_weights,
2999                                                    regenerate_input,
3000                                                    regenerate_biases,
3001                                                    schema_file,
3002                                                    in_ch=7,
3003                                                    out_ch=11,
3004                                                    x_in=10,
3005                                                    y_in=10,
3006                                                    batches=3,
3007                                                    out_activation_min=-1444,
3008                                                    out_activation_max=32767,
3009                                                    int16xint8=True)
3010    dataset = 'fc_int16_slow'
3011    testdata_sets[dataset] = FullyConnectedSettings(dataset,
3012                                                    type_of_test,
3013                                                    regenerate_weights,
3014                                                    regenerate_input,
3015                                                    regenerate_biases,
3016                                                    schema_file,
3017                                                    in_ch=7,
3018                                                    out_ch=11,
3019                                                    x_in=10,
3020                                                    y_in=8,
3021                                                    batches=3,
3022                                                    randmin=(INT16_MAX - 100),
3023                                                    randmax=INT16_MAX,
3024                                                    int16xint8=True)
3025
3026    type_of_test = 'avgpool'
3027    dataset = 'avgpooling'
3028    testdata_sets[dataset] = PoolingSettings(dataset,
3029                                             type_of_test,
3030                                             regenerate_weights,
3031                                             regenerate_input,
3032                                             regenerate_biases,
3033                                             schema_file,
3034                                             channels=20,
3035                                             x_in=22,
3036                                             y_in=12,
3037                                             stride_x=9,
3038                                             stride_y=5,
3039                                             w_x=6,
3040                                             w_y=5,
3041                                             pad=True)
3042    dataset = 'avgpooling_1'
3043    testdata_sets[dataset] = PoolingSettings(dataset,
3044                                             type_of_test,
3045                                             regenerate_weights,
3046                                             regenerate_input,
3047                                             regenerate_biases,
3048                                             schema_file,
3049                                             channels=3,
3050                                             x_in=9,
3051                                             y_in=5,
3052                                             stride_x=1,
3053                                             stride_y=2,
3054                                             w_x=9,
3055                                             w_y=5,
3056                                             pad=False)
3057    dataset = 'avgpooling_2'
3058    testdata_sets[dataset] = PoolingSettings(dataset,
3059                                             type_of_test,
3060                                             regenerate_weights,
3061                                             regenerate_input,
3062                                             regenerate_biases,
3063                                             schema_file,
3064                                             channels=5,
3065                                             x_in=12,
3066                                             y_in=1,
3067                                             stride_x=1,
3068                                             stride_y=2,
3069                                             w_x=3,
3070                                             w_y=1,
3071                                             pad=True)
3072    dataset = 'avgpooling_3'
3073    testdata_sets[dataset] = PoolingSettings(dataset,
3074                                             type_of_test,
3075                                             regenerate_weights,
3076                                             regenerate_input,
3077                                             regenerate_biases,
3078                                             schema_file,
3079                                             channels=2,
3080                                             x_in=9,
3081                                             y_in=1,
3082                                             stride_x=2,
3083                                             stride_y=1,
3084                                             w_x=1,
3085                                             w_y=1,
3086                                             pad=False)
3087    dataset = 'avgpooling_4'
3088    testdata_sets[dataset] = PoolingSettings(dataset,
3089                                             type_of_test,
3090                                             regenerate_weights,
3091                                             regenerate_input,
3092                                             regenerate_biases,
3093                                             schema_file,
3094                                             channels=2,
3095                                             x_in=1,
3096                                             y_in=20,
3097                                             stride_x=1,
3098                                             stride_y=3,
3099                                             w_x=1,
3100                                             w_y=3,
3101                                             pad=True)
3102    dataset = 'avgpooling_5'
3103    testdata_sets[dataset] = PoolingSettings(dataset,
3104                                             type_of_test,
3105                                             regenerate_weights,
3106                                             regenerate_input,
3107                                             regenerate_biases,
3108                                             schema_file,
3109                                             channels=1,
3110                                             x_in=3,
3111                                             y_in=3,
3112                                             stride_x=1,
3113                                             stride_y=1,
3114                                             w_x=1,
3115                                             w_y=3,
3116                                             pad=True,
3117                                             relu6=True)
3118    dataset = 'avgpooling_int16'
3119    testdata_sets[dataset] = PoolingSettings(dataset,
3120                                             type_of_test,
3121                                             regenerate_weights,
3122                                             regenerate_input,
3123                                             regenerate_biases,
3124                                             schema_file,
3125                                             channels=17,
3126                                             x_in=6,
3127                                             y_in=4,
3128                                             stride_x=2,
3129                                             stride_y=1,
3130                                             w_x=2,
3131                                             w_y=3,
3132                                             pad=True,
3133                                             randmin=INT16_MIN,
3134                                             randmax=INT16_MAX,
3135                                             int16xint8=True)
3136    dataset = 'avgpooling_int16_1'
3137    testdata_sets[dataset] = PoolingSettings(dataset,
3138                                             type_of_test,
3139                                             regenerate_weights,
3140                                             regenerate_input,
3141                                             regenerate_biases,
3142                                             schema_file,
3143                                             channels=2,
3144                                             x_in=9,
3145                                             y_in=1,
3146                                             stride_x=2,
3147                                             stride_y=1,
3148                                             w_x=1,
3149                                             w_y=1,
3150                                             pad=False,
3151                                             randmin=INT16_MIN,
3152                                             randmax=INT16_MAX,
3153                                             int16xint8=True)
3154    dataset = 'avgpooling_int16_2'
3155    testdata_sets[dataset] = PoolingSettings(dataset,
3156                                             type_of_test,
3157                                             regenerate_weights,
3158                                             regenerate_input,
3159                                             regenerate_biases,
3160                                             schema_file,
3161                                             channels=20,
3162                                             x_in=9,
3163                                             y_in=1,
3164                                             stride_x=2,
3165                                             stride_y=1,
3166                                             w_x=1,
3167                                             w_y=1,
3168                                             pad=False,
3169                                             randmin=INT16_MIN,
3170                                             randmax=INT16_MAX,
3171                                             int16xint8=True)
3172    dataset = 'avgpooling_int16_3'
3173    testdata_sets[dataset] = PoolingSettings(dataset,
3174                                             type_of_test,
3175                                             regenerate_weights,
3176                                             regenerate_input,
3177                                             regenerate_biases,
3178                                             schema_file,
3179                                             channels=21,
3180                                             x_in=1,
3181                                             y_in=20,
3182                                             stride_x=1,
3183                                             stride_y=3,
3184                                             w_x=1,
3185                                             w_y=3,
3186                                             pad=True,
3187                                             randmin=INT16_MIN,
3188                                             randmax=INT16_MAX,
3189                                             int16xint8=True)
3190
3191    type_of_test = 'maxpool'
3192    dataset = 'maxpooling'
3193    testdata_sets[dataset] = PoolingSettings(dataset,
3194                                             type_of_test,
3195                                             regenerate_weights,
3196                                             regenerate_input,
3197                                             regenerate_biases,
3198                                             schema_file,
3199                                             channels=8,
3200                                             x_in=22,
3201                                             y_in=12,
3202                                             stride_x=9,
3203                                             stride_y=5,
3204                                             w_x=6,
3205                                             w_y=5,
3206                                             pad=True)
3207    dataset = 'maxpooling_1'
3208    testdata_sets[dataset] = PoolingSettings(dataset,
3209                                             type_of_test,
3210                                             regenerate_weights,
3211                                             regenerate_input,
3212                                             regenerate_biases,
3213                                             schema_file,
3214                                             channels=3,
3215                                             x_in=9,
3216                                             y_in=5,
3217                                             stride_x=1,
3218                                             stride_y=2,
3219                                             w_x=9,
3220                                             w_y=5,
3221                                             pad=False)
3222    dataset = 'maxpooling_2'
3223    testdata_sets[dataset] = PoolingSettings(dataset,
3224                                             type_of_test,
3225                                             regenerate_weights,
3226                                             regenerate_input,
3227                                             regenerate_biases,
3228                                             schema_file,
3229                                             channels=5,
3230                                             x_in=12,
3231                                             y_in=1,
3232                                             stride_x=1,
3233                                             stride_y=2,
3234                                             w_x=3,
3235                                             w_y=1,
3236                                             pad=True)
3237    dataset = 'maxpooling_3'
3238    testdata_sets[dataset] = PoolingSettings(dataset,
3239                                             type_of_test,
3240                                             regenerate_weights,
3241                                             regenerate_input,
3242                                             regenerate_biases,
3243                                             schema_file,
3244                                             channels=2,
3245                                             x_in=9,
3246                                             y_in=1,
3247                                             stride_x=2,
3248                                             stride_y=1,
3249                                             w_x=1,
3250                                             w_y=1,
3251                                             pad=False)
3252    dataset = 'maxpooling_4'
3253    testdata_sets[dataset] = PoolingSettings(dataset,
3254                                             type_of_test,
3255                                             regenerate_weights,
3256                                             regenerate_input,
3257                                             regenerate_biases,
3258                                             schema_file,
3259                                             channels=2,
3260                                             x_in=1,
3261                                             y_in=20,
3262                                             stride_x=1,
3263                                             stride_y=3,
3264                                             w_x=1,
3265                                             w_y=3,
3266                                             pad=True)
3267    dataset = 'maxpooling_5'
3268    testdata_sets[dataset] = PoolingSettings(dataset,
3269                                             type_of_test,
3270                                             regenerate_weights,
3271                                             regenerate_input,
3272                                             regenerate_biases,
3273                                             schema_file,
3274                                             channels=20,
3275                                             x_in=1,
3276                                             y_in=1,
3277                                             stride_x=1,
3278                                             stride_y=1,
3279                                             w_x=1,
3280                                             w_y=1,
3281                                             pad=True)
3282    dataset = 'maxpooling_6'
3283    testdata_sets[dataset] = PoolingSettings(dataset,
3284                                             type_of_test,
3285                                             regenerate_weights,
3286                                             regenerate_input,
3287                                             regenerate_biases,
3288                                             schema_file,
3289                                             channels=17,
3290                                             x_in=1,
3291                                             y_in=5,
3292                                             stride_x=1,
3293                                             stride_y=3,
3294                                             w_x=3,
3295                                             w_y=4,
3296                                             pad=True)
3297    dataset = 'maxpooling_7'
3298    testdata_sets[dataset] = PoolingSettings(dataset,
3299                                             type_of_test,
3300                                             regenerate_weights,
3301                                             regenerate_input,
3302                                             regenerate_biases,
3303                                             schema_file,
3304                                             channels=1,
3305                                             x_in=4,
3306                                             y_in=2,
3307                                             stride_x=2,
3308                                             stride_y=2,
3309                                             w_x=2,
3310                                             w_y=2,
3311                                             pad=False,
3312                                             relu6=True)
3313    dataset = 'maxpool_int16'
3314    testdata_sets[dataset] = PoolingSettings(dataset,
3315                                             type_of_test,
3316                                             regenerate_weights,
3317                                             regenerate_input,
3318                                             regenerate_biases,
3319                                             schema_file,
3320                                             channels=2,
3321                                             x_in=4,
3322                                             y_in=3,
3323                                             stride_x=2,
3324                                             stride_y=2,
3325                                             w_x=2,
3326                                             w_y=2,
3327                                             pad=False,
3328                                             randmin=INT16_MIN,
3329                                             randmax=INT16_MAX,
3330                                             int16xint8=True)
3331    dataset = 'maxpool_int16_1'
3332    testdata_sets[dataset] = PoolingSettings(dataset,
3333                                             type_of_test,
3334                                             regenerate_weights,
3335                                             regenerate_input,
3336                                             regenerate_biases,
3337                                             schema_file,
3338                                             channels=2,
3339                                             x_in=4,
3340                                             y_in=5,
3341                                             stride_x=2,
3342                                             stride_y=1,
3343                                             w_x=3,
3344                                             w_y=3,
3345                                             pad=True,
3346                                             randmin=INT16_MIN,
3347                                             randmax=INT16_MAX,
3348                                             out_activation_min=-30000,
3349                                             out_activation_max=30000,
3350                                             int16xint8=True)
3351    dataset = 'maxpool_int16_2'
3352    testdata_sets[dataset] = PoolingSettings(dataset,
3353                                             type_of_test,
3354                                             regenerate_weights,
3355                                             regenerate_input,
3356                                             regenerate_biases,
3357                                             schema_file,
3358                                             channels=3,
3359                                             x_in=7,
3360                                             y_in=7,
3361                                             stride_x=1,
3362                                             stride_y=1,
3363                                             w_x=3,
3364                                             w_y=3,
3365                                             pad=False,
3366                                             randmin=INT16_MIN,
3367                                             randmax=INT16_MAX,
3368                                             out_activation_min=-30000,
3369                                             out_activation_max=30000,
3370                                             int16xint8=True)
3371
3372    type_of_test = 'softmax'
3373    dataset = 'softmax'
3374    testdata_sets[dataset] = SoftmaxSettings(dataset,
3375                                             type_of_test,
3376                                             regenerate_weights,
3377                                             regenerate_input,
3378                                             regenerate_biases,
3379                                             schema_file,
3380                                             x_in=5,
3381                                             y_in=2)
3382    dataset = 'softmax_s16'
3383    testdata_sets[dataset] = SoftmaxSettings(dataset,
3384                                             type_of_test,
3385                                             regenerate_weights,
3386                                             regenerate_input,
3387                                             regenerate_biases,
3388                                             schema_file,
3389                                             x_in=10,
3390                                             y_in=3,
3391                                             int16xint8=True,
3392                                             randmin=INT16_MIN,
3393                                             randmax=INT16_MAX)
3394    dataset = 'softmax_s8_s16'
3395    testdata_sets[dataset] = SoftmaxSettings(dataset,
3396                                             type_of_test,
3397                                             regenerate_weights,
3398                                             regenerate_input,
3399                                             regenerate_biases,
3400                                             schema_file,
3401                                             x_in=12,
3402                                             y_in=2,
3403                                             inInt8outInt16=True)
3404
3405    type_of_test = 'svdf'
3406    dataset = 'svdf'
3407    testdata_sets[dataset] = SVDFSettings(dataset,
3408                                          type_of_test,
3409                                          regenerate_weights,
3410                                          regenerate_input,
3411                                          regenerate_biases,
3412                                          schema_file,
3413                                          batches=2,
3414                                          number_inputs=2,
3415                                          rank=8,
3416                                          memory_size=8,
3417                                          input_size=3,
3418                                          number_units=3)
3419    dataset = 'svdf_1'
3420    testdata_sets[dataset] = SVDFSettings(dataset,
3421                                          type_of_test,
3422                                          regenerate_weights,
3423                                          regenerate_input,
3424                                          regenerate_biases,
3425                                          schema_file,
3426                                          batches=3,
3427                                          number_inputs=2,
3428                                          rank=1,
3429                                          memory_size=2,
3430                                          input_size=7,
3431                                          number_units=5)
3432    dataset = 'svdf_2'
3433    testdata_sets[dataset] = SVDFSettings(dataset,
3434                                          type_of_test,
3435                                          regenerate_weights,
3436                                          regenerate_input,
3437                                          regenerate_biases,
3438                                          schema_file,
3439                                          batches=3,
3440                                          number_inputs=2,
3441                                          rank=2,
3442                                          memory_size=2,
3443                                          input_size=7,
3444                                          number_units=5,
3445                                          generate_bias=False)
3446    dataset = 'svdf_3'
3447    testdata_sets[dataset] = SVDFSettings(dataset,
3448                                          type_of_test,
3449                                          regenerate_weights,
3450                                          regenerate_input,
3451                                          regenerate_biases,
3452                                          schema_file,
3453                                          batches=1,
3454                                          number_inputs=2,
3455                                          rank=1,
3456                                          memory_size=2,
3457                                          input_size=20,
3458                                          number_units=12,
3459                                          generate_bias=False)
3460    dataset = 'svdf_int8'
3461    testdata_sets[dataset] = SVDFSettings(dataset,
3462                                          type_of_test,
3463                                          regenerate_weights,
3464                                          regenerate_input,
3465                                          regenerate_biases,
3466                                          schema_file,
3467                                          batches=1,
3468                                          number_inputs=2,
3469                                          rank=1,
3470                                          memory_size=2,
3471                                          input_size=20,
3472                                          number_units=12,
3473                                          generate_bias=False,
3474                                          int8_time_weights=True)
3475
3476    type_of_test = 'add'
3477    dataset = 'add'
3478    testdata_sets[dataset] = AddMulSettings(dataset,
3479                                            type_of_test,
3480                                            regenerate_weights,
3481                                            regenerate_input,
3482                                            regenerate_biases,
3483                                            schema_file,
3484                                            channels=8,
3485                                            x_in=4,
3486                                            y_in=4,
3487                                            randmin=INT8_MIN,
3488                                            randmax=INT8_MAX)
3489    dataset = 'add_s16'
3490    testdata_sets[dataset] = AddMulSettings(dataset,
3491                                            type_of_test,
3492                                            regenerate_weights,
3493                                            regenerate_input,
3494                                            regenerate_biases,
3495                                            schema_file,
3496                                            channels=8,
3497                                            x_in=4,
3498                                            y_in=4,
3499                                            randmin=INT16_MIN,
3500                                            randmax=INT16_MAX,
3501                                            out_activation_min=INT16_MIN,
3502                                            out_activation_max=INT16_MAX,
3503                                            int16xint8=True)
3504    dataset = 'add_s16_spill'
3505    testdata_sets[dataset] = AddMulSettings(dataset,
3506                                            type_of_test,
3507                                            regenerate_weights,
3508                                            regenerate_input,
3509                                            regenerate_biases,
3510                                            schema_file,
3511                                            channels=7,
3512                                            x_in=5,
3513                                            y_in=3,
3514                                            randmin=INT16_MIN,
3515                                            randmax=INT16_MAX,
3516                                            out_activation_min=-2000,
3517                                            out_activation_max=INT16_MAX,
3518                                            int16xint8=True)
3519
3520    type_of_test = 'mul'
3521    dataset = 'mul'
3522    testdata_sets[dataset] = AddMulSettings(dataset,
3523                                            type_of_test,
3524                                            regenerate_weights,
3525                                            regenerate_input,
3526                                            regenerate_biases,
3527                                            schema_file,
3528                                            channels=8,
3529                                            x_in=4,
3530                                            y_in=5,
3531                                            randmin=INT8_MIN,
3532                                            randmax=INT8_MAX)
3533    dataset = 'mul_s16'
3534    testdata_sets[dataset] = AddMulSettings(dataset,
3535                                            type_of_test,
3536                                            regenerate_weights,
3537                                            regenerate_input,
3538                                            regenerate_biases,
3539                                            schema_file,
3540                                            channels=8,
3541                                            x_in=5,
3542                                            y_in=4,
3543                                            randmin=INT16_MIN,
3544                                            randmax=INT16_MAX,
3545                                            out_activation_min=INT16_MIN,
3546                                            out_activation_max=INT16_MAX,
3547                                            int16xint8=True)
3548    dataset = 'mul_s16_spill'
3549    testdata_sets[dataset] = AddMulSettings(dataset,
3550                                            type_of_test,
3551                                            regenerate_weights,
3552                                            regenerate_input,
3553                                            regenerate_biases,
3554                                            schema_file,
3555                                            channels=7,
3556                                            x_in=5,
3557                                            y_in=7,
3558                                            randmin=INT16_MIN,
3559                                            randmax=INT16_MAX,
3560                                            out_activation_min=INT16_MIN,
3561                                            out_activation_max=1000,
3562                                            int16xint8=True)
3563
3564    type_of_test = 'lstm'
3565    dataset = 'lstm_1'
3566    testdata_sets[dataset] = LSTMSettings(dataset,
3567                                          type_of_test,
3568                                          regenerate_weights,
3569                                          regenerate_input,
3570                                          regenerate_biases,
3571                                          schema_file,
3572                                          batches=1,
3573                                          time_steps=10,
3574                                          number_inputs=22,
3575                                          number_units=11,
3576                                          time_major=True)
3577    dataset = 'lstm_2'
3578    testdata_sets[dataset] = LSTMSettings(dataset,
3579                                          type_of_test,
3580                                          regenerate_weights,
3581                                          regenerate_input,
3582                                          regenerate_biases,
3583                                          schema_file,
3584                                          batches=2,
3585                                          time_steps=9,
3586                                          number_inputs=6,
3587                                          number_units=7,
3588                                          time_major=False)
3589    dataset = 'lstm_one_time_step'
3590    testdata_sets[dataset] = LSTMSettings(dataset,
3591                                          type_of_test,
3592                                          regenerate_weights,
3593                                          regenerate_input,
3594                                          regenerate_biases,
3595                                          schema_file,
3596                                          batches=3,
3597                                          time_steps=1,
3598                                          number_inputs=22,
3599                                          number_units=3,
3600                                          time_major=False)
3601
3602    return testdata_sets
3603
3604
3605if __name__ == '__main__':
3606    if version.parse(tf.__version__) < REQUIRED_MINIMUM_TENSORFLOW_VERSION:
3607        print("Unsupported tensorflow version, ", version.parse(tf.__version__))
3608        sys.exit(0)
3609
3610    args = parse_args()
3611
3612    testdataset = args.dataset
3613    test_type = args.testtype
3614    schema_file = args.schema_file
3615
3616    testdata_sets = load_testdata_sets()
3617
3618    if args.run_all_testsets:
3619        for testset_name, testset_generator in testdata_sets.items():
3620            if test_type and testset_generator.test_type != test_type:
3621                continue
3622            print("Generating testset {}..".format(testset_name))
3623            testset_generator.generate_data()
3624            print()
3625
3626        # Check that all testsets have been loaded.
3627        found_test_data_sets = []
3628        directory = 'TestCases/TestData'
3629        for dir in next(os.walk(directory))[1]:
3630            found_test_data_sets.append(dir)
3631        for testset_name in found_test_data_sets:
3632            if testset_name not in testdata_sets:
3633                print("WARNING: Testset {} in {} was not loaded".format(testset_name, directory))
3634    elif testdataset:
3635        try:
3636            generator = testdata_sets[testdataset]
3637        except KeyError:
3638            print("WARNING: testset {} not in testset list".format(testdataset))
3639            if test_type == 'conv' or test_type == 'depthwise_conv':
3640                generator = ConvSettings(testdataset, test_type, True, True, True, schema_file)
3641            elif test_type == 'fully_connected':
3642                generator = FullyConnectedSettings(testdataset, test_type, True, True, True, schema_file)
3643            elif test_type == 'avgpool' or test_type == 'maxpool':
3644                generator = PoolingSettings(testdataset, test_type, True, True, True, schema_file)
3645            elif test_type == 'softmax':
3646                generator = SoftmaxSettings(testdataset, test_type, True, True, True, schema_file)
3647            elif test_type == 'svdf':
3648                generator = SVDFSettings(testdataset, test_type, True, True, True, schema_file)
3649            elif test_type == 'add' or test_type == 'mul':
3650                generator = AddMulSettings(testdataset, test_type, True, True, True, schema_file)
3651            elif test_type == 'lstm':
3652                generator = LSTMSettings(testdataset, test_type, True, True, True, schema_file)
3653            else:
3654                raise RuntimeError("Please specify type of test with -t")
3655        generator.generate_data()
3656    else:
3657        raise RuntimeError("Please select testdataset or use --run-all-testsets")
3658