blob: 776fbf3415e1af03618c23e3771ad58ba36bd720 [file] [log] [blame]
Eric Kunzee5e26762020-10-13 16:11:07 -07001
Jared Smolens62a7b7f2022-03-19 05:42:27 +00002// Copyright (c) 2020-2022, ARM Limited.
Eric Kunzee5e26762020-10-13 16:11:07 -07003//
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
Matthew Sloyanba5fad32022-09-26 13:31:43 +010016#include "model_runner.h"
17#include "version.h"
Eric Kunzee5e26762020-10-13 16:11:07 -070018
Matthew Sloyanba5fad32022-09-26 13:31:43 +010019#include "command_line_utils.h"
Eric Kunzee5e26762020-10-13 16:11:07 -070020#include "ops/op_factory.h"
21#include "subgraph_traverser.h"
22#include "tosa_serialization_handler.h"
Eric Kunzee5e26762020-10-13 16:11:07 -070023
Kevin Chengcd79f0e2021-06-03 15:00:34 -070024#include <fstream>
Matthew Sloyanba5fad32022-09-26 13:31:43 +010025#include <iostream>
26#include <stdio.h>
27#include <Eigen/CXX11/Tensor>
Kevin Chengcd79f0e2021-06-03 15:00:34 -070028#include <nlohmann/json.hpp>
29
Eric Kunzee5e26762020-10-13 16:11:07 -070030using namespace TosaReference;
31using namespace tosa;
Kevin Chengcd79f0e2021-06-03 15:00:34 -070032using json = nlohmann::json;
Eric Kunzee5e26762020-10-13 16:11:07 -070033
Kevin Chengcd79f0e2021-06-03 15:00:34 -070034int initTestDesc(json& test_desc);
35int readInputTensors(SubgraphTraverser& gt, json test_desc);
36int writeFinalTensors(SubgraphTraverser& gt, json test_desc);
37int loadGraph(TosaSerializationHandler& tsh, json test_desc);
Eric Kunzee5e26762020-10-13 16:11:07 -070038
Eric Kunze286f8342022-06-22 11:30:23 -070039int main(int argc, char** argv)
Eric Kunzee5e26762020-10-13 16:11:07 -070040{
Matthew Sloyanba5fad32022-09-26 13:31:43 +010041 TosaVersion model_version(TOSA_REFERENCE_MODEL_VERSION_MAJOR,
42 TOSA_REFERENCE_MODEL_VERSION_MINOR,
43 TOSA_REFERENCE_MODEL_VERSION_PATCH,
44 TOSA_REFERENCE_MODEL_VERSION_DRAFT);
Kevin Cheng10096742021-10-20 19:51:41 +000045
Eric Kunzee5e26762020-10-13 16:11:07 -070046 // Initialize configuration and debug subsystems
Eric Kunze286f8342022-06-22 11:30:23 -070047 g_func_debug.init_debug(0);
Eric Kunzee5e26762020-10-13 16:11:07 -070048
Eric Kunze286f8342022-06-22 11:30:23 -070049 if (func_model_parse_cmd_line(g_func_config, g_func_debug, argc, argv, model_version.to_string().c_str()))
Eric Kunzee5e26762020-10-13 16:11:07 -070050 {
51 return 1;
52 }
53
Kevin Cheng10096742021-10-20 19:51:41 +000054 TosaSerializationHandler tsh;
55 TosaVersion::compat_t is_compat = model_version.is_compatible(tsh.GetVersion());
56 switch (is_compat)
57 {
58 case TosaVersion::compat_t::COMPLETELY_COMPATIBLE:
59 break;
60 case TosaVersion::compat_t::PARTIALLY_COMPATIBLE:
61 printf("WARNING: Reference model version %s is partially compatible with serializer version %s\n",
62 model_version.to_string().c_str(), tsh.GetVersion().to_string().c_str());
63 break;
64 case TosaVersion::compat_t::NOT_COMPATIBLE:
65 printf("ERROR: Reference model version %s is not compatible with serializer version %s\n",
66 model_version.to_string().c_str(), tsh.GetVersion().to_string().c_str());
67 return TOSA_VERSION_MISMATCH;
68 }
69
Kevin Chengcd79f0e2021-06-03 15:00:34 -070070 json test_desc;
71
72 // Initialize test descriptor
73 if (initTestDesc(test_desc))
74 {
Kevin Cheng903763c2021-09-28 16:14:52 -070075 FATAL_ERROR("Unable to load test json");
Kevin Chengcd79f0e2021-06-03 15:00:34 -070076 }
77
78 if (loadGraph(tsh, test_desc))
Eric Kunzee5e26762020-10-13 16:11:07 -070079 {
Kevin Cheng903763c2021-09-28 16:14:52 -070080 FATAL_ERROR("Unable to load graph");
Eric Kunzee5e26762020-10-13 16:11:07 -070081 }
82
Eric Kunzee5e26762020-10-13 16:11:07 -070083 SubgraphTraverser main_gt(tsh.GetMainBlock(), &tsh);
84
85 if (main_gt.initializeGraph())
86 {
Kevin Chengacb550f2021-06-29 15:32:19 -070087 WARNING("Unable to initialize main graph traverser.");
88 goto done;
Eric Kunzee5e26762020-10-13 16:11:07 -070089 }
90
91 if (main_gt.linkTensorsAndNodes())
92 {
Kevin Cheng903763c2021-09-28 16:14:52 -070093 WARNING("Failed to link tensors and nodes");
94 goto done;
Eric Kunzee5e26762020-10-13 16:11:07 -070095 }
96
97 if (main_gt.validateGraph())
98 {
Kevin Cheng6097c3d2021-09-23 15:25:24 -070099 WARNING("Failed to validate graph. Evaluation aborted.");
Kevin Cheng6097c3d2021-09-23 15:25:24 -0700100 goto done;
Eric Kunzee5e26762020-10-13 16:11:07 -0700101 }
102
Kevin Chengcc61be32021-10-14 17:09:57 -0700103 if (main_gt.allocateTensor())
104 {
105 WARNING("Failed to allocate tensor. Evaluation aborted.");
106 goto done;
107 }
108
Eric Kunzee5e26762020-10-13 16:11:07 -0700109 if (g_func_config.validate_only)
110 {
111 goto done;
112 }
113
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700114 if (readInputTensors(main_gt, test_desc))
Eric Kunzee5e26762020-10-13 16:11:07 -0700115 {
Kevin Cheng903763c2021-09-28 16:14:52 -0700116 FATAL_ERROR("Unable to read input tensors");
Eric Kunzee5e26762020-10-13 16:11:07 -0700117 }
118
119 if (g_func_config.eval)
120 {
121
Kevin Chengacb550f2021-06-29 15:32:19 -0700122 // evaluateAll() returns 1 if graph evaluation is forced to be terminated earlier.
Eric Kunzee5e26762020-10-13 16:11:07 -0700123 if (main_gt.evaluateAll())
124 {
Kevin Chengacb550f2021-06-29 15:32:19 -0700125 ASSERT_MSG(main_gt.getGraphStatus() != GraphStatus::TOSA_VALID,
126 "Upon evaluateAll() returning 1, graph can not be VALID.");
127 }
128 else
129 {
130 ASSERT_MSG(main_gt.getGraphStatus() == GraphStatus::TOSA_VALID ||
131 main_gt.getGraphStatus() == GraphStatus::TOSA_UNPREDICTABLE,
132 "Upon evaluateAll() returning 0, graph can only be VALID/UNPREDICTABLE.");
Eric Kunzee5e26762020-10-13 16:11:07 -0700133 }
134
Kevin Chengacb550f2021-06-29 15:32:19 -0700135 // Only generate output tensor if graph is valid.
136 if (main_gt.getGraphStatus() == GraphStatus::TOSA_VALID)
Eric Kunzee5e26762020-10-13 16:11:07 -0700137 {
Kevin Chengacb550f2021-06-29 15:32:19 -0700138 // make sure output tensor is evaluated and show its value
139 int num_output_tensors = main_gt.getNumOutputTensors();
140 bool all_output_valid = true;
141 for (int i = 0; i < num_output_tensors; i++)
Eric Kunzee5e26762020-10-13 16:11:07 -0700142 {
Kevin Chengacb550f2021-06-29 15:32:19 -0700143 const Tensor* ct = main_gt.getOutputTensor(i);
144 ASSERT_MEM(ct);
145 if (!ct->getIsValid())
Eric Kunzee5e26762020-10-13 16:11:07 -0700146 {
Kevin Chengacb550f2021-06-29 15:32:19 -0700147 ct->dumpTensorParams(g_func_debug.func_debug_file);
148 if (DEBUG_ENABLED(DEBUG_VERB_HIGH, GT))
149 {
150 ct->dumpTensor(g_func_debug.func_debug_file);
151 }
152 all_output_valid = false;
Eric Kunzee5e26762020-10-13 16:11:07 -0700153 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700154 }
Kevin Chengacb550f2021-06-29 15:32:19 -0700155 if (!all_output_valid)
Eric Kunzee5e26762020-10-13 16:11:07 -0700156 {
Kevin Chengacb550f2021-06-29 15:32:19 -0700157 main_gt.dumpGraph(g_func_debug.func_debug_file);
Kevin Cheng903763c2021-09-28 16:14:52 -0700158 FATAL_ERROR(
Kevin Chengacb550f2021-06-29 15:32:19 -0700159 "SubgraphTraverser \"main\" error: Output tensors are not all valid at the end of evaluation.");
160 }
161
162 if (g_func_config.output_tensors)
163 {
164 if (writeFinalTensors(main_gt, test_desc))
165 {
166 WARNING("Errors encountered in saving output tensors");
167 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700168 }
169 }
170 }
171
172done:
Kevin Chengacb550f2021-06-29 15:32:19 -0700173 switch (main_gt.getGraphStatus())
174 {
175 case GraphStatus::TOSA_VALID:
176 // Result is valid.
177 break;
178 case GraphStatus::TOSA_UNPREDICTABLE:
179 fprintf(stderr, "Graph result: UNPREDICTABLE.\n");
180 break;
181 case GraphStatus::TOSA_ERROR:
182 fprintf(stderr, "Graph result: ERROR.\n");
183 break;
184 default:
185 fprintf(stderr, "Unknown graph status code=%d.\n", (int)main_gt.getGraphStatus());
186 }
187
Eric Kunze286f8342022-06-22 11:30:23 -0700188 g_func_debug.fini_debug();
Eric Kunzee5e26762020-10-13 16:11:07 -0700189
Kevin Chengacb550f2021-06-29 15:32:19 -0700190 return (int)main_gt.getGraphStatus();
Eric Kunzee5e26762020-10-13 16:11:07 -0700191}
192
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700193int loadGraph(TosaSerializationHandler& tsh, json test_desc)
Eric Kunzee5e26762020-10-13 16:11:07 -0700194{
195 char graph_fullname[1024];
196
Eric Kunze286f8342022-06-22 11:30:23 -0700197 snprintf(graph_fullname, sizeof(graph_fullname), "%s/%s", g_func_config.flatbuffer_dir.c_str(),
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700198 test_desc["tosa_file"].get<std::string>().c_str());
Eric Kunzee5e26762020-10-13 16:11:07 -0700199
200 if (strlen(graph_fullname) <= 2)
201 {
Kevin Cheng903763c2021-09-28 16:14:52 -0700202 FATAL_ERROR("Missing required argument: Check \"tosa_file\" in .json specified by -Ctosa_desc=");
Eric Kunzee5e26762020-10-13 16:11:07 -0700203 }
204
205 const char JSON_EXT[] = ".json";
206 int is_json = 0;
207 {
208 // look for JSON file extension
209 size_t suffix_len = strlen(JSON_EXT);
210 size_t str_len = strlen(graph_fullname);
211
212 if (str_len > suffix_len && strncasecmp(graph_fullname + (str_len - suffix_len), JSON_EXT, suffix_len) == 0)
213 {
214 is_json = 1;
215 }
216 }
217
218 if (is_json)
219 {
Eric Kunze286f8342022-06-22 11:30:23 -0700220 if (tsh.LoadFileSchema(g_func_config.operator_fbs.c_str()))
Eric Kunzee5e26762020-10-13 16:11:07 -0700221 {
Kevin Cheng903763c2021-09-28 16:14:52 -0700222 FATAL_ERROR("\nJSON file detected. Unable to load TOSA flatbuffer schema from: %s\nCheck -Coperator_fbs=",
Eric Kunze286f8342022-06-22 11:30:23 -0700223 g_func_config.operator_fbs.c_str());
Eric Kunzee5e26762020-10-13 16:11:07 -0700224 }
225
226 if (tsh.LoadFileJson(graph_fullname))
227 {
Kevin Cheng903763c2021-09-28 16:14:52 -0700228 FATAL_ERROR("\nError loading JSON graph file: %s\nCheck -Ctest_desc=, -Ctosa_file= and -Cflatbuffer_dir=",
229 graph_fullname);
Eric Kunzee5e26762020-10-13 16:11:07 -0700230 }
231 }
232 else
233 {
234 if (tsh.LoadFileTosaFlatbuffer(graph_fullname))
235 {
Kevin Cheng903763c2021-09-28 16:14:52 -0700236 FATAL_ERROR(
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700237 "\nError loading TOSA flatbuffer file: %s\nCheck -Ctest_desc=, -Ctosa_file= and -Cflatbuffer_dir=",
238 graph_fullname);
Eric Kunzee5e26762020-10-13 16:11:07 -0700239 }
240 }
241
242 return 0;
243}
244
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700245int readInputTensors(SubgraphTraverser& gt, json test_desc)
Eric Kunzee5e26762020-10-13 16:11:07 -0700246{
247 int tensorCount = gt.getNumInputTensors();
248 Tensor* tensor;
249 char filename[1024];
250
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700251 try
Eric Kunzee5e26762020-10-13 16:11:07 -0700252 {
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700253 if ((tensorCount != (int)test_desc["ifm_name"].size()) || (tensorCount != (int)test_desc["ifm_file"].size()))
Eric Kunzee5e26762020-10-13 16:11:07 -0700254 {
Eric Kunze286f8342022-06-22 11:30:23 -0700255 WARNING("Number of input tensors(%d) doesn't match name(%ld)/file(%ld) in test descriptor.", tensorCount,
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700256 test_desc["ifm_name"].size(), test_desc["ifm_file"].size());
Eric Kunzee5e26762020-10-13 16:11:07 -0700257 return 1;
258 }
259
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700260 for (int i = 0; i < tensorCount; i++)
Eric Kunzee5e26762020-10-13 16:11:07 -0700261 {
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700262 tensor = gt.getInputTensorByName(test_desc["ifm_name"][i].get<std::string>());
263 if (!tensor)
Eric Kunzee5e26762020-10-13 16:11:07 -0700264 {
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700265 WARNING("Unable to find input tensor %s", test_desc["ifm_name"][i].get<std::string>().c_str());
266 return 1;
267 }
268
Eric Kunze286f8342022-06-22 11:30:23 -0700269 snprintf(filename, sizeof(filename), "%s/%s", g_func_config.flatbuffer_dir.c_str(),
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700270 test_desc["ifm_file"][i].get<std::string>().c_str());
271
272 DEBUG_MED(GT, "Loading input tensor %s from filename: %s", tensor->getName().c_str(), filename);
273
Kevin Chengcc61be32021-10-14 17:09:57 -0700274 if (!tensor->is_allocated())
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700275 {
Kevin Chengcc61be32021-10-14 17:09:57 -0700276 WARNING("Tensor %s is not allocated before being initialized", tensor->getName().c_str());
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700277 return 1;
278 }
279
280 if (tensor->readFromNpyFile(filename))
281 {
282 WARNING("Unable to read input tensor %s from filename: %s", tensor->getName().c_str(), filename);
283 tensor->dumpTensorParams(g_func_debug.func_debug_file);
284 return 1;
285 }
286
287 // Push ready consumers to the next node list
288 for (auto gn : tensor->getConsumers())
289 {
290 if (gn->hasAllInputsReady() && !gn->getOnNextNodeList())
291 {
292 gt.addToNextNodeList(gn);
293 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700294 }
295 }
296 }
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700297 catch (nlohmann::json::type_error& e)
298 {
299 WARNING("Fail accessing test descriptor: %s", e.what());
300 return 1;
301 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700302
303 if (DEBUG_ENABLED(DEBUG_VERB_HIGH, GT))
304 {
305 gt.dumpNextNodeList(g_func_debug.func_debug_file);
306 }
307
308 return 0;
309}
310
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700311int writeFinalTensors(SubgraphTraverser& gt, json test_desc)
Eric Kunzee5e26762020-10-13 16:11:07 -0700312{
313 int tensorCount = gt.getNumOutputTensors();
314 const Tensor* tensor;
315 char filename[1024];
316
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700317 try
Eric Kunzee5e26762020-10-13 16:11:07 -0700318 {
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700319 if ((tensorCount != (int)test_desc["ofm_name"].size()) || (tensorCount != (int)test_desc["ofm_file"].size()))
Eric Kunzee5e26762020-10-13 16:11:07 -0700320 {
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700321 WARNING("Number of output tensors(%d) doesn't match name(%ld)/file(%ld) in test descriptor.", tensorCount,
322 test_desc["ofm_name"].size(), test_desc["ofm_file"].size());
Eric Kunzee5e26762020-10-13 16:11:07 -0700323 return 1;
324 }
325
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700326 for (int i = 0; i < tensorCount; i++)
Eric Kunzee5e26762020-10-13 16:11:07 -0700327 {
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700328 tensor = gt.getOutputTensorByName(test_desc["ofm_name"][i].get<std::string>());
329 if (!tensor)
330 {
331 WARNING("Unable to find output tensor %s", test_desc["ofm_name"][i].get<std::string>().c_str());
332 return 1;
333 }
334
Eric Kunze286f8342022-06-22 11:30:23 -0700335 snprintf(filename, sizeof(filename), "%s/%s", g_func_config.output_dir.c_str(),
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700336 test_desc["ofm_file"][i].get<std::string>().c_str());
337
338 DEBUG_MED(GT, "Writing output tensor[%d] %s to filename: %s", i, tensor->getName().c_str(), filename);
339
340 if (tensor->writeToNpyFile(filename))
341 {
342 WARNING("Unable to write output tensor[%d] %s to filename: %s", i, tensor->getName().c_str(), filename);
343 return 1;
344 }
345 }
346 }
347 catch (nlohmann::json::type_error& e)
348 {
349 WARNING("Fail accessing test descriptor: %s", e.what());
350 return 1;
351 }
352
353 return 0;
354}
355
356// Read "foo,bar,..." and return std::vector({foo, bar, ...})
357std::vector<std::string> parseFromString(std::string raw_str)
358{
359 bool last_pair = false;
360 std::string::size_type start = 0, end;
361 std::string name;
362
363 std::vector<std::string> result;
364 do
365 {
366 end = raw_str.find(',', start);
367 if (end == std::string::npos)
368 last_pair = true;
369
370 name = raw_str.substr(start, end);
371
372 result.push_back(name);
373
374 start = end + 1; // skip comma
375 } while (!last_pair);
376
377 return result;
378}
379
380int initTestDesc(json& test_desc)
381{
382 std::ifstream ifs(g_func_config.test_desc);
383
384 if (ifs.good())
385 {
386 try
387 {
388 test_desc = nlohmann::json::parse(ifs);
389 }
390 catch (nlohmann::json::parse_error& e)
391 {
392 WARNING("Error parsing test descriptor json: %s", e.what());
Eric Kunzee5e26762020-10-13 16:11:07 -0700393 return 1;
394 }
395 }
Jared Smolens62a7b7f2022-03-19 05:42:27 +0000396 else
397 {
Eric Kunze286f8342022-06-22 11:30:23 -0700398 WARNING("Cannot open input file: %s", g_func_config.test_desc.c_str());
Jared Smolens62a7b7f2022-03-19 05:42:27 +0000399 return 1;
400 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700401
Kevin Chengd5934142021-06-28 16:23:24 -0700402 // Overwrite flatbuffer_dir/output_dir with dirname(g_func_config.test_desc) if it's not specified.
Eric Kunze286f8342022-06-22 11:30:23 -0700403 if (g_func_config.flatbuffer_dir.empty() || g_func_config.output_dir.empty())
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700404 {
Eric Kunze286f8342022-06-22 11:30:23 -0700405 std::string test_dir = g_func_config.test_desc.substr(0, g_func_config.test_desc.find_last_of("/\\"));
406 if (g_func_config.flatbuffer_dir.empty())
Kevin Chengd5934142021-06-28 16:23:24 -0700407 {
Eric Kunze286f8342022-06-22 11:30:23 -0700408 g_func_config.flatbuffer_dir = test_dir;
Kevin Chengd5934142021-06-28 16:23:24 -0700409 }
Eric Kunze286f8342022-06-22 11:30:23 -0700410 if (g_func_config.output_dir.empty())
Kevin Chengd5934142021-06-28 16:23:24 -0700411 {
Eric Kunze286f8342022-06-22 11:30:23 -0700412 g_func_config.output_dir = test_dir;
Kevin Chengd5934142021-06-28 16:23:24 -0700413 }
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700414 }
415
416 // Overwrite test_desc["tosa_file"] if -Ctosa_file= specified.
Eric Kunze286f8342022-06-22 11:30:23 -0700417 if (!g_func_config.tosa_file.empty())
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700418 {
Eric Kunze286f8342022-06-22 11:30:23 -0700419 test_desc["tosa_file"] = g_func_config.tosa_file;
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700420 }
421
422 // Overwrite test_desc["ifm_name"] if -Cifm_name= specified.
Eric Kunze286f8342022-06-22 11:30:23 -0700423 if (!g_func_config.ifm_name.empty())
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700424 {
Eric Kunze286f8342022-06-22 11:30:23 -0700425 std::vector<std::string> ifm_name_vec = parseFromString(g_func_config.ifm_name);
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700426 test_desc["ifm_name"] = ifm_name_vec;
427 }
428
429 // Overwrite test_desc["ifm_file"] if -Cifm_file= specified.
Eric Kunze286f8342022-06-22 11:30:23 -0700430 if (!g_func_config.ifm_file.empty())
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700431 {
Eric Kunze286f8342022-06-22 11:30:23 -0700432 std::vector<std::string> ifm_file_vec = parseFromString(g_func_config.ifm_file);
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700433 test_desc["ifm_file"] = ifm_file_vec;
434 }
435
436 // Overwrite test_desc["ofm_name"] if -Cofm_name= specified.
Eric Kunze286f8342022-06-22 11:30:23 -0700437 if (!g_func_config.ofm_name.empty())
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700438 {
Eric Kunze286f8342022-06-22 11:30:23 -0700439 std::vector<std::string> ofm_name_vec = parseFromString(g_func_config.ofm_name);
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700440 test_desc["ofm_name"] = ofm_name_vec;
441 }
442
443 // Overwrite test_desc["ofm_file"] if -Cofm_file= specified.
Eric Kunze286f8342022-06-22 11:30:23 -0700444 if (!g_func_config.ofm_file.empty())
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700445 {
Eric Kunze286f8342022-06-22 11:30:23 -0700446 std::vector<std::string> ofm_file_vec = parseFromString(g_func_config.ofm_file);
Kevin Chengcd79f0e2021-06-03 15:00:34 -0700447 test_desc["ofm_file"] = ofm_file_vec;
448 }
449
Eric Kunzee5e26762020-10-13 16:11:07 -0700450 return 0;
451}