blob: 47c351ab14038fc372e26cedb34f2bcc08ff5351 [file] [log] [blame]
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001# Copyright (c) 2020-2024, ARM Limited.
Jeremy Johnson5c1364c2022-01-13 15:04:21 +00002# SPDX-License-Identifier: Apache-2.0
Eric Kunzee5e26762020-10-13 16:11:07 -07003import argparse
Jeremy Johnsonaf090182024-02-13 18:25:39 +00004import json
5import logging
Eric Kunzee5e26762020-10-13 16:11:07 -07006import re
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +01007import sys
Jeremy Johnson65ba8092023-10-09 16:31:13 +01008from pathlib import Path
Eric Kunzee5e26762020-10-13 16:11:07 -07009
Jeremy Johnson65ba8092023-10-09 16:31:13 +010010import conformance.model_files as cmf
Jeremy Johnsonaf090182024-02-13 18:25:39 +000011import generator.tosa_test_select as tts
Jeremy Johnson2ec34942021-12-14 16:34:05 +000012from generator.tosa_test_gen import TosaTestGen
13from serializer.tosa_serializer import dtype_str_to_val
James Ward24dbc422022-10-19 12:20:31 +010014from serializer.tosa_serializer import DTypeNames
Eric Kunzee5e26762020-10-13 16:11:07 -070015
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +010016OPTION_FP_VALUES_RANGE = "--fp-values-range"
17
Jeremy Johnsonaf090182024-02-13 18:25:39 +000018logging.basicConfig()
19logger = logging.getLogger("tosa_verif_build_tests")
20
Jeremy Johnson5c1364c2022-01-13 15:04:21 +000021
Jeremy Johnsona4d907e2023-10-26 13:53:14 +010022# Used for parsing a comma-separated list of integers/floats in a string
23# to an actual list of integers/floats with special case max
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +010024def str_to_list(in_s, is_float=False):
Jeremy Johnsona4d907e2023-10-26 13:53:14 +010025 """Converts a comma-separated list string to a python list of numbers."""
Kevin Cheng550ccc52021-03-03 11:21:43 -080026 lst = in_s.split(",")
Eric Kunzee5e26762020-10-13 16:11:07 -070027 out_list = []
28 for i in lst:
Jeremy Johnsona4d907e2023-10-26 13:53:14 +010029 # Special case for allowing maximum FP numbers
30 if is_float and i in ("-max", "max"):
31 val = i
32 else:
33 val = float(i) if is_float else int(i)
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +010034 out_list.append(val)
Eric Kunzee5e26762020-10-13 16:11:07 -070035 return out_list
36
Kevin Cheng550ccc52021-03-03 11:21:43 -080037
Eric Kunzee5e26762020-10-13 16:11:07 -070038def auto_int(x):
Kevin Cheng550ccc52021-03-03 11:21:43 -080039 """Converts hex/dec argument values to an int"""
Eric Kunzee5e26762020-10-13 16:11:07 -070040 return int(x, 0)
41
Kevin Cheng550ccc52021-03-03 11:21:43 -080042
Jeremy Johnson00423432022-09-12 17:27:37 +010043def parseArgs(argv):
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +010044 """Parse the command line arguments."""
45 if argv is None:
46 argv = sys.argv[1:]
47
48 if OPTION_FP_VALUES_RANGE in argv:
49 # Argparse fix for hyphen (minus values) in argument values
50 # convert "ARG VAL" into "ARG=VAL"
51 # Example --fp-values-range -2.0,2.0 -> --fp-values-range=-2.0,2.0
52 new_argv = []
53 idx = 0
54 while idx < len(argv):
55 arg = argv[idx]
56 if arg == OPTION_FP_VALUES_RANGE and idx + 1 < len(argv):
57 val = argv[idx + 1]
58 if val.startswith("-"):
59 arg = f"{arg}={val}"
60 idx += 1
61 new_argv.append(arg)
62 idx += 1
63 argv = new_argv
Eric Kunzee5e26762020-10-13 16:11:07 -070064
65 parser = argparse.ArgumentParser()
Jeremy Johnson1271c442023-09-05 11:39:26 +010066
Jeremy Johnsonaf090182024-02-13 18:25:39 +000067 filter_group = parser.add_argument_group("test filter options")
Jeremy Johnson1271c442023-09-05 11:39:26 +010068 ops_group = parser.add_argument_group("operator options")
69 tens_group = parser.add_argument_group("tensor options")
70
Kevin Cheng550ccc52021-03-03 11:21:43 -080071 parser.add_argument(
72 "-o", dest="output_dir", type=str, default="vtest", help="Test output directory"
73 )
Eric Kunzee5e26762020-10-13 16:11:07 -070074
Kevin Cheng550ccc52021-03-03 11:21:43 -080075 parser.add_argument(
76 "--seed",
77 dest="random_seed",
78 default=42,
79 type=int,
80 help="Random seed for test generation",
81 )
Eric Kunzee5e26762020-10-13 16:11:07 -070082
Jeremy Johnsonaf090182024-02-13 18:25:39 +000083 filter_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -080084 "--filter",
85 dest="filter",
86 default="",
87 type=str,
88 help="Filter operator test names by this expression",
89 )
Eric Kunzee5e26762020-10-13 16:11:07 -070090
Kevin Cheng550ccc52021-03-03 11:21:43 -080091 parser.add_argument(
Jeremy Johnsonaf090182024-02-13 18:25:39 +000092 "-v",
93 "--verbose",
94 dest="verbose",
95 action="count",
96 default=0,
97 help="Verbose operation",
Kevin Cheng550ccc52021-03-03 11:21:43 -080098 )
Eric Kunzee5e26762020-10-13 16:11:07 -070099
Kevin Cheng550ccc52021-03-03 11:21:43 -0800100 parser.add_argument(
Jeremy Johnson1271c442023-09-05 11:39:26 +0100101 "--lazy-data-generation",
102 dest="lazy_data_gen",
103 action="store_true",
104 help="Tensor data generation is delayed til test running",
105 )
106
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100107 parser.add_argument(
108 "--generate-lib-path",
109 dest="generate_lib_path",
110 type=Path,
111 help="Path to TOSA generate library.",
112 )
113
Jeremy Johnson1271c442023-09-05 11:39:26 +0100114 # Constraints on tests
115 tens_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800116 "--tensor-dim-range",
117 dest="tensor_shape_range",
118 default="1,64",
119 type=lambda x: str_to_list(x),
120 help="Min,Max range of tensor shapes",
121 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700122
Jeremy Johnson1271c442023-09-05 11:39:26 +0100123 tens_group.add_argument(
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100124 OPTION_FP_VALUES_RANGE,
125 dest="tensor_fp_value_range",
126 default="0.0,1.0",
127 type=lambda x: str_to_list(x, is_float=True),
128 help="Min,Max range of floating point tensor values",
129 )
130
Jeremy Johnson1271c442023-09-05 11:39:26 +0100131 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800132 "--max-batch-size",
133 dest="max_batch_size",
134 default=1,
James Ward30124a82023-02-02 14:56:33 +0000135 type=positive_integer_type,
Kevin Cheng550ccc52021-03-03 11:21:43 -0800136 help="Maximum batch size for NHWC tests",
137 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700138
Jeremy Johnson1271c442023-09-05 11:39:26 +0100139 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800140 "--max-conv-padding",
141 dest="max_conv_padding",
142 default=1,
143 type=int,
144 help="Maximum padding for Conv tests",
145 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700146
Jeremy Johnson1271c442023-09-05 11:39:26 +0100147 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800148 "--max-conv-dilation",
149 dest="max_conv_dilation",
150 default=2,
151 type=int,
152 help="Maximum dilation for Conv tests",
153 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700154
Jeremy Johnson1271c442023-09-05 11:39:26 +0100155 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800156 "--max-conv-stride",
157 dest="max_conv_stride",
158 default=2,
159 type=int,
160 help="Maximum stride for Conv tests",
161 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700162
Jeremy Johnson1271c442023-09-05 11:39:26 +0100163 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800164 "--max-pooling-padding",
165 dest="max_pooling_padding",
166 default=1,
167 type=int,
168 help="Maximum padding for pooling tests",
169 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700170
Jeremy Johnson1271c442023-09-05 11:39:26 +0100171 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800172 "--max-pooling-stride",
173 dest="max_pooling_stride",
174 default=2,
175 type=int,
176 help="Maximum stride for pooling tests",
177 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700178
Jeremy Johnson1271c442023-09-05 11:39:26 +0100179 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800180 "--max-pooling-kernel",
181 dest="max_pooling_kernel",
Jeremy Johnson39f127b2022-01-25 17:51:26 +0000182 default=3,
Kevin Cheng550ccc52021-03-03 11:21:43 -0800183 type=int,
Jeremy Johnson39f127b2022-01-25 17:51:26 +0000184 help="Maximum kernel for pooling tests",
Kevin Cheng550ccc52021-03-03 11:21:43 -0800185 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700186
Jeremy Johnson1271c442023-09-05 11:39:26 +0100187 ops_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800188 "--num-rand-permutations",
189 dest="num_rand_permutations",
190 default=6,
191 type=int,
192 help="Number of random permutations for a given shape/rank for randomly-sampled parameter spaces",
193 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700194
Jeremy Johnson1271c442023-09-05 11:39:26 +0100195 ops_group.add_argument(
Jeremy Johnsona0e03f32022-06-13 17:48:09 +0100196 "--max-resize-output-dim",
197 dest="max_resize_output_dim",
198 default=1000,
199 type=int,
200 help="Upper limit on width and height output dimensions for `resize` op. Default: 1000",
201 )
202
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100203 # Targeting a specific shape/rank/dtype
Jeremy Johnson1271c442023-09-05 11:39:26 +0100204 tens_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800205 "--target-shape",
206 dest="target_shapes",
207 action="append",
208 default=[],
209 type=lambda x: str_to_list(x),
210 help="Create tests with a particular input tensor shape, e.g., 1,4,4,8 (may be repeated for tests that require multiple input shapes)",
211 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700212
Jeremy Johnson1271c442023-09-05 11:39:26 +0100213 tens_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800214 "--target-rank",
215 dest="target_ranks",
216 action="append",
217 default=None,
218 type=lambda x: auto_int(x),
219 help="Create tests with a particular input tensor rank",
220 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700221
James Ward24dbc422022-10-19 12:20:31 +0100222 # Used for parsing a comma-separated list of integers in a string
Jeremy Johnson1271c442023-09-05 11:39:26 +0100223 tens_group.add_argument(
Kevin Cheng550ccc52021-03-03 11:21:43 -0800224 "--target-dtype",
225 dest="target_dtypes",
226 action="append",
227 default=None,
228 type=lambda x: dtype_str_to_val(x),
James Ward24dbc422022-10-19 12:20:31 +0100229 help=f"Create test with a particular DType: [{', '.join([d.lower() for d in DTypeNames[1:]])}] (may be repeated)",
Kevin Cheng550ccc52021-03-03 11:21:43 -0800230 )
Eric Kunzee5e26762020-10-13 16:11:07 -0700231
Jeremy Johnson1271c442023-09-05 11:39:26 +0100232 ops_group.add_argument(
Matthew Haddon818ab902021-07-27 09:12:49 +0100233 "--num-const-inputs-concat",
234 dest="num_const_inputs_concat",
235 default=0,
236 choices=[0, 1, 2, 3],
237 type=int,
238 help="Allow constant input tensors for concat operator",
239 )
240
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000241 filter_group.add_argument(
Matthew Haddon74567092021-07-16 15:38:20 +0100242 "--test-type",
243 dest="test_type",
Jeremy Johnson5c1364c2022-01-13 15:04:21 +0000244 choices=["positive", "negative", "both"],
Matthew Haddon74567092021-07-16 15:38:20 +0100245 default="positive",
246 type=str,
Jeremy Johnson39f127b2022-01-25 17:51:26 +0000247 help="type of tests produced, positive, negative, or both",
Matthew Haddon74567092021-07-16 15:38:20 +0100248 )
Jeremy Johnson39f127b2022-01-25 17:51:26 +0000249
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000250 filter_group.add_argument(
251 "--test-selection-config",
252 dest="selection_config",
253 type=Path,
254 help="enables test selection, this is the path to the JSON test selection config file, will use the default selection specified for each op unless --selection-criteria is supplied",
255 )
256
257 filter_group.add_argument(
258 "--test-selection-criteria",
259 dest="selection_criteria",
260 help="enables test selection, this is the selection criteria to use from the selection config",
261 )
262
263 parser.add_argument(
264 "--list-tests",
265 dest="list_tests",
266 action="store_true",
267 help="lists the tests that will be generated and then exits",
268 )
269
Jeremy Johnson1271c442023-09-05 11:39:26 +0100270 ops_group.add_argument(
Jeremy Johnson39f127b2022-01-25 17:51:26 +0000271 "--allow-pooling-and-conv-oversizes",
272 dest="oversize",
Jeremy Johnsonae0c1c62022-02-10 17:27:34 +0000273 action="store_true",
Jeremy Johnson39f127b2022-01-25 17:51:26 +0000274 help="allow oversize padding, stride and kernel tests",
275 )
276
Jeremy Johnson1271c442023-09-05 11:39:26 +0100277 ops_group.add_argument(
Jeremy Johnson00423432022-09-12 17:27:37 +0100278 "--zero-point",
279 dest="zeropoint",
280 default=None,
281 type=int,
282 help="set a particular zero point for all valid positive tests",
283 )
284
Jeremy Johnsona0848c62022-09-15 15:01:30 +0100285 parser.add_argument(
286 "--dump-const-tensors",
287 dest="dump_consts",
288 action="store_true",
289 help="output const tensors as numpy files for inspection",
290 )
291
Jeremy Johnson1271c442023-09-05 11:39:26 +0100292 ops_group.add_argument(
Jeremy Johnsonb2099702023-04-12 15:59:01 +0100293 "--level-8k-sizes",
294 dest="level8k",
295 action="store_true",
Jeremy Johnson1271c442023-09-05 11:39:26 +0100296 help="create level 8k size tests",
Jeremy Johnsonb2099702023-04-12 15:59:01 +0100297 )
298
Jeremy Johnson00423432022-09-12 17:27:37 +0100299 args = parser.parse_args(argv)
Eric Kunzee5e26762020-10-13 16:11:07 -0700300
301 return args
302
Eric Kunzee5e26762020-10-13 16:11:07 -0700303
James Ward30124a82023-02-02 14:56:33 +0000304def positive_integer_type(argv_str):
305 value = int(argv_str)
306 if value <= 0:
307 msg = f"{argv_str} is not a valid positive integer"
308 raise argparse.ArgumentTypeError(msg)
309 return value
310
311
Jeremy Johnson00423432022-09-12 17:27:37 +0100312def main(argv=None):
Eric Kunzee5e26762020-10-13 16:11:07 -0700313
Jeremy Johnson00423432022-09-12 17:27:37 +0100314 args = parseArgs(argv)
Eric Kunzee5e26762020-10-13 16:11:07 -0700315
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000316 loglevels = (logging.WARNING, logging.INFO, logging.DEBUG)
317 loglevel = loglevels[min(args.verbose, len(loglevels) - 1)]
318 logger.setLevel(loglevel)
319
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100320 if not args.lazy_data_gen:
321 if args.generate_lib_path is None:
322 args.generate_lib_path = cmf.find_tosa_file(
323 cmf.TosaFileType.GENERATE_LIBRARY, Path("reference_model"), False
324 )
325 if not args.generate_lib_path.is_file():
326 print(
327 f"Argument error: Generate library (--generate-lib-path) not found - {str(args.generate_lib_path)}"
328 )
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000329 return 2
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100330
Eric Kunzee5e26762020-10-13 16:11:07 -0700331 ttg = TosaTestGen(args)
332
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000333 # Determine if test selection mode is enabled or not
334 selectionMode = (
335 args.selection_config is not None or args.selection_criteria is not None
336 )
337 selectionCriteria = (
338 "default" if args.selection_criteria is None else args.selection_criteria
339 )
340 if args.selection_config is not None:
341 # Try loading the selection config
342 if not args.generate_lib_path.is_file():
343 print(
344 f"Argument error: Test selection config (--test-selection-config) not found {str(args.selection_config)}"
345 )
346 return 2
347 with args.selection_config.open("r") as fd:
348 selectionCfg = json.load(fd)
349 else:
350 # Fallback to using anything defined in the TosaTestGen list
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000351 selectionCfg = ttg.TOSA_OP_LIST
Jeremy Johnson00dc22e2024-03-13 17:06:06 +0000352 # Set up some defaults to create a quick testing selection
353 selectDefault = {"default": {"permutes": ["rank", "dtype"], "maximum": 10}}
354 for opName in selectionCfg:
355 if (
356 "selection" not in selectionCfg[opName]
357 or "default" not in selectionCfg[opName]["selection"]
358 ):
359 selectionCfg[opName]["selection"] = selectDefault
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000360
Jeremy Johnson5c1364c2022-01-13 15:04:21 +0000361 if args.test_type == "both":
362 testType = ["positive", "negative"]
Matthew Haddon1c00b712021-10-01 15:51:03 +0100363 else:
364 testType = [args.test_type]
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000365
Matthew Haddon74567092021-07-16 15:38:20 +0100366 results = []
Matthew Haddon1c00b712021-10-01 15:51:03 +0100367 for test_type in testType:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000368 testList = tts.TestList(selectionCfg, selectionCriteria=selectionCriteria)
Jeremy Johnson7bf0cb92023-10-31 14:37:54 +0000369 try:
370 for opName in ttg.TOSA_OP_LIST:
371 if re.match(args.filter + ".*", opName):
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000372 tests = ttg.genOpTestList(
373 opName,
374 shapeFilter=args.target_shapes,
375 rankFilter=args.target_ranks,
376 dtypeFilter=args.target_dtypes,
377 testType=test_type,
Matthew Haddon1c00b712021-10-01 15:51:03 +0100378 )
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000379 for testOpName, testStr, dtype, error, shapeList, argsDict in tests:
380 if "real_name" in ttg.TOSA_OP_LIST[testOpName]:
381 name = ttg.TOSA_OP_LIST[testOpName]["real_name"]
382 else:
383 name = testOpName
384 test = tts.Test(
385 name, testStr, dtype, error, shapeList, argsDict, testOpName
386 )
387 testList.add(test)
Jeremy Johnson7bf0cb92023-10-31 14:37:54 +0000388 except Exception as e:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000389 logger.error(f"INTERNAL ERROR: Failure generating test lists for {opName}")
Jeremy Johnson7bf0cb92023-10-31 14:37:54 +0000390 raise e
Matthew Haddon848efb42021-09-09 12:30:53 +0100391
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000392 if not selectionMode:
393 # Allow all tests to be selected
394 tests = testList.all()
395 else:
396 # Use the random number generator to shuffle the test list
397 # and select the per op tests from it
398 tests = testList.select(ttg.rng)
Matthew Haddon1c00b712021-10-01 15:51:03 +0100399
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000400 if args.list_tests:
401 for test in tests:
402 print(test)
403 continue
404
405 print(f"{len(tests)} matching {test_type} tests")
406
Jeremy Johnson7bf0cb92023-10-31 14:37:54 +0000407 try:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000408 for test in tests:
409 opName = test.testOpName
Jeremy Johnson7bf0cb92023-10-31 14:37:54 +0000410 results.append(
411 ttg.serializeTest(
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000412 opName,
413 str(test),
414 test.dtype,
415 test.error,
416 test.shapeList,
417 test.argsDict,
Jeremy Johnson7bf0cb92023-10-31 14:37:54 +0000418 )
419 )
420 except Exception as e:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000421 logger.error(f"INTERNAL ERROR: Failure creating test output for {opName}")
Jeremy Johnson7bf0cb92023-10-31 14:37:54 +0000422 raise e
Matthew Haddon74567092021-07-16 15:38:20 +0100423
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000424 if not args.list_tests:
425 print(f"Done creating {len(results)} tests")
426 return 0
Matthew Haddon74567092021-07-16 15:38:20 +0100427
Eric Kunzee5e26762020-10-13 16:11:07 -0700428
Kevin Cheng550ccc52021-03-03 11:21:43 -0800429if __name__ == "__main__":
Eric Kunzee5e26762020-10-13 16:11:07 -0700430 exit(main())