blob: 99cb0c1f9bfc05681fa11e394b3fca504822d270 [file] [log] [blame]
Georgios Pinitas7021ef02023-08-22 08:25:57 +01001
2// Copyright (c) 2023, ARM Limited.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#include "verify_utils.h"
17
18#include <nlohmann/json.hpp>
19
20#include <algorithm>
21#include <map>
22
23namespace tosa
24{
25
26NLOHMANN_JSON_SERIALIZE_ENUM(DType,
27 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010028 { DType::DType_UNKNOWN, "UNKNOWN" },
Georgios Pinitas7021ef02023-08-22 08:25:57 +010029 { DType::DType_BOOL, "BOOL" },
30 { DType::DType_INT4, "INT4" },
31 { DType::DType_INT8, "INT8" },
32 { DType::DType_INT16, "INT16" },
33 { DType::DType_INT32, "INT32" },
34 { DType::DType_INT48, "INT48" },
35 { DType::DType_FP16, "FP16" },
36 { DType::DType_BF16, "BF16" },
37 { DType::DType_FP32, "FP32" },
38 })
39
40} // namespace tosa
41
42namespace TosaReference
43{
44
45NLOHMANN_JSON_SERIALIZE_ENUM(VerifyMode,
46 {
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010047 { VerifyMode::Unknown, "UNKNOWN" },
Georgios Pinitas7021ef02023-08-22 08:25:57 +010048 { VerifyMode::Exact, "EXACT" },
49 { VerifyMode::Ulp, "ULP" },
50 { VerifyMode::DotProduct, "DOT_PRODUCT" },
51 { VerifyMode::ReduceProduct, "REDUCE_PRODUCT" },
52 { VerifyMode::FpSpecial, "FP_SPECIAL" },
53 })
54
55void from_json(const nlohmann::json& j, UlpInfo& ulpInfo)
56{
57 j.at("ulp").get_to(ulpInfo.ulp);
58}
59
60void from_json(const nlohmann::json& j, DotProductVerifyInfo& dotProductInfo)
61{
Georgios Pinitas7021ef02023-08-22 08:25:57 +010062 j.at("s").get_to(dotProductInfo.s);
63 j.at("ks").get_to(dotProductInfo.ks);
64}
65
Jack Frankland12ee1a72023-09-20 09:08:34 +010066void from_json(const nlohmann::json& j, ReduceProductVerifyInfo& reduceProduceInfo)
67{
68 j.at("m").get_to(reduceProduceInfo.m);
69 j.at("n").get_to(reduceProduceInfo.n);
70}
71
Georgios Pinitas7021ef02023-08-22 08:25:57 +010072void from_json(const nlohmann::json& j, VerifyConfig& cfg)
73{
74 j.at("mode").get_to(cfg.mode);
Jeremy Johnsonbb0935f2023-09-14 16:43:48 +010075 j.at("data_type").get_to(cfg.dataType);
Georgios Pinitas7021ef02023-08-22 08:25:57 +010076 if (j.contains("ulp_info"))
77 {
78 j.at("ulp_info").get_to(cfg.ulpInfo);
79 }
80 if (j.contains("dot_product_info"))
81 {
82 j.at("dot_product_info").get_to(cfg.dotProductInfo);
83 }
Jack Frankland12ee1a72023-09-20 09:08:34 +010084 if (j.contains("reduce_product_info"))
85 {
86 j.at("reduce_product_info").get_to(cfg.reduceProductInfo);
87 }
Georgios Pinitas7021ef02023-08-22 08:25:57 +010088}
89
90std::optional<VerifyConfig> parseVerifyConfig(const char* tensorName, const char* json)
91{
92 if (!tensorName)
93 return std::nullopt;
94
95 auto jsonCfg = nlohmann::json::parse(json, nullptr, /* allow exceptions */ false);
96
97 if (jsonCfg.is_discarded())
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +010098 {
99 WARNING("[Verifier] Invalid json config.");
Georgios Pinitas7021ef02023-08-22 08:25:57 +0100100 return std::nullopt;
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100101 }
Georgios Pinitas7021ef02023-08-22 08:25:57 +0100102 if (!jsonCfg.contains("tensors"))
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100103 {
104 WARNING("[Verifier] Missing tensors in json config.");
Georgios Pinitas7021ef02023-08-22 08:25:57 +0100105 return std::nullopt;
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100106 }
Georgios Pinitas7021ef02023-08-22 08:25:57 +0100107
108 const auto& tensors = jsonCfg["tensors"];
109 if (!tensors.contains(tensorName))
Jeremy Johnsonfc5e34e2023-10-24 14:45:12 +0100110 if (!tensors.contains(tensorName))
111 {
112 WARNING("[Verifier] Missing tensor %s in json config.", tensorName);
113 return std::nullopt;
114 }
Georgios Pinitas7021ef02023-08-22 08:25:57 +0100115 const auto& namedTensor = tensors[tensorName];
116 return namedTensor.get<VerifyConfig>();
117}
118
119int64_t numElements(const std::vector<int32_t>& shape)
120{
121 return std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<int64_t>());
122}
123
124DType mapToDType(tosa_datatype_t dataType)
125{
126 static std::map<tosa_datatype_t, DType> typeMap = {
127 { tosa_datatype_bool_t, DType_BOOL }, { tosa_datatype_int4_t, DType_INT4 },
128 { tosa_datatype_int8_t, DType_INT8 }, { tosa_datatype_uint16_t, DType_UINT16 },
129 { tosa_datatype_int16_t, DType_INT16 }, { tosa_datatype_int32_t, DType_INT32 },
130 { tosa_datatype_int48_t, DType_INT48 }, { tosa_datatype_fp16_t, DType_FP16 },
131 { tosa_datatype_bf16_t, DType_BF16 }, { tosa_datatype_fp32_t, DType_FP32 },
132 { tosa_datatype_shape_t, DType_SHAPE },
133 };
134
135 if (typeMap.count(dataType))
136 {
137 return typeMap[dataType];
138 }
139
140 return DType_UNKNOWN;
141}
Jeremy Johnsond1a08ce2023-10-18 17:22:21 +0100142
143// Like const_exp2 but for use during runtime
144double exp2(int32_t n)
145{
Jeremy Johnsona4d907e2023-10-26 13:53:14 +0100146 TOSA_REF_REQUIRE(-1022 <= n && n <= 1023, " Invalid exponent value (%d) in exp2", n);
Jeremy Johnsond1a08ce2023-10-18 17:22:21 +0100147 return const_exp2(n);
148}
Jeremy Johnsona4d907e2023-10-26 13:53:14 +0100149
150int32_t ilog2(double v)
151{
152 TOSA_REF_REQUIRE(0.0 < v && v < std::numeric_limits<double>::infinity(), " Value out of range (%g) in ilog2", v);
153 int32_t n = 0;
154 while (v >= 2.0)
155 {
156 v = v / 2.0;
157 n++;
158 }
159 while (v < 1.0)
160 {
161 v = v * 2.0;
162 n--;
163 }
164 return n;
165}
Georgios Pinitas7021ef02023-08-22 08:25:57 +0100166} // namespace TosaReference