From 64e4bfe627ded0ba44ff60b23db28c1ff5d73d13 Mon Sep 17 00:00:00 2001 From: Won Jeon Date: Thu, 18 Jan 2024 06:31:55 +0000 Subject: Update RESHAPE and TILE conformance testing Signed-off-by: Won Jeon Change-Id: Iaf59472cb32e03a92bad87ae9dba1b7548f20268 --- reference_model/CMakeLists.txt | 2 + reference_model/src/generate/generate_entry.cc | 7 +- .../src/generate/generate_fixed_data.cc | 56 +++++++++++++++ reference_model/src/generate/generate_fixed_data.h | 34 ++++++++++ reference_model/src/generate/generate_utils.cc | 15 ++++ reference_model/src/generate/generate_utils.h | 12 +++- .../schemavalidation/datagen-config.schema.json | 19 +++++- verif/generator/datagenerator.py | 2 +- verif/generator/tosa_arg_gen.py | 79 ++++++++++++++++------ verif/generator/tosa_test_gen.py | 30 ++------ verif/generator/tosa_utils.py | 5 +- 11 files changed, 213 insertions(+), 48 deletions(-) create mode 100644 reference_model/src/generate/generate_fixed_data.cc create mode 100644 reference_model/src/generate/generate_fixed_data.h diff --git a/reference_model/CMakeLists.txt b/reference_model/CMakeLists.txt index 178594b..d2dce3c 100644 --- a/reference_model/CMakeLists.txt +++ b/reference_model/CMakeLists.txt @@ -73,6 +73,7 @@ set(CXX_SOURCE src/generate/generate_dot_product_states.cc src/generate/generate_dot_product.cc src/generate/generate_pseudo_random.cc + src/generate/generate_fixed_data.cc src/generate/generate_entry.cc src/generate/generate_utils.cc src/verify/verify_abs_error.cc @@ -173,6 +174,7 @@ add_library(tosa_reference_generate_lib SHARED src/generate/generate_dot_product_states.cc src/generate/generate_dot_product.cc src/generate/generate_pseudo_random.cc + src/generate/generate_fixed_data.cc src/generate/generate_entry.cc src/generate/generate_utils.cc src/generate/generate_config.cc diff --git a/reference_model/src/generate/generate_entry.cc b/reference_model/src/generate/generate_entry.cc index 741cd79..91b2fc7 100644 --- a/reference_model/src/generate/generate_entry.cc +++ b/reference_model/src/generate/generate_entry.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2023, ARM Limited. +// Copyright (c) 2023-2024, ARM Limited. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ #include "generate.h" #include "generate_dot_product.h" +#include "generate_fixed_data.h" #include "generate_pseudo_random.h" #include "generate_utils.h" @@ -36,6 +37,10 @@ bool generate(const GenerateConfig& cfg, void* data, size_t size) return generatePseudoRandom(cfg, data, size); break; } + case GeneratorType::FixedData: { + return generateFixedData(cfg, data, size); + break; + } default: { WARNING("[Generator] Unsupported generation mode."); break; diff --git a/reference_model/src/generate/generate_fixed_data.cc b/reference_model/src/generate/generate_fixed_data.cc new file mode 100644 index 0000000..d83ee58 --- /dev/null +++ b/reference_model/src/generate/generate_fixed_data.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2024, ARM Limited. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "generate.h" +#include "generate_utils.h" + +#include +#include +#include +#include +#include + +namespace TosaReference +{ +bool generateFixedData(const GenerateConfig& cfg, void* data, size_t size) +{ + // Check we support the operator + if (cfg.opType == Op::Op_UNKNOWN) + { + WARNING("[Generator][FD] Unknown operator."); + return false; + } + + switch (cfg.dataType) + { + case DType::DType_SHAPE: { + int32_t* outData = reinterpret_cast(data); + std::vector inData = cfg.fixedDataInfo.data; + const auto T = TosaReference::numElementsFromShape(cfg.shape); + if (T != inData.size()) + { + WARNING("[Generator][FD] Size does not match."); + return false; + } + for (auto t = 0; t < T; t++) + { + outData[t] = inData[t]; + } + return true; + } + default: + WARNING("[Generator][FD] Unsupported type."); + return false; + } +} +} // namespace TosaReference diff --git a/reference_model/src/generate/generate_fixed_data.h b/reference_model/src/generate/generate_fixed_data.h new file mode 100644 index 0000000..50371c8 --- /dev/null +++ b/reference_model/src/generate/generate_fixed_data.h @@ -0,0 +1,34 @@ +// Copyright (c) 2024, ARM Limited. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GENERATE_FIXED_DATA_H_ +#define GENERATE_FIXED_DATA_H_ + +#include "generate_utils.h" + +namespace TosaReference +{ + +/// \brief Perform fixed data generation +/// +/// \param cfg Generator related meta-data +/// \param data Buffer to generate the data to +/// \param size Size of the buffer +/// +/// \return True on successful generation +bool generateFixedData(const GenerateConfig& cfg, void* data, size_t size); + +}; // namespace TosaReference + +#endif // GENERATE_FIXED_DATA_H_ diff --git a/reference_model/src/generate/generate_utils.cc b/reference_model/src/generate/generate_utils.cc index c16d1c6..9eda0b6 100644 --- a/reference_model/src/generate/generate_utils.cc +++ b/reference_model/src/generate/generate_utils.cc @@ -33,6 +33,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(DType, { DType::DType_FP16, "FP16" }, { DType::DType_BF16, "BF16" }, { DType::DType_FP32, "FP32" }, + { DType::DType_SHAPE, "SHAPE" }, }) NLOHMANN_JSON_SERIALIZE_ENUM(Op, @@ -93,6 +94,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(GeneratorType, { GeneratorType::OpFullRange, "OP_FULL_RANGE" }, { GeneratorType::OpBoundary, "OP_BOUNDARY" }, { GeneratorType::OpSpecial, "OP_SPECIAL" }, + { GeneratorType::FixedData, "FIXED_DATA" }, }) // NOTE: This assumes it's VARIABLE if the InputType is not recognized @@ -130,6 +132,11 @@ void from_json(const nlohmann::json& j, PseudoRandomInfo& pseudoRandomInfo) } } +void from_json(const nlohmann::json& j, FixedDataInfo& fixedDataInfo) +{ + j.at("data").get_to(fixedDataInfo.data); +} + void from_json(const nlohmann::json& j, GenerateConfig& cfg) { j.at("data_type").get_to(cfg.dataType); @@ -158,6 +165,13 @@ void from_json(const nlohmann::json& j, GenerateConfig& cfg) { j.at("pseudo_random_info").get_to(cfg.pseudoRandomInfo); } + + // Set up defaults for fixedDataInfo + cfg.fixedDataInfo.data = std::vector(); + if (j.contains("fixed_data_info")) + { + j.at("fixed_data_info").get_to(cfg.fixedDataInfo); + } } std::optional parseGenerateConfig(const char* json, const char* tensorName) @@ -209,6 +223,7 @@ size_t elementSizeFromType(DType type) return 2; case DType::DType_INT32: case DType::DType_FP32: + case DType::DType_SHAPE: return 4; default: return 0; diff --git a/reference_model/src/generate/generate_utils.h b/reference_model/src/generate/generate_utils.h index f9ec713..697b404 100644 --- a/reference_model/src/generate/generate_utils.h +++ b/reference_model/src/generate/generate_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2023, ARM Limited. +// Copyright (c) 2023-2024, ARM Limited. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ enum class GeneratorType OpFullRange, OpBoundary, OpSpecial, + FixedData, }; /// \brief Supported input types @@ -65,6 +66,14 @@ struct PseudoRandomInfo bool round; }; +/// \brief Fixed data generator meta-data +struct FixedDataInfo +{ + FixedDataInfo() = default; + + std::vector data; +}; + /// \brief Generator configuration struct GenerateConfig { @@ -76,6 +85,7 @@ struct GenerateConfig tosa::Op opType; DotProductInfo dotProductInfo; PseudoRandomInfo pseudoRandomInfo; + FixedDataInfo fixedDataInfo; }; /// \brief Parse the generator config when given in JSON form diff --git a/scripts/schemavalidation/datagen-config.schema.json b/scripts/schemavalidation/datagen-config.schema.json index 08d564b..a74d79f 100644 --- a/scripts/schemavalidation/datagen-config.schema.json +++ b/scripts/schemavalidation/datagen-config.schema.json @@ -1,5 +1,5 @@ { - "$comment": "Copyright (c) 2023, ARM Limited.", + "$comment": "Copyright (c) 2023-2024, ARM Limited.", "$comment": "SPDX-License-Identifier: Apache-2.0", "$id": "datagen-config.schema.json", "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -147,6 +147,23 @@ }, "additionalProperties": false, "required": [ "sub_generator" ] + }, + "fixed_data_info": { + "description": "info required for FIXED_DATA generator", + "type": "object", + "properties": + { + "data": { + "description": "flattened fixed data", + "type": "array", + "items": { + "description": "integer tensor data", + "type": "integer" + } + } + }, + "additionalProperties": false, + "required": [ "data" ] } }, "additionalProperties": false, diff --git a/verif/generator/datagenerator.py b/verif/generator/datagenerator.py index b5ef35d..743475c 100644 --- a/verif/generator/datagenerator.py +++ b/verif/generator/datagenerator.py @@ -78,7 +78,7 @@ class GenerateLibrary: size_bytes = size * 2 # Create buffer of bytes and initialize to zero buffer = (ct.c_ubyte * size_bytes)(0) - elif dtype == "INT32": + elif dtype == "INT32" or dtype == "SHAPE": # Create buffer and initialize to zero buffer = (ct.c_int32 * size)(0) size_bytes = size * 4 diff --git a/verif/generator/tosa_arg_gen.py b/verif/generator/tosa_arg_gen.py index 00490fa..a655a50 100644 --- a/verif/generator/tosa_arg_gen.py +++ b/verif/generator/tosa_arg_gen.py @@ -731,7 +731,11 @@ class TosaTensorValuesGen: # Change from inclusive to exclusive range data_range = (data_range[0], data_range[1] + 1) # Ignore lazy data gen option and create data array using any range limits - arr = testGen.getRandTensor(shape, dtype, data_range) + + if "fixed_data" in argsDict and argsDict["fixed_data"][idx] is not None: + arr = np.int64(argsDict["fixed_data"][idx]) + else: + arr = testGen.getRandTensor(shape, dtype, data_range) if roundMode: arr = np.round(arr) if idx < pCount: @@ -751,7 +755,13 @@ class TosaTensorValuesGen: for idx, shape in enumerate(shapeList): tens_meta = {} - tens_meta["generator"] = gtu.DataGenType(dg_type).name + if "fixed_data" in argsDict and argsDict["fixed_data"][idx] is not None: + tens_meta["generator"] = gtu.DataGenType( + gtu.DataGenType.FIXED_DATA + ).name + else: + tens_meta["generator"] = gtu.DataGenType(dg_type).name + tens_meta["data_type"] = gtu.DTYPE_ATTRIBUTES[dtypeList[idx]]["json"] tens_meta["shape"] = [int(i) for i in shape] tens_meta["input_pos"] = idx @@ -764,23 +774,30 @@ class TosaTensorValuesGen: if dg_type == gtu.DataGenType.PSEUDO_RANDOM: info = {} - # TODO - generate seed for this generator based on test - info["rng_seed"] = 42 - - data_range = None - if "data_range_list" in argsDict: - data_range = argsDict["data_range_list"][idx]["range"] - if "round" in argsDict["data_range_list"][idx]: - info["round"] = argsDict["data_range_list"][idx]["round"] - elif "data_range" in argsDict: - data_range = argsDict["data_range"] - - if data_range is None: - data_range = testGen.getDTypeRange( - dtypeList[idx], high_inclusive=True - ) - info["range"] = [str(v) for v in data_range] - tens_meta["pseudo_random_info"] = info + if ( + tens_meta["generator"] + == gtu.DataGenType(gtu.DataGenType.FIXED_DATA).name + ): + info["data"] = [int(i) for i in argsDict["fixed_data"][idx]] + tens_meta["fixed_data_info"] = info + else: + # TODO - generate seed for this generator based on test + info["rng_seed"] = 42 + + data_range = None + if "data_range_list" in argsDict: + data_range = argsDict["data_range_list"][idx]["range"] + if "round" in argsDict["data_range_list"][idx]: + info["round"] = argsDict["data_range_list"][idx]["round"] + elif "data_range" in argsDict: + data_range = argsDict["data_range"] + + if data_range is None: + data_range = testGen.getDTypeRange( + dtypeList[idx], high_inclusive=True + ) + info["range"] = [str(v) for v in data_range] + tens_meta["pseudo_random_info"] = info elif dg_type == gtu.DataGenType.DOT_PRODUCT: info = {} info["s"] = argsDict["s"] @@ -812,6 +829,9 @@ class TosaTensorValuesGen: dg_tens_meta[temp_name] = tens_meta # Create data now using the temporary name to access meta details data = testGen.dgl.get_tensor_data(temp_name, tens_data) + if tens_meta["data_type"] == "SHAPE": + # Tensor type SHAPE and Numpy file type must be the same + data = np.int64(data) # Remove the item as we will give it the correct name later del dg_tens_meta[temp_name] @@ -1013,6 +1033,27 @@ class TosaTensorValuesGen: return placeholders + @staticmethod + def tvgReshape(testGen, op, dtypeList, shapeList, argsDict, error_name=None): + dtypeList[1] = DType.SHAPE + shapeList[1] = [len(argsDict["new_shape"])] + # Create a new list for the pre-generated data in argsDict["fixed_data"] + argsDict["fixed_data"] = [None, argsDict["new_shape"]] + + return TosaTensorValuesGen.tvgLazyGenDefault( + testGen, op, dtypeList, shapeList, argsDict, error_name + ) + + @staticmethod + def tvgTile(testGen, op, dtypeList, shapeList, argsDict, error_name=None): + dtypeList[1] = DType.SHAPE + shapeList[1] = [len(argsDict["multiples"])] + argsDict["fixed_data"] = [None, argsDict["multiples"]] + + return TosaTensorValuesGen.tvgLazyGenDefault( + testGen, op, dtypeList, shapeList, argsDict, error_name + ) + @staticmethod def tvgSelect(testGen, opName, dtypeList, shapeList, argsDict, error_name=None): # Set datatype of condition tensor to boolean diff --git a/verif/generator/tosa_test_gen.py b/verif/generator/tosa_test_gen.py index 67ac367..159ee83 100644 --- a/verif/generator/tosa_test_gen.py +++ b/verif/generator/tosa_test_gen.py @@ -1558,22 +1558,14 @@ class TosaTestGen: ): assert len(inputs) == 2 a = inputs[0] - # second input is not properly generated yet - # new_shape = inputs[1] - - # modify inputs[1] by a shape tensor from new_shape arg value - new_shape_attr = args_dict["new_shape"] - shape_array = np.array(new_shape_attr) - shape = shape_array.shape - new_shape = self.ser.addPlaceholder(shape, DType.SHAPE, shape_array) - inputs[1] = new_shape - + shape = inputs[1] + shape_attr = args_dict["new_shape"] result_tensor = OutputShaper.reshapeOp( - self.ser, self.rng, a, new_shape_attr, error_name + self.ser, self.rng, a, shape_attr, error_name ) # Invalidate Input/Output list for error if checks. - input_list = [a.name, new_shape.name] + input_list = [a.name, shape.name] output_list = [result_tensor.name] pCount, cCount = op["operands"] num_operands = pCount + cCount @@ -1725,16 +1717,8 @@ class TosaTestGen: ): assert len(inputs) == 2 a = inputs[0] - # second input is not properly generated yet - # multiples = inputs[1] - - # modify inputs[1] by a shape tensor from multiples arg value + multiples = inputs[1] multiples_attr = args_dict["multiples"] - shape_array = np.int64(np.array(multiples_attr)) - shape = shape_array.shape - multiples = self.ser.addPlaceholder(shape, DType.SHAPE, shape_array) - inputs[1] = multiples - result_tensor = OutputShaper.tileOp( self.ser, self.rng, a, multiples_attr, error_name ) @@ -4236,7 +4220,7 @@ class TosaTestGen: "build_fcn": ( build_reshape, TosaTensorGen.tgBasic, - TosaTensorValuesGen.tvgLazyGenDefault, + TosaTensorValuesGen.tvgReshape, TosaArgGen.agReshape, ), "types": TYPE_FIB, @@ -4302,7 +4286,7 @@ class TosaTestGen: "build_fcn": ( build_tile, TosaTensorGen.tgBasic, - TosaTensorValuesGen.tvgLazyGenDefault, + TosaTensorValuesGen.tvgTile, TosaArgGen.agTile, ), "types": TYPE_FIB, diff --git a/verif/generator/tosa_utils.py b/verif/generator/tosa_utils.py index 3d733f4..33db95f 100644 --- a/verif/generator/tosa_utils.py +++ b/verif/generator/tosa_utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2023, ARM Limited. +# Copyright (c) 2021-2024, ARM Limited. # SPDX-License-Identifier: Apache-2.0 import struct import sys @@ -49,13 +49,14 @@ class DataGenType(IntEnum): OP_BOUNDARY = 2 OP_FULLSET = 3 OP_SPECIAL = 4 + FIXED_DATA = 5 def dtypeIsSupportedByCompliance(dtype): """Types supported by the new data generation and compliance flow.""" if isinstance(dtype, list) or isinstance(dtype, tuple): dtype = dtype[0] - return dtype in (DType.FP32, DType.FP16) + return dtype in (DType.FP32, DType.FP16, DType.SHAPE) def getOpNameFromOpListName(opName): -- cgit v1.2.1