blob: 2041805d201650cd21aab09e3a1bb771d54f0f68 [file] [log] [blame]
Marat Dukhanc07cb7f2019-11-14 15:32:05 -08001#!/usr/bin/env python
2# Copyright 2019 Google LLC
3#
4# This source code is licensed under the BSD-style license found in the
5# LICENSE file in the root directory of this source tree.
6
7import argparse
8import codecs
9import math
10import os
11import re
12import sys
13import yaml
14
15sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
16import xngen
17import xnncommon
18
19
20parser = argparse.ArgumentParser(
21 description='Vector binary operation microkernel test generator')
Marat Dukhand9f3ad42020-08-10 12:30:58 -070022parser.add_argument("-t", "--tester", metavar="TESTER", required=True,
Marat Dukhan0270d9f2020-08-11 00:56:46 -070023 choices=["VAddMicrokernelTester", "VAddCMicrokernelTester",
Marat Dukhand9f3ad42020-08-10 12:30:58 -070024 "VBinOpMicrokernelTester", "VBinOpCMicrokernelTester"],
25 help="Tester class to be used in the generated test")
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080026parser.add_argument("-s", "--spec", metavar="FILE", required=True,
27 help="Specification (YAML) file")
28parser.add_argument("-o", "--output", metavar="FILE", required=True,
29 help='Output (C++ source) file')
30parser.set_defaults(defines=list())
31
32
33def split_ukernel_name(name):
Marat Dukhand9f3ad42020-08-10 12:30:58 -070034 match = re.match(r"^xnn_(qs8|f16|f32)_v(add|div|max|min|mul|sqrdiff|sub|addc|divc|rdivc|maxc|minc|mulc|sqrdiffc|subc|rsubc)(_(minmax|relu))?_ukernel__(.+)_x(\d+)$", name)
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080035 if match is None:
36 raise ValueError("Unexpected microkernel name: " + name)
37 op_type = {
38 "add": "Add",
Marat Dukhan77ca6302019-12-06 12:48:15 -080039 "div": "Div",
Marat Dukhan403b7d42019-12-05 12:49:11 -080040 "max": "Max",
41 "min": "Min",
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080042 "mul": "Mul",
Marat Dukhan13bafb02020-06-05 00:43:11 -070043 "sqrdiff": "SqrDiff",
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080044 "sub": "Sub",
45 "addc": "AddC",
Marat Dukhan77ca6302019-12-06 12:48:15 -080046 "divc": "DivC",
47 "rdivc": "RDivC",
Marat Dukhan403b7d42019-12-05 12:49:11 -080048 "maxc": "MaxC",
49 "minc": "MinC",
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080050 "mulc": "MulC",
Marat Dukhan13bafb02020-06-05 00:43:11 -070051 "sqrdiffc": "SqrDiffC",
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080052 "subc": "SubC",
53 "rsubc": "RSubC",
54 }[match.group(2)]
Marat Dukhan91cd2b72020-04-09 23:57:31 -070055 batch_tile = int(match.group(6))
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080056
Marat Dukhan13bafb02020-06-05 00:43:11 -070057 activation_type = match.group(4)
58 if activation_type is None:
59 activation_type = "LINEAR"
60 else:
61 activation_type = activation_type.upper()
62
Marat Dukhan91cd2b72020-04-09 23:57:31 -070063 arch, isa = xnncommon.parse_target_name(target_name=match.group(5))
Marat Dukhan13bafb02020-06-05 00:43:11 -070064 return op_type, activation_type, batch_tile, arch, isa
Marat Dukhanc07cb7f2019-11-14 15:32:05 -080065
66
67BINOP_TEST_TEMPLATE = """\
68TEST(${TEST_NAME}, batch_eq_${BATCH_TILE}) {
69 $if ISA_CHECK:
70 ${ISA_CHECK};
71 ${TESTER}()
72 .batch_size(${BATCH_TILE})
73 .Test(${", ".join(TEST_ARGS)});
74}
75
76$if BATCH_TILE > 1:
77 TEST(${TEST_NAME}, batch_div_${BATCH_TILE}) {
78 $if ISA_CHECK:
79 ${ISA_CHECK};
80 for (size_t batch_size = ${BATCH_TILE*2}; batch_size < ${BATCH_TILE*10}; batch_size += ${BATCH_TILE}) {
81 ${TESTER}()
82 .batch_size(batch_size)
83 .Test(${", ".join(TEST_ARGS)});
84 }
85 }
86
87 TEST(${TEST_NAME}, batch_lt_${BATCH_TILE}) {
88 $if ISA_CHECK:
89 ${ISA_CHECK};
90 for (size_t batch_size = 1; batch_size < ${BATCH_TILE}; batch_size++) {
91 ${TESTER}()
92 .batch_size(batch_size)
93 .Test(${", ".join(TEST_ARGS)});
94 }
95 }
96
97TEST(${TEST_NAME}, batch_gt_${BATCH_TILE}) {
98 $if ISA_CHECK:
99 ${ISA_CHECK};
100 for (size_t batch_size = ${BATCH_TILE+1}; batch_size < ${10 if BATCH_TILE == 1 else BATCH_TILE*2}; batch_size++) {
101 ${TESTER}()
102 .batch_size(batch_size)
103 .Test(${", ".join(TEST_ARGS)});
104 }
105}
106
Marat Dukhan0270d9f2020-08-11 00:56:46 -0700107$if TESTER in ["VAddCMicrokernelTester", "VBinOpCMicrokernelTester"]:
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800108 TEST(${TEST_NAME}, inplace) {
109 $if ISA_CHECK:
110 ${ISA_CHECK};
111 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
112 ${TESTER}()
113 .batch_size(batch_size)
114 .inplace(true)
115 .Test(${", ".join(TEST_ARGS)});
116 }
117 }
118$else:
119 TEST(${TEST_NAME}, inplace_a) {
120 $if ISA_CHECK:
121 ${ISA_CHECK};
122 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
123 ${TESTER}()
124 .batch_size(batch_size)
125 .inplace_a(true)
126 .Test(${", ".join(TEST_ARGS)});
127 }
128 }
129
130 TEST(${TEST_NAME}, inplace_b) {
131 $if ISA_CHECK:
132 ${ISA_CHECK};
133 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
134 ${TESTER}()
135 .batch_size(batch_size)
136 .inplace_b(true)
137 .Test(${", ".join(TEST_ARGS)});
138 }
139 }
140
141 TEST(${TEST_NAME}, inplace_a_and_b) {
142 $if ISA_CHECK:
143 ${ISA_CHECK};
144 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
145 ${TESTER}()
146 .batch_size(batch_size)
147 .inplace_a(true)
148 .inplace_b(true)
149 .Test(${", ".join(TEST_ARGS)});
150 }
151 }
152
Marat Dukhan95caee52020-09-02 03:41:32 -0700153$if DATATYPE == "QS8":
154 TEST(${TEST_NAME}, a_zero_point) {
155 $if ISA_CHECK:
156 ${ISA_CHECK};
157 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
158 for (int32_t a_zero_point = -128; a_zero_point <= 127; a_zero_point += 51) {
159 ${TESTER}()
160 .batch_size(batch_size)
161 .a_zero_point(a_zero_point)
162 .Test(${", ".join(TEST_ARGS)});
163 }
164 }
165 }
166
167 TEST(${TEST_NAME}, b_zero_point) {
168 $if ISA_CHECK:
169 ${ISA_CHECK};
170 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
171 for (int32_t b_zero_point = -128; b_zero_point <= 127; b_zero_point += 51) {
172 ${TESTER}()
173 .batch_size(batch_size)
174 .b_zero_point(b_zero_point)
175 .Test(${", ".join(TEST_ARGS)});
176 }
177 }
178 }
179
180 TEST(${TEST_NAME}, y_zero_point) {
181 $if ISA_CHECK:
182 ${ISA_CHECK};
183 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
184 for (int32_t y_zero_point = -128; y_zero_point <= 127; y_zero_point += 51) {
185 ${TESTER}()
186 .batch_size(batch_size)
187 .y_zero_point(y_zero_point)
188 .Test(${", ".join(TEST_ARGS)});
189 }
190 }
191 }
192
193 TEST(${TEST_NAME}, a_scale) {
194 $if ISA_CHECK:
195 ${ISA_CHECK};
196 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
197 for (float a_scale = 0.1f; a_scale <= 10.0f; a_scale *= 3.14f) {
198 ${TESTER}()
199 .batch_size(batch_size)
200 .a_scale(a_scale)
201 .Test(${", ".join(TEST_ARGS)});
202 }
203 }
204 }
205
206 TEST(${TEST_NAME}, b_scale) {
207 $if ISA_CHECK:
208 ${ISA_CHECK};
209 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
210 for (float b_scale = 0.1f; b_scale <= 10.0f; b_scale *= 3.14f) {
211 ${TESTER}()
212 .batch_size(batch_size)
213 .b_scale(b_scale)
214 .Test(${", ".join(TEST_ARGS)});
215 }
216 }
217 }
218
219 TEST(${TEST_NAME}, y_scale) {
220 $if ISA_CHECK:
221 ${ISA_CHECK};
222 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
223 for (float y_scale = 0.1f; y_scale <= 10.0f; y_scale *= 3.14f) {
224 ${TESTER}()
225 .batch_size(batch_size)
226 .y_scale(y_scale)
227 .Test(${", ".join(TEST_ARGS)});
228 }
229 }
230 }
231
Marat Dukhan13bafb02020-06-05 00:43:11 -0700232$if ACTIVATION_TYPE == "MINMAX":
233 TEST(${TEST_NAME}, qmin) {
234 $if ISA_CHECK:
235 ${ISA_CHECK};
236 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
237 ${TESTER}()
238 .batch_size(batch_size)
239 .qmin(128)
240 .Test(${", ".join(TEST_ARGS)});
241 }
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800242 }
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800243
Marat Dukhan13bafb02020-06-05 00:43:11 -0700244 TEST(${TEST_NAME}, qmax) {
245 $if ISA_CHECK:
246 ${ISA_CHECK};
247 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
248 ${TESTER}()
249 .batch_size(batch_size)
250 .qmax(128)
251 .Test(${", ".join(TEST_ARGS)});
252 }
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800253 }
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800254"""
255
256
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700257def generate_test_cases(ukernel, op_type, activation_type, tester, batch_tile, isa):
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800258 """Generates all tests cases for a Vector Binary Operation micro-kernel.
259
260 Args:
261 ukernel: C name of the micro-kernel function.
262 op_type: Operation type (ADD/MUL/SUB/etc).
Marat Dukhan13bafb02020-06-05 00:43:11 -0700263 activation_type: Activation type (LINEAR/MINMAX/RELU).
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700264 tester: C++ name of the tester class.
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800265 batch_tile: Number of batch elements processed per one iteration of the
266 inner loop of the micro-kernel.
267 isa: instruction set required to run the micro-kernel. Generated unit test
268 will skip execution if the host processor doesn't support this ISA.
269
270 Returns:
271 Code for the test case.
272 """
273 _, test_name = ukernel.split("_", 1)
274 _, datatype, _ = ukernel.split("_", 2)
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700275 test_args = [ukernel]
276 if tester in ["VBinOpMicrokernelTester", "VBinOpCMicrokernelTester"]:
277 test_args.append("%s::OpType::%s" % (tester, op_type))
Marat Dukhan3de5dfa2020-12-10 11:19:47 -0800278 if not isa:
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800279 test_args.append("%s::Variant::Scalar" % tester)
280 return xngen.preprocess(BINOP_TEST_TEMPLATE, {
281 "TEST_NAME": test_name.upper().replace("UKERNEL_", ""),
282 "TEST_ARGS": test_args,
283 "TESTER": tester,
Marat Dukhan95caee52020-09-02 03:41:32 -0700284 "DATATYPE": datatype.upper(),
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800285 "BATCH_TILE": batch_tile,
286 "OP_TYPE": op_type,
Marat Dukhan13bafb02020-06-05 00:43:11 -0700287 "ACTIVATION_TYPE": activation_type,
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800288 "ISA_CHECK": xnncommon.generate_isa_check_macro(isa),
289 })
290
291
292def main(args):
293 options = parser.parse_args(args)
294
295 with codecs.open(options.spec, "r", encoding="utf-8") as spec_file:
296 spec_yaml = yaml.safe_load(spec_file)
297 if not isinstance(spec_yaml, list):
298 raise ValueError("expected a list of micro-kernels in the spec")
299
Marat Dukhan91cd2b72020-04-09 23:57:31 -0700300 spec_name = os.path.splitext(os.path.split(options.spec)[1])[0]
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700301 microkernel_header = {
302 "VAddMicrokernelTester": "xnnpack/vadd.h",
Marat Dukhan0270d9f2020-08-11 00:56:46 -0700303 "VAddCMicrokernelTester": "xnnpack/vadd.h",
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700304 "VBinOpMicrokernelTester": "xnnpack/vbinary.h",
305 "VBinOpCMicrokernelTester": "xnnpack/vbinary.h",
306 }[options.tester]
307 tester_header = {
308 "VAddMicrokernelTester": "vadd-microkernel-tester.h",
Marat Dukhan0270d9f2020-08-11 00:56:46 -0700309 "VAddCMicrokernelTester": "vaddc-microkernel-tester.h",
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700310 "VBinOpMicrokernelTester": "vbinary-microkernel-tester.h",
311 "VBinOpCMicrokernelTester": "vbinaryc-microkernel-tester.h",
312 }[options.tester]
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800313 tests = """\
314// Copyright 2019 Google LLC
315//
316// This source code is licensed under the BSD-style license found in the
317// LICENSE file in the root directory of this source tree.
318//
319// Auto-generated file. Do not edit!
320// Specification: {specification}
321// Generator: {generator}
322
323
324#include <gtest/gtest.h>
325
326#include <xnnpack/common.h>
327#include <xnnpack/isa-checks.h>
328
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700329#include <{microkernel_header}>
330#include "{tester_header}"
331""".format(specification=options.spec, generator=sys.argv[0],
332 microkernel_header=microkernel_header, tester_header=tester_header)
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800333
334 for ukernel_spec in spec_yaml:
335 name = ukernel_spec["name"]
Marat Dukhan13bafb02020-06-05 00:43:11 -0700336 op_type, activation_type, batch_tile, arch, isa = split_ukernel_name(name)
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800337
338 # specification can override architecture
339 arch = ukernel_spec.get("arch", arch)
340
Marat Dukhan13bafb02020-06-05 00:43:11 -0700341 test_case = generate_test_cases(name, op_type, activation_type,
Marat Dukhand9f3ad42020-08-10 12:30:58 -0700342 options.tester, batch_tile, isa)
Marat Dukhanc07cb7f2019-11-14 15:32:05 -0800343 tests += "\n\n" + xnncommon.postprocess_test_case(test_case, arch, isa)
344
345 with codecs.open(options.output, "w", encoding="utf-8") as output_file:
346 output_file.write(tests)
347
348
349if __name__ == "__main__":
350 main(sys.argv[1:])