blob: c24a3696ffae4e3dfc757950153de9032ddb2d05 [file] [log] [blame]
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +01001// Copyright (c) 2023, ARM Limited.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14#include "generate.h"
15
16#include <doctest.h>
17
18#include <array>
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010019#include <sstream>
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +010020#include <string>
21#include <vector>
22
Jeremy Johnson59b307d2023-10-04 14:17:26 +010023namespace
24{
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010025void update_json_template(std::string& str, const std::string& find, const std::string& change)
Jeremy Johnson59b307d2023-10-04 14:17:26 +010026{
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010027 // Update the 'str' by looking for instances of 'find' and replacing them with 'change'
28 auto pos = str.find(find);
Jeremy Johnson59b307d2023-10-04 14:17:26 +010029 while (pos != std::string::npos)
30 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010031 str.replace(pos, find.length(), change);
Jeremy Johnson59b307d2023-10-04 14:17:26 +010032 pos = str.find(find);
33 }
34}
35
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010036void check_value(bool match, uint32_t result, uint32_t expected, uint32_t idx)
37{
38 std::stringstream msg;
39 msg << "index: " << idx << " expected: " << std::hex << expected << " got: " << result;
40 if (match)
41 {
42 REQUIRE_MESSAGE(expected == result, msg.str());
43 }
44 else
45 {
46 REQUIRE_MESSAGE(expected != result, msg.str());
47 }
48}
49
Jeremy Johnson59b307d2023-10-04 14:17:26 +010050template <typename T>
51void check_output(const std::vector<T>& results, const std::vector<uint32_t>& expected)
52{
53 for (size_t idx = 0; idx < expected.size(); ++idx)
54 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010055 check_value(true, *(uint32_t*)&results[idx], expected[idx], idx);
Jeremy Johnson59b307d2023-10-04 14:17:26 +010056 }
57}
58
Jeremy Johnsond41feb72023-10-12 16:03:15 +010059template <typename T>
60void check_output(const std::vector<T>& results, const std::vector<T>& expected)
61{
62 for (size_t idx = 0; idx < expected.size(); ++idx)
63 {
64 check_value(true, *(uint32_t*)&results[idx], *(uint32_t*)&expected[idx], idx);
65 }
66}
67
68template <typename T>
69void check_not_output(const std::vector<T>& results, const std::vector<T>& expected)
70{
71 for (size_t idx = 0; idx < expected.size(); ++idx)
72 {
73 check_value(false, *(uint32_t*)&results[idx], *(uint32_t*)&expected[idx], idx);
74 }
75}
76
Jeremy Johnson59b307d2023-10-04 14:17:26 +010077} // namespace
78
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +010079TEST_SUITE_BEGIN("generate");
80
81TEST_CASE("negative - api")
82{
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010083 std::string templateJsonCfg = R"({
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +010084 "tensors" : {
85 "in1" : {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010086 "generator": "_GENERATOR_",
87 "data_type": "_TYPE_",
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +010088 "input_type": "VARIABLE",
89 "shape" : [ 4, 8, 8 ],
90 "input_pos": 0,
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010091 "op" : "_OP_",
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +010092 "dot_product_info": {
93 "s": 0,
Jeremy Johnson59b307d2023-10-04 14:17:26 +010094 "ks": 8,
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010095 "acc_type": "_TYPE_"
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +010096 }
97 }
98 }
99 })";
100
101 const std::string tosaName = "in1";
102 const size_t tosaElements = 4 * 8 * 8;
103 const size_t tosaSize = tosaElements * 4;
104
105 SUBCASE("missing input")
106 {
107 REQUIRE_FALSE(tgd_generate_data(NULL, NULL, NULL, 0));
108 }
109 SUBCASE("invalid json")
110 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100111 std::string invalidJsonCfg = R"({
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100112 "tensors" : {
113 "in1" : {
114 "generator": DOT_PRODUCT,
115 },
116 }
117 })";
118
119 std::vector<float> buffer(tosaElements);
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100120 REQUIRE_FALSE(tgd_generate_data(invalidJsonCfg.c_str(), tosaName.c_str(), (void*)buffer.data(), tosaSize));
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100121 }
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100122 SUBCASE("unknown generator")
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100123 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100124 std::string jsonCfg = templateJsonCfg;
125 update_json_template(jsonCfg, "_GENERATOR_", "SOLAR");
126 update_json_template(jsonCfg, "_TYPE_", "FP32");
127 update_json_template(jsonCfg, "_OP_", "MATMUL");
128 std::vector<float> buffer(tosaElements);
129 REQUIRE_FALSE(tgd_generate_data(jsonCfg.c_str(), tosaName.c_str(), (void*)buffer.data(), tosaSize));
130 }
131 SUBCASE("unknown op")
132 {
133 std::string jsonCfg = templateJsonCfg;
134 update_json_template(jsonCfg, "_GENERATOR_", "DOT_PRODUCT");
135 update_json_template(jsonCfg, "_TYPE_", "FP32");
136 update_json_template(jsonCfg, "_OP_", "GREEN");
137
138 std::vector<float> buffer(tosaElements);
139 REQUIRE_FALSE(tgd_generate_data(jsonCfg.c_str(), tosaName.c_str(), (void*)buffer.data(), tosaSize));
140 }
141 SUBCASE("unknown type")
142 {
143 std::string jsonCfg = templateJsonCfg;
144 update_json_template(jsonCfg, "_GENERATOR_", "DOT_PRODUCT");
145 update_json_template(jsonCfg, "_TYPE_", "WATT");
146 update_json_template(jsonCfg, "_OP_", "MATMUL");
147
148 std::vector<float> buffer(tosaElements);
149 REQUIRE_FALSE(tgd_generate_data(jsonCfg.c_str(), tosaName.c_str(), (void*)buffer.data(), tosaSize));
150 }
151 SUBCASE("mismatching name")
152 {
153 std::string jsonCfg = templateJsonCfg;
154 update_json_template(jsonCfg, "_GENERATOR_", "DOT_PRODUCT");
155 update_json_template(jsonCfg, "_TYPE_", "FP32");
156 update_json_template(jsonCfg, "_OP_", "MATMUL");
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100157 std::string invalidName = "notFound1";
158
159 std::vector<float> buffer(tosaElements);
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100160 REQUIRE_FALSE(tgd_generate_data(jsonCfg.c_str(), invalidName.c_str(), (void*)buffer.data(), tosaSize));
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100161 }
162 SUBCASE("mismatching size")
163 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100164 std::string jsonCfg = templateJsonCfg;
165 update_json_template(jsonCfg, "_GENERATOR_", "DOT_PRODUCT");
166 update_json_template(jsonCfg, "_TYPE_", "FP32");
167 update_json_template(jsonCfg, "_OP_", "MATMUL");
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100168 size_t smallElements = 4 * 8 * 7;
169 size_t smallSize = smallElements * 4;
170
171 std::vector<float> buffer(smallElements);
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100172 REQUIRE_FALSE(tgd_generate_data(jsonCfg.c_str(), tosaName.c_str(), (void*)buffer.data(), smallSize));
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100173 }
174}
175
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100176void matmul_test_FP32(const std::string tosaName[2],
177 const size_t tosaElements[2],
178 const std::string templateJsonCfg,
179 const std::string setStr,
180 int32_t param,
181 const std::vector<uint32_t> expected)
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100182{
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100183 std::string jsonCfg = templateJsonCfg;
184 update_json_template(jsonCfg, "_SET_", setStr);
185 std::vector<float> buffer(tosaElements[param]);
186 REQUIRE(tgd_generate_data(jsonCfg.c_str(), tosaName[param].c_str(), (void*)buffer.data(), tosaElements[param] * 4));
187 check_output<float>(buffer, expected);
188}
189
190TEST_CASE("positive - FP32 matmul dot product (first 3 values)")
191{
192 std::string templateJsonCfg = R"({
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100193 "tensors" : {
194 "in1" : {
195 "generator": "DOT_PRODUCT",
196 "data_type": "FP32",
197 "input_type": "VARIABLE",
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100198 "shape" : [ 4, 8, 2 ],
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100199 "input_pos": 0,
200 "op" : "MATMUL",
201 "dot_product_info": {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100202 "s": _SET_,
203 "ks": 2,
204 "acc_type": "FP32"
205 }
206 },
207 "in2" : {
208 "generator": "DOT_PRODUCT",
209 "data_type": "FP32",
210 "input_type": "VARIABLE",
211 "shape" : [ 4, 2, 5 ],
212 "input_pos": 1,
213 "op" : "MATMUL",
214 "dot_product_info": {
215 "s": _SET_,
216 "ks": 2,
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100217 "acc_type": "FP32"
218 }
219 }
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100220
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100221 }
222 })";
223
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100224 const std::string tosaName[2] = { "in1", "in2" };
225 const size_t tosaElements[2] = { (4 * 8 * 2), (4 * 2 * 5) };
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100226
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100227 SUBCASE("matmul, set 0, param 0")
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100228 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100229 std::vector<uint32_t> expected = { 0xbf665aa4, 0xbf736bd3, 0x0 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100230 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "0", 0, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100231 }
232 SUBCASE("matmul, set 0, param 1")
233 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100234 std::vector<uint32_t> expected = { 0x0, 0x0, 0x3f34f2dd };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100235 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "0", 1, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100236 }
237 SUBCASE("matmul, set 1, param 0")
238 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100239 std::vector<uint32_t> expected = { 0x5e97f1b0, 0x5ea6a18e, 0x5eb811af };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100240 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "1", 0, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100241 }
242 SUBCASE("matmul, set 1, param 1")
243 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100244 std::vector<uint32_t> expected = { 0x5f128bb1, 0x5ef54579, 0x5ebd65b8 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100245 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "1", 1, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100246 }
247 SUBCASE("matmul, set 2, param 0")
248 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100249 std::vector<uint32_t> expected = { 0x3f800000, 0x3e66ed53, 0x3f800000 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100250 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "2", 0, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100251 }
252 SUBCASE("matmul, set 2, param 1")
253 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100254 std::vector<uint32_t> expected = { 0x3f800000, 0x3f800000, 0x3f800000 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100255 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "2", 1, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100256 }
257 SUBCASE("matmul, set 3, param 0")
258 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100259 // NOTE: Python test script produced 0xbf256686 - so off by 1
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100260 std::vector<uint32_t> expected = { 0x41800000, 0xbf256685, 0x41800000 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100261 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "3", 0, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100262 }
263 SUBCASE("matmul, set 3, param 1")
264 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100265 std::vector<uint32_t> expected = { 0x41800000, 0x41800000, 0x41800000 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100266 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "3", 1, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100267 }
268 SUBCASE("matmul, set 4, param 0")
269 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100270 std::vector<uint32_t> expected = { 0x0, 0x3f000000, 0x5f14e80c };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100271 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "4", 0, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100272 }
273 SUBCASE("matmul, set 4, param 1")
274 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100275 std::vector<uint32_t> expected = { 0x5d5d0db2, 0xdf2c82a8, 0x0 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100276 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "4", 1, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100277 }
278 SUBCASE("matmul, set 5, param 0")
279 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100280 std::vector<uint32_t> expected = { 0x5df6c4b3, 0x5e6b4088, 0x5ed0fe71 };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100281 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "5", 0, expected);
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100282 }
283 SUBCASE("matmul, set 5, param 1")
284 {
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100285 std::vector<uint32_t> expected = { 0xde086d85, 0x5e630878, 0x5eba5c7b };
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100286 matmul_test_FP32(tosaName, tosaElements, templateJsonCfg, "5", 1, expected);
Jeremy Johnsonb20b0c92023-10-04 14:17:55 +0100287 }
288}
Jeremy Johnsond41feb72023-10-12 16:03:15 +0100289TEST_CASE("positive - pseudo random")
290{
291 std::string templateJsonCfg = R"({
292 "tensors" : {
293 "input0" : {
294 "generator": "PSEUDO_RANDOM",
295 "data_type": "FP32",
296 "input_type": "VARIABLE",
297 "shape" : [ 12, 3 ],
298 "input_pos": 0,
299 "op" : "PAD",
300 "pseudo_random_info": {
301 "rng_seed": _SEED0_
302 }
303 },
304 "input1" : {
305 "generator": "PSEUDO_RANDOM",
306 "data_type": "FP32",
307 "input_type": "VARIABLE",
308 "shape" : [ 1, 3 ],
309 "input_pos": 1,
310 "op" : "PAD",
311 "pseudo_random_info": {
312 "rng_seed": _SEED1_
313 }
314 }
315
316 }
317 })";
318
319 const std::string tosaNameP0 = "input0";
320 const size_t tosaElementsP0 = 12 * 3;
321 const std::string tosaNameP1 = "input1";
322 const size_t tosaElementsP1 = 1 * 3;
323
324 SUBCASE("pad - same rng")
325 {
326 std::string jsonCfg = templateJsonCfg;
327 update_json_template(jsonCfg, "_SEED0_", "0");
328 update_json_template(jsonCfg, "_SEED1_", "0");
329
330 std::vector<float> bufferP0(tosaElementsP0);
331 std::vector<float> bufferP1(tosaElementsP1);
332 REQUIRE(tgd_generate_data(jsonCfg.c_str(), tosaNameP0.c_str(), (void*)bufferP0.data(), tosaElementsP0 * 4));
333 REQUIRE(tgd_generate_data(jsonCfg.c_str(), tosaNameP1.c_str(), (void*)bufferP1.data(), tosaElementsP1 * 4));
334 check_output<float>(bufferP0, bufferP1);
335 }
336
337 SUBCASE("pad - different rng")
338 {
339 std::string jsonCfg = templateJsonCfg;
340 update_json_template(jsonCfg, "_SEED0_", "0");
341 update_json_template(jsonCfg, "_SEED1_", "1000");
342
343 std::vector<float> bufferP0(tosaElementsP0);
344 std::vector<float> bufferP1(tosaElementsP1);
345 REQUIRE(tgd_generate_data(jsonCfg.c_str(), tosaNameP0.c_str(), (void*)bufferP0.data(), tosaElementsP0 * 4));
346 REQUIRE(tgd_generate_data(jsonCfg.c_str(), tosaNameP1.c_str(), (void*)bufferP1.data(), tosaElementsP1 * 4));
347 check_not_output<float>(bufferP0, bufferP1);
348 }
349}
Jeremy Johnson59b307d2023-10-04 14:17:26 +0100350TEST_SUITE_END(); // generate