blob: 4f8c3374b14ab30216ffa891d9debe91cdf8afcb [file] [log] [blame]
XNNPACK Teamb455b122019-09-27 18:10:33 -07001#!/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 bisect
9import codecs
10import math
11import os
12import sys
13import yaml
14
15sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
16from primes import next_prime
17import xngen
Marat Dukhan918a4a62019-10-27 19:49:49 -070018import xnncommon
XNNPACK Teamb455b122019-09-27 18:10:33 -070019
20
21parser = argparse.ArgumentParser(description='XNNPACK generator')
22parser.add_argument("-s", "--spec", metavar="FILE", required=True,
23 help="Spec (YAML) file")
24parser.add_argument("-o", "--output", metavar="FILE", required=True,
25 help='Output (C++ source) file')
26parser.set_defaults(defines=list())
27
28
XNNPACK Teamb455b122019-09-27 18:10:33 -070029def split_ukernel_name(name):
30 common_name, target_name = name.split("__", 1)
31 common_parts = common_name.split("_")
32 param_spec = common_parts[-1]
33 assert param_spec.startswith("up")
34 cr, kr = map(int, param_spec[2:].split("x"))
Marat Dukhan918a4a62019-10-27 19:49:49 -070035 arch, isa = xnncommon.parse_target_name(target_name)
XNNPACK Teamb455b122019-09-27 18:10:33 -070036 return cr, kr, arch, isa
37
38
39DWCONV_TEST_CODE = """\
40TEST(${TEST_NAME}, c_eq_${CBLOCK}) {
41 $if ISA_CHECK:
42 ${ISA_CHECK};
43 DWConvMicrokernelTester()
44 .cr(${CR})
45 .kr(${KR})
46 .channels(${CBLOCK})
47 .Test(${", ".join(TEST_ARGS)});
48}
49
50$if IS_PIPELINED:
51 TEST(${TEST_NAME}, c_eq_${CBLOCK * 2}) {
52 $if ISA_CHECK:
53 ${ISA_CHECK};
54 DWConvMicrokernelTester()
55 .cr(${CR})
56 .kr(${KR})
57 .channels(${CBLOCK * 2})
58 .Test(${", ".join(TEST_ARGS)});
59 }
60
61$if CBLOCK > 1:
62 TEST(${TEST_NAME}, c_div_${CBLOCK}) {
63 $if ISA_CHECK:
64 ${ISA_CHECK};
65 for (uint32_t channels = ${ADJCBLOCK + CBLOCK}; channels < ${CR * 16}; channels += ${CR * 3}) {
66 DWConvMicrokernelTester()
67 .cr(${CR})
68 .kr(${KR})
69 .channels(channels)
70 .Test(${", ".join(TEST_ARGS)});
71 }
72 }
73
Marat Dukhan163a7e62020-04-09 04:19:26 -070074 $if ACTIVATION == "MINMAX":
75 TEST(${TEST_NAME}, c_div_${CBLOCK}_with_qmin) {
76 $if ISA_CHECK:
77 ${ISA_CHECK};
78 for (uint32_t channels = ${ADJCBLOCK + CBLOCK}; channels < ${CR * 16}; channels += ${CR * 3}) {
79 DWConvMicrokernelTester()
80 .cr(${CR})
81 .kr(${KR})
82 .channels(channels)
83 .qmin(128)
84 .Test(${", ".join(TEST_ARGS)});
85 }
XNNPACK Teamb455b122019-09-27 18:10:33 -070086 }
XNNPACK Teamb455b122019-09-27 18:10:33 -070087
Marat Dukhan163a7e62020-04-09 04:19:26 -070088 TEST(${TEST_NAME}, c_div_${CBLOCK}_with_qmax) {
89 $if ISA_CHECK:
90 ${ISA_CHECK};
91 for (uint32_t channels = ${ADJCBLOCK + CBLOCK}; channels < ${CR * 16}; channels += ${CR * 3}) {
92 DWConvMicrokernelTester()
93 .cr(${CR})
94 .kr(${KR})
95 .channels(channels)
96 .qmax(128)
97 .Test(${", ".join(TEST_ARGS)});
98 }
XNNPACK Teamb455b122019-09-27 18:10:33 -070099 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700100
101 TEST(${TEST_NAME}, c_lt_${ADJCBLOCK}) {
102 $if ISA_CHECK:
103 ${ISA_CHECK};
104 for (uint32_t channels = 1; channels < ${ADJCBLOCK}; channels++) {
105 DWConvMicrokernelTester()
106 .cr(${CR})
107 .kr(${KR})
108 .channels(channels)
109 .Test(${", ".join(TEST_ARGS)});
110 }
111 }
112
113TEST(${TEST_NAME}, c_gt_${ADJCBLOCK}) {
114 $if ISA_CHECK:
115 ${ISA_CHECK};
116 for (uint32_t channels = ${ADJCBLOCK + 1}; channels < ${10 if CBLOCK == 1 else ADJCBLOCK + CBLOCK}; channels++) {
117 DWConvMicrokernelTester()
118 .cr(${CR})
119 .kr(${KR})
120 .channels(channels)
121 .Test(${", ".join(TEST_ARGS)});
122 }
123}
124
Marat Dukhan163a7e62020-04-09 04:19:26 -0700125$if ACTIVATION == "MINMAX":
126 TEST(${TEST_NAME}, c_gt_${ADJCBLOCK}_with_qmin) {
127 $if ISA_CHECK:
128 ${ISA_CHECK};
129 for (uint32_t channels = ${ADJCBLOCK + 1}; channels < ${10 if CBLOCK == 1 else ADJCBLOCK + CBLOCK}; channels++) {
130 DWConvMicrokernelTester()
131 .cr(${CR})
132 .kr(${KR})
133 .channels(channels)
134 .qmin(128)
135 .Test(${", ".join(TEST_ARGS)});
136 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700137 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700138
Marat Dukhan163a7e62020-04-09 04:19:26 -0700139 TEST(${TEST_NAME}, c_gt_${ADJCBLOCK}_with_qmax) {
140 $if ISA_CHECK:
141 ${ISA_CHECK};
142 for (uint32_t channels = ${ADJCBLOCK + 1}; channels < ${10 if CBLOCK == 1 else ADJCBLOCK + CBLOCK}; channels++) {
143 DWConvMicrokernelTester()
144 .cr(${CR})
145 .kr(${KR})
146 .channels(channels)
147 .qmax(128)
148 .Test(${", ".join(TEST_ARGS)});
149 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700150 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700151
152TEST(${TEST_NAME}, multipixel) {
153 $if ISA_CHECK:
154 ${ISA_CHECK};
155 for (size_t channels = 1; channels <= ${CBLOCK * 5}; channels += ${max(1, CBLOCK - 1)}) {
156 DWConvMicrokernelTester()
157 .cr(${CR})
158 .kr(${KR})
159 .channels(channels)
160 .width(3)
161 .Test(${", ".join(TEST_ARGS)});
162 }
163}
164
165TEST(${TEST_NAME}, multipixel_with_step) {
166 $if ISA_CHECK:
167 ${ISA_CHECK};
168 for (size_t channels = 1; channels <= ${CBLOCK * 5}; channels += ${max(1, CBLOCK - 1)}) {
169 for (size_t step = 2; step <= ${KR}; step++) {
170 DWConvMicrokernelTester()
171 .cr(${CR})
172 .kr(${KR})
173 .channels(channels)
174 .width(3)
175 .step(step)
176 .Test(${", ".join(TEST_ARGS)});
177 }
178 }
179}
180
181TEST(${TEST_NAME}, multipixel_with_output_stride) {
182 $if ISA_CHECK:
183 ${ISA_CHECK};
184 for (size_t channels = 1; channels <= ${CBLOCK * 5}; channels += ${max(1, CBLOCK - 1)}) {
185 DWConvMicrokernelTester()
186 .cr(${CR})
187 .kr(${KR})
188 .channels(${CR})
189 .width(5)
190 .output_stride(${next_prime(CR * 5 + 1)})
191 .Test(${", ".join(TEST_ARGS)});
192 }
193}
194
Marat Dukhan163a7e62020-04-09 04:19:26 -0700195$if ACTIVATION == "MINMAX":
196 TEST(${TEST_NAME}, multipixel_with_qmin) {
197 $if ISA_CHECK:
198 ${ISA_CHECK};
199 for (size_t channels = 1; channels <= ${CBLOCK * 5}; channels += ${max(1, CBLOCK - 1)}) {
200 DWConvMicrokernelTester()
201 .cr(${CR})
202 .kr(${KR})
203 .channels(channels)
204 .width(3)
205 .qmin(128)
206 .Test(${", ".join(TEST_ARGS)});
207 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700208 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700209
Marat Dukhan163a7e62020-04-09 04:19:26 -0700210 TEST(${TEST_NAME}, multipixel_with_qmax) {
211 $if ISA_CHECK:
212 ${ISA_CHECK};
213 for (size_t channels = 1; channels <= ${CBLOCK * 5}; channels += ${max(1, CBLOCK - 1)}) {
214 DWConvMicrokernelTester()
215 .cr(${CR})
216 .kr(${KR})
217 .channels(channels)
218 .width(3)
219 .qmax(128)
220 .Test(${", ".join(TEST_ARGS)});
221 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700222 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700223
Marat Dukhan08b7a972020-07-14 18:17:29 -0700224$if DATATYPE == "qu8":
XNNPACK Teamb455b122019-09-27 18:10:33 -0700225 TEST(${TEST_NAME}, input_zero_point_only) {
226 $if ISA_CHECK:
227 ${ISA_CHECK};
228 for (size_t channels = 1; channels <= ${CBLOCK * 5}; channels += ${max(1, CBLOCK - 1)}) {
229 DWConvMicrokernelTester()
230 .cr(${CR})
231 .kr(${KR})
232 .channels(channels)
233 .width(3)
234 .input_zero_point(255)
235 .kernel_zero_point(0)
236 .Test(${", ".join(TEST_ARGS)});
237 }
238 }
239
240 TEST(${TEST_NAME}, kernel_zero_point_only) {
241 $if ISA_CHECK:
242 ${ISA_CHECK};
243 for (size_t channels = 1; channels <= ${CBLOCK * 5}; channels += ${max(1, CBLOCK - 1)}) {
244 DWConvMicrokernelTester()
245 .cr(${CR})
246 .kr(${KR})
247 .channels(channels)
248 .width(3)
249 .input_zero_point(0)
250 .kernel_zero_point(255)
251 .Test(${", ".join(TEST_ARGS)});
252 }
253 }
XNNPACK Teamb455b122019-09-27 18:10:33 -0700254
Frank Barchardd5360722020-05-17 16:10:36 -0700255TEST(${TEST_NAME}, input_offset) {
256 $if ISA_CHECK:
257 ${ISA_CHECK};
258 for (uint32_t channels = ${ADJCBLOCK + CBLOCK}; channels < ${CR * 16}; channels += ${CR * 3}) {
259 DWConvMicrokernelTester()
260 .cr(${CR})
261 .kr(${KR})
262 .channels(channels)
263 .input_offset(${next_prime(CR + 1) * 16})
264 .Test(${", ".join(TEST_ARGS)});
265 }
266}
267
268TEST(${TEST_NAME}, zero) {
269 $if ISA_CHECK:
270 ${ISA_CHECK};
271 for (uint32_t mz = 0; mz < ${KR}; mz++) {
272 for (uint32_t channels = ${ADJCBLOCK + CBLOCK}; channels < ${CR * 16}; channels += ${CR * 3}) {
273 DWConvMicrokernelTester()
274 .cr(${CR})
275 .kr(${KR})
276 .channels(channels)
277 .input_offset(${next_prime(CR + 1) * 16})
278 .zero_index(mz)
279 .Test(${", ".join(TEST_ARGS)});
280 }
281 }
282}
283"""
XNNPACK Teamb455b122019-09-27 18:10:33 -0700284
285def generate_test_cases(ukernel, cr, kr, c_block, is_pipelined, isa):
286 """Generates all tests cases for a DWCONV micro-kernel.
287
288 Args:
289 ukernel: C name of the micro-kernel function.
290 cr: CR parameter of the DWCONV micro-kernel.
291 kr: KR parameter of the DWCONV micro-kernel.
292 k_block: Number of C values processed per one iteration of the main loop of
293 the micro-kernel.
294 is_pipelined: Indicates if the micro-kernel is implemented with software
295 pipelining. Additional test cases are generated for software
296 pipelined micro-kernels to separately test prologue + epiloque
297 of the pipelined loop and iteration of the pipelined loop.
298 isa: instruction set required to run the micro-kernel. Generated unit test
299 will skip execution if the host processor doesn't support this ISA.
300
301 Returns:
302 Code for the test case.
303 """
304 _, test_name = ukernel.split("_", 1)
Marat Dukhan163a7e62020-04-09 04:19:26 -0700305 _, datatype, ukernel_type, activation, _ = ukernel.split("_", 4)
306 if activation == "ukernel":
307 activation = "linear"
XNNPACK Teamb455b122019-09-27 18:10:33 -0700308 test_args = [ukernel]
Marat Dukhan163a7e62020-04-09 04:19:26 -0700309 if activation != "linear" and (not isa or isa == "psimd"):
XNNPACK Teamb455b122019-09-27 18:10:33 -0700310 test_args.append("DWConvMicrokernelTester::Variant::Scalar")
311 return xngen.preprocess(DWCONV_TEST_CODE, {
312 "TEST_NAME": test_name.upper().replace("UKERNEL_", ""),
313 "TEST_ARGS": test_args,
314 "UKERNEL_TYPE": ukernel_type.upper(),
315 "DATATYPE": datatype,
Marat Dukhan163a7e62020-04-09 04:19:26 -0700316 "ACTIVATION": activation.upper(),
XNNPACK Teamb455b122019-09-27 18:10:33 -0700317 "CR": cr,
318 "KR": kr,
319 "CBLOCK": c_block,
320 "ADJCBLOCK": 2 * c_block if is_pipelined else c_block,
321 "IS_PIPELINED": is_pipelined,
Marat Dukhan918a4a62019-10-27 19:49:49 -0700322 "ISA_CHECK": xnncommon.generate_isa_check_macro(isa),
XNNPACK Teamb455b122019-09-27 18:10:33 -0700323 "next_prime": next_prime,
324 "sqrt": math.sqrt,
325 })
326
327
328def main(args):
329 options = parser.parse_args(args)
330
331 with codecs.open(options.spec, "r", encoding="utf-8") as spec_file:
332 spec_yaml = yaml.safe_load(spec_file)
333 if not isinstance(spec_yaml, list):
334 raise ValueError("expected a list of micro-kernels in the spec")
335
336 tests = """\
337// Copyright (c) Facebook, Inc. and its affiliates.
338// All rights reserved.
339//
340// Copyright 2019 Google LLC
341//
342// This source code is licensed under the BSD-style license found in the
343// LICENSE file in the root directory of this source tree.
344//
345// Auto-generated file. Do not edit!
346// Specification: {specification}
347// Generator: {generator}
348
349
Marat Dukhan629a33e2019-10-01 10:39:14 -0700350#include <gtest/gtest.h>
XNNPACK Teamb455b122019-09-27 18:10:33 -0700351
Marat Dukhan1dadbf72019-10-01 10:46:20 -0700352#include <xnnpack/common.h>
XNNPACK Teamb455b122019-09-27 18:10:33 -0700353#include <xnnpack/isa-checks.h>
354
Marat Dukhan1dadbf72019-10-01 10:46:20 -0700355#include <xnnpack/dwconv.h>
XNNPACK Teamb455b122019-09-27 18:10:33 -0700356#include "dwconv-microkernel-tester.h"
357""".format(specification=options.spec, generator=sys.argv[0])
358
359 for ukernel_spec in spec_yaml:
360 name = ukernel_spec["name"]
361 pipelined = bool(ukernel_spec.get("pipelined", False))
Frank Barchard7e955972019-10-11 10:34:25 -0700362 assembly = bool(ukernel_spec.get("assembly", False))
XNNPACK Teamb455b122019-09-27 18:10:33 -0700363 cr, kr, arch, isa = split_ukernel_name(name)
364
365 # specification can override architecture
366 arch = ukernel_spec.get("arch", arch)
367
368 test_case = generate_test_cases(name, cr, kr, cr, pipelined, isa)
Marat Dukhan918a4a62019-10-27 19:49:49 -0700369 tests += "\n\n" + xnncommon.postprocess_test_case(test_case, arch, isa, assembly)
XNNPACK Teamb455b122019-09-27 18:10:33 -0700370
371 with codecs.open(options.output, "w", encoding="utf-8") as output_file:
372 output_file.write(tests)
373
374
375if __name__ == "__main__":
376 main(sys.argv[1:])