blob: 23d689831e900db063341ba8578e3d6b99aa0e5a [file] [log] [blame]
Marat Dukhan346a9e52019-11-15 09:06:30 -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 unary operation microkernel test generator')
22parser.add_argument("-s", "--spec", metavar="FILE", required=True,
23 help="Specification (YAML) file")
24parser.add_argument("-o", "--output", metavar="FILE", required=True,
25 help='Output (C++ source) file')
26parser.set_defaults(defines=list())
27
28
29def split_ukernel_name(name):
Marat Dukhaned6baaf2020-12-01 15:07:08 -080030 match = re.match(r"^xnn_(f16|f32)_(relu|sigmoid|vabs|velu|vlrelu|vneg|vsqr|vrndne|vrndz|vrndd|vrndu|vsqrt)_(fact_)?ukernel__(.+)_x(\d+)$", name)
Marat Dukhan346a9e52019-11-15 09:06:30 -080031 if match is None:
32 raise ValueError("Unexpected microkernel name: " + name)
33 op_type = {
Frank Barchardfb158e22020-07-15 16:10:10 -070034 "relu": "ReLU",
Marat Dukhan2b9efd82020-06-08 01:09:31 -070035 "vabs": "Abs",
Marat Dukhaned6baaf2020-12-01 15:07:08 -080036 "velu": "ELU",
Marat Dukhan8cc7efe2020-06-10 16:24:27 -070037 "vlrelu": "LeakyReLU",
Marat Dukhaneecf8fd2020-06-09 08:59:37 -070038 "vneg": "Negate",
Marat Dukhan346a9e52019-11-15 09:06:30 -080039 "sigmoid": "Sigmoid",
Marat Dukhaneecf8fd2020-06-09 08:59:37 -070040 "vrndne": "RoundToNearestEven",
41 "vrndz": "RoundTowardsZero",
42 "vrndu": "RoundUp",
43 "vrndd": "RoundDown",
44 "vsqr": "Square",
Marat Dukhanf4db2f32020-06-30 10:55:30 -070045 "vsqrt": "SquareRoot",
Marat Dukhan346a9e52019-11-15 09:06:30 -080046 }[match.group(2)]
Erich Elsen8fd7b5f2019-11-18 10:50:41 -080047 batch_tile = int(match.group(5))
Marat Dukhan346a9e52019-11-15 09:06:30 -080048
Erich Elsen8fd7b5f2019-11-18 10:50:41 -080049 arch, isa = xnncommon.parse_target_name(target_name=match.group(4))
Marat Dukhan346a9e52019-11-15 09:06:30 -080050 return op_type, batch_tile, arch, isa
51
52
53BINOP_TEST_TEMPLATE = """\
54TEST(${TEST_NAME}, batch_eq_${BATCH_TILE}) {
55 $if ISA_CHECK:
56 ${ISA_CHECK};
57 VUnOpMicrokernelTester()
58 .batch_size(${BATCH_TILE})
59 .Test(${", ".join(TEST_ARGS)});
60}
61
62$if BATCH_TILE > 1:
63 TEST(${TEST_NAME}, batch_div_${BATCH_TILE}) {
64 $if ISA_CHECK:
65 ${ISA_CHECK};
66 for (size_t batch_size = ${BATCH_TILE*2}; batch_size < ${BATCH_TILE*10}; batch_size += ${BATCH_TILE}) {
67 VUnOpMicrokernelTester()
68 .batch_size(batch_size)
69 .Test(${", ".join(TEST_ARGS)});
70 }
71 }
72
73 TEST(${TEST_NAME}, batch_lt_${BATCH_TILE}) {
74 $if ISA_CHECK:
75 ${ISA_CHECK};
76 for (size_t batch_size = 1; batch_size < ${BATCH_TILE}; batch_size++) {
77 VUnOpMicrokernelTester()
78 .batch_size(batch_size)
79 .Test(${", ".join(TEST_ARGS)});
80 }
81 }
82
83TEST(${TEST_NAME}, batch_gt_${BATCH_TILE}) {
84 $if ISA_CHECK:
85 ${ISA_CHECK};
86 for (size_t batch_size = ${BATCH_TILE+1}; batch_size < ${10 if BATCH_TILE == 1 else BATCH_TILE*2}; batch_size++) {
87 VUnOpMicrokernelTester()
88 .batch_size(batch_size)
89 .Test(${", ".join(TEST_ARGS)});
90 }
91}
92
93TEST(${TEST_NAME}, inplace) {
94 $if ISA_CHECK:
95 ${ISA_CHECK};
96 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
97 VUnOpMicrokernelTester()
98 .batch_size(batch_size)
99 .inplace(true)
100 .Test(${", ".join(TEST_ARGS)});
101 }
102}
Marat Dukhan8cc7efe2020-06-10 16:24:27 -0700103
104$if OP_TYPE == "LeakyReLU":
105 TEST(${TEST_NAME}, slope) {
106 $if ISA_CHECK:
107 ${ISA_CHECK};
108 for (float slope : std::vector<float>({-0.7f, 0.3f, 1.3f})) {
109 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
110 VUnOpMicrokernelTester()
111 .batch_size(batch_size)
112 .slope(slope)
113 .Test(${", ".join(TEST_ARGS)});
114 }
115 }
116 }
Marat Dukhaned6baaf2020-12-01 15:07:08 -0800117
118$if OP_TYPE == "ELU":
119 TEST(${TEST_NAME}, prescale) {
120 $if ISA_CHECK:
121 ${ISA_CHECK};
122 for (float prescale : std::vector<float>({0.1f, 10.0f})) {
123 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
124 VUnOpMicrokernelTester()
125 .batch_size(batch_size)
126 .prescale(prescale)
127 .Test(${", ".join(TEST_ARGS)});
128 }
129 }
130 }
131
132 TEST(${TEST_NAME}, alpha) {
133 $if ISA_CHECK:
134 ${ISA_CHECK};
135 for (float alpha : std::vector<float>({0.3f, 3.0f})) {
136 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
137 VUnOpMicrokernelTester()
138 .batch_size(batch_size)
139 .alpha(alpha)
140 .Test(${", ".join(TEST_ARGS)});
141 }
142 }
143 }
144
145 TEST(${TEST_NAME}, beta) {
146 $if ISA_CHECK:
147 ${ISA_CHECK};
148 for (float beta : std::vector<float>({0.3f, 3.0f})) {
149 for (size_t batch_size = 1; batch_size <= ${BATCH_TILE*5}; batch_size += ${max(1, BATCH_TILE-1)}) {
150 VUnOpMicrokernelTester()
151 .batch_size(batch_size)
152 .beta(beta)
153 .Test(${", ".join(TEST_ARGS)});
154 }
155 }
156 }
Marat Dukhan346a9e52019-11-15 09:06:30 -0800157"""
158
159
160def generate_test_cases(ukernel, op_type, batch_tile, isa):
161 """Generates all tests cases for a Vector Unary Operation micro-kernel.
162
163 Args:
164 ukernel: C name of the micro-kernel function.
165 op_type: Operation type.
166 batch_tile: Number of batch elements processed per one iteration of the
167 inner loop of the micro-kernel.
168 isa: instruction set required to run the micro-kernel. Generated unit test
169 will skip execution if the host processor doesn't support this ISA.
170
171 Returns:
172 Code for the test case.
173 """
174 _, test_name = ukernel.split("_", 1)
175 _, datatype, _ = ukernel.split("_", 2)
176 test_args = [
Marat Dukhan2b9efd82020-06-08 01:09:31 -0700177 "xnn_f32_vunary_ukernel_function(%s)" % ukernel,
Marat Dukhan346a9e52019-11-15 09:06:30 -0800178 "VUnOpMicrokernelTester::OpType::%s" % op_type,
179 ]
Marat Dukhan3de5dfa2020-12-10 11:19:47 -0800180 if not isa:
Marat Dukhan3a77ea72019-12-23 12:10:24 -0800181 test_args.append("VUnOpMicrokernelTester::Variant::Scalar")
Marat Dukhan346a9e52019-11-15 09:06:30 -0800182 return xngen.preprocess(BINOP_TEST_TEMPLATE, {
183 "TEST_NAME": test_name.upper().replace("UKERNEL_", ""),
184 "TEST_ARGS": test_args,
185 "DATATYPE": datatype,
186 "BATCH_TILE": batch_tile,
187 "OP_TYPE": op_type,
188 "ISA_CHECK": xnncommon.generate_isa_check_macro(isa),
189 })
190
191
192def main(args):
193 options = parser.parse_args(args)
194
195 with codecs.open(options.spec, "r", encoding="utf-8") as spec_file:
196 spec_yaml = yaml.safe_load(spec_file)
197 if not isinstance(spec_yaml, list):
198 raise ValueError("expected a list of micro-kernels in the spec")
199
200 tests = """\
201// Copyright 2019 Google LLC
202//
203// This source code is licensed under the BSD-style license found in the
204// LICENSE file in the root directory of this source tree.
205//
206// Auto-generated file. Do not edit!
207// Specification: {specification}
208// Generator: {generator}
209
210
211#include <gtest/gtest.h>
212
213#include <xnnpack/common.h>
214#include <xnnpack/isa-checks.h>
215
Marat Dukhan1e782c42019-11-21 17:02:40 -0800216#include <xnnpack/vunary.h>
217#include "vunary-microkernel-tester.h"
Marat Dukhan346a9e52019-11-15 09:06:30 -0800218""".format(specification=options.spec, generator=sys.argv[0])
219
220 for ukernel_spec in spec_yaml:
221 name = ukernel_spec["name"]
222 op_type, batch_tile, arch, isa = split_ukernel_name(name)
223
224 # specification can override architecture
225 arch = ukernel_spec.get("arch", arch)
226
227 test_case = generate_test_cases(name, op_type, batch_tile, isa)
228 tests += "\n\n" + xnncommon.postprocess_test_case(test_case, arch, isa)
229
230 with codecs.open(options.output, "w", encoding="utf-8") as output_file:
231 output_file.write(tests)
232
233
234if __name__ == "__main__":
235 main(sys.argv[1:])