blob: 6b9082086962887be6686d92bd95ab247697e2a3 [file] [log] [blame]
Marat Dukhan35dacfb2019-11-07 19:18:16 -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 os
10import re
11import sys
12import yaml
13
14sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
15from primes import next_prime
16import xngen
17import xnncommon
18
19
20parser = argparse.ArgumentParser(
21 description='Bilinear 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):
30 match = re.match(r"^xnn_(f16|f32)_bilinear_ukernel__(.+)_c(\d+)$", name)
31 assert match is not None
32 channel_tile = int(match.group(3))
33 pixel_tile = 1
34
35 arch, isa = xnncommon.parse_target_name(target_name=match.group(2))
36 return channel_tile, pixel_tile, arch, isa
37
38
39BILINEAR_TEST_TEMPLATE = """\
40TEST(${TEST_NAME}, channels_eq_${CHANNEL_TILE}) {
41 $if ISA_CHECK:
42 ${ISA_CHECK};
43 BilinearMicrokernelTester()
44 .pixels(${PIXEL_TILE})
45 .channels(${CHANNEL_TILE})
46 .Test(${TEST_FUNC});
47}
48
49$if CHANNEL_TILE > 1:
50 TEST(${TEST_NAME}, channels_div_${CHANNEL_TILE}) {
51 $if ISA_CHECK:
52 ${ISA_CHECK};
53 for (size_t channels = ${CHANNEL_TILE*2}; channels < ${CHANNEL_TILE*10}; channels += ${CHANNEL_TILE}) {
54 BilinearMicrokernelTester()
55 .pixels(${PIXEL_TILE})
56 .channels(channels)
57 .Test(${TEST_FUNC});
58 }
59 }
60
61 TEST(${TEST_NAME}, channels_lt_${CHANNEL_TILE}) {
62 $if ISA_CHECK:
63 ${ISA_CHECK};
64 for (size_t channels = 1; channels < ${CHANNEL_TILE}; channels++) {
65 BilinearMicrokernelTester()
66 .pixels(${PIXEL_TILE})
67 .channels(channels)
68 .Test(${TEST_FUNC});
69 }
70 }
71
72TEST(${TEST_NAME}, channels_gt_${CHANNEL_TILE}) {
73 $if ISA_CHECK:
74 ${ISA_CHECK};
75 for (size_t channels = ${CHANNEL_TILE+1}; channels < ${10 if CHANNEL_TILE == 1 else CHANNEL_TILE*2}; channels++) {
76 BilinearMicrokernelTester()
77 .pixels(${PIXEL_TILE})
78 .channels(channels)
79 .Test(${TEST_FUNC});
80 }
81}
82
83$if PIXEL_TILE > 1:
84 TEST(${TEST_NAME}, pixels_div_${PIXEL_TILE}) {
85 $if ISA_CHECK:
86 ${ISA_CHECK};
87 for (size_t pixels = ${PIXEL_TILE*2}; pixels < ${PIXEL_TILE*10}; pixels += ${PIXEL_TILE}) {
88 for (size_t channels = 1; channels <= ${CHANNEL_TILE * 5}; channels += ${max(1, CHANNEL_TILE - 1)}) {
89 BilinearMicrokernelTester()
90 .pixels(pixels)
91 .channels(channels)
92 .Test(${TEST_FUNC});
93 }
94 }
95 }
96
97 TEST(${TEST_NAME}, pixels_lt_${PIXEL_TILE}) {
98 $if ISA_CHECK:
99 ${ISA_CHECK};
100 for (size_t pixels = 1; pixels < ${PIXEL_TILE}; pixels++) {
101 for (size_t channels = 1; channels <= ${CHANNEL_TILE * 5}; channels += ${max(1, CHANNEL_TILE - 1)}) {
102 BilinearMicrokernelTester()
103 .pixels(pixels)
104 .channels(channels)
105 .Test(${TEST_FUNC});
106 }
107 }
108 }
109
110TEST(${TEST_NAME}, pixels_gt_${PIXEL_TILE}) {
111 $if ISA_CHECK:
112 ${ISA_CHECK};
113 for (size_t pixels = ${PIXEL_TILE+1}; pixels < ${max(PIXEL_TILE*2, 3)}; pixels++) {
114 for (size_t channels = 1; channels <= ${CHANNEL_TILE * 5}; channels += ${max(1, CHANNEL_TILE - 1)}) {
115 BilinearMicrokernelTester()
116 .pixels(pixels)
117 .channels(channels)
118 .Test(${TEST_FUNC});
119 }
120 }
121}
122
Marat Dukhan9fab3f92019-11-08 14:55:19 -0800123TEST(${TEST_NAME}, input_offset) {
124 $if ISA_CHECK:
125 ${ISA_CHECK};
126 for (size_t pixels = 1; pixels < ${PIXEL_TILE * 5}; pixels += ${max(1, PIXEL_TILE - 1)}) {
127 for (size_t channels = 1; channels <= ${CHANNEL_TILE * 5}; channels += ${max(1, CHANNEL_TILE - 1)}) {
128 BilinearMicrokernelTester()
129 .pixels(pixels)
130 .channels(channels)
131 .input_offset(${next_prime(CHANNEL_TILE * 5 + 1)})
132 .Test(${TEST_FUNC});
133 }
134 }
135}
Marat Dukhan35dacfb2019-11-07 19:18:16 -0800136TEST(${TEST_NAME}, output_stride) {
137 $if ISA_CHECK:
138 ${ISA_CHECK};
139 for (size_t pixels = 1; pixels < ${PIXEL_TILE * 5}; pixels += ${max(1, PIXEL_TILE - 1)}) {
140 for (size_t channels = 1; channels <= ${CHANNEL_TILE * 5}; channels += ${max(1, CHANNEL_TILE - 1)}) {
141 BilinearMicrokernelTester()
142 .pixels(pixels)
143 .channels(channels)
144 .output_stride(${next_prime(CHANNEL_TILE * 5 + 1)})
145 .Test(${TEST_FUNC});
146 }
147 }
148}
149"""
150
151
152def generate_test_cases(ukernel, channel_tile, pixel_tile, isa):
153 """Generates all tests cases for a BILINEAR micro-kernel.
154
155 Args:
156 ukernel: C name of the micro-kernel function.
157 channel_tile: Number of channels processed per one iteration of the inner
158 loop of the micro-kernel.
159 pixel_tile: Number of pixels processed per one iteration of the outer loop
160 of the micro-kernel.
161 isa: instruction set required to run the micro-kernel. Generated unit test
162 will skip execution if the host processor doesn't support this ISA.
163
164 Returns:
165 Code for the test case.
166 """
167 _, test_name = ukernel.split("_", 1)
168 _, datatype, ukernel_type, _ = ukernel.split("_", 3)
169 test_args = [ukernel]
170 return xngen.preprocess(BILINEAR_TEST_TEMPLATE, {
171 "TEST_NAME": test_name.upper().replace("UKERNEL_", ""),
172 "TEST_FUNC": ukernel,
173 "UKERNEL_TYPE": ukernel_type.upper(),
174 "DATATYPE": datatype,
175 "CHANNEL_TILE": channel_tile,
176 "PIXEL_TILE": pixel_tile,
177 "ISA_CHECK": xnncommon.generate_isa_check_macro(isa),
178 "next_prime": next_prime,
179 })
180
181
182def main(args):
183 options = parser.parse_args(args)
184
185 with codecs.open(options.spec, "r", encoding="utf-8") as spec_file:
186 spec_yaml = yaml.safe_load(spec_file)
187 if not isinstance(spec_yaml, list):
188 raise ValueError("expected a list of micro-kernels in the spec")
189
190 tests = """\
191// Copyright 2019 Google LLC
192//
193// This source code is licensed under the BSD-style license found in the
194// LICENSE file in the root directory of this source tree.
195//
196// Auto-generated file. Do not edit!
197// Specification: {specification}
198// Generator: {generator}
199
200
201#include <gtest/gtest.h>
202
203#include <xnnpack/common.h>
204#include <xnnpack/isa-checks.h>
205
206#include <xnnpack/bilinear.h>
207#include "bilinear-microkernel-tester.h"
208""".format(specification=options.spec, generator=sys.argv[0])
209
210 for ukernel_spec in spec_yaml:
211 name = ukernel_spec["name"]
212 channel_tile, pixel_tile, arch, isa = split_ukernel_name(name)
213
214 # specification can override architecture
215 arch = ukernel_spec.get("arch", arch)
216
217 test_case = generate_test_cases(name, channel_tile, pixel_tile, isa)
218 tests += "\n\n" + xnncommon.postprocess_test_case(test_case, arch, isa)
219
220 with codecs.open(options.output, "w", encoding="utf-8") as output_file:
221 output_file.write(tests)
222
223
224if __name__ == "__main__":
225 main(sys.argv[1:])