blob: 6799d71aacaba4cd922106704c3c423ad46fe2d6 [file] [log] [blame]
Eric Kunze2364dcd2021-04-26 11:06:57 -07001
2// Copyright (c) 2020-2021, 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 "tosa_serialization_handler.h"
17
18#include <iostream>
19using namespace tosa;
20
21TosaSerializationTensor::TosaSerializationTensor(const flatbuffers::String* name,
Kevin Cheng3bb1bc12021-06-17 15:57:08 -070022 const flatbuffers::Vector<int32_t>* shape,
Eric Kunze2364dcd2021-04-26 11:06:57 -070023 DType dtype,
Kevin Cheng3bb1bc12021-06-17 15:57:08 -070024 const flatbuffers::Vector<uint8_t>* data)
Eric Kunze2364dcd2021-04-26 11:06:57 -070025{
26 _dtype = dtype;
27
Kevin Cheng3bb1bc12021-06-17 15:57:08 -070028 std::copy(shape->begin(), shape->end(), std::back_inserter(_shape));
Eric Kunze2364dcd2021-04-26 11:06:57 -070029
30 assert(name);
31 _name = name->str();
32
Kevin Cheng3bb1bc12021-06-17 15:57:08 -070033 if (data)
Eric Kunze2364dcd2021-04-26 11:06:57 -070034 {
Kevin Cheng3bb1bc12021-06-17 15:57:08 -070035 std::copy(data->begin(), data->end(), std::back_inserter(_data));
Eric Kunze2364dcd2021-04-26 11:06:57 -070036 }
37}
38
Kevin Cheng545a5082021-11-11 01:36:33 +000039TosaSerializationTensor::TosaSerializationTensor(const std::string& name,
Eric Kunze2364dcd2021-04-26 11:06:57 -070040 const std::vector<int32_t>& shape,
41 DType dtype,
Kevin Cheng3bb1bc12021-06-17 15:57:08 -070042 const std::vector<uint8_t>& data)
Eric Kunze2364dcd2021-04-26 11:06:57 -070043{
Kevin Cheng3bb1bc12021-06-17 15:57:08 -070044 _dtype = dtype;
45 _shape = shape;
46 _name = name;
47 _data = data;
Eric Kunze2364dcd2021-04-26 11:06:57 -070048}
49
50TosaSerializationTensor::TosaSerializationTensor()
51{
52 _dtype = DType_UNKNOWN;
Kevin Cheng545a5082021-11-11 01:36:33 +000053 _name = "UNKNOWN";
Eric Kunze2364dcd2021-04-26 11:06:57 -070054}
55
56TosaSerializationTensor::~TosaSerializationTensor()
57{}
58
Kevin Cheng545a5082021-11-11 01:36:33 +000059void TosaSerializationOperator::InitializeAttributeQinfo(Attribute attribute_type,
60 const TosaAttributeBase* attribute,
61 QuantInfo qinfo_type,
62 const TosaQuantInfoBase* qinfo)
Eric Kunze2364dcd2021-04-26 11:06:57 -070063{
Eric Kunze2364dcd2021-04-26 11:06:57 -070064 _attribute_type = attribute_type;
65
66 switch (attribute_type)
67 {
68 case Attribute_NONE:
69 _attribute = new TosaNoneAttribute();
70 break;
71#define DEF_ATTRIBUTE(NAME, ...) \
72 case Attribute_##NAME##Attribute: \
73 _attribute = new Tosa##NAME##Attribute(attribute); \
74 break;
75#include "attribute.def"
76#undef DEF_ATTRIBUTE
77 default:
78 printf("TosaSerializationOperator::TosaSerializationOperator(): Attribute %s not implemented yet\n",
79 EnumNamesAttribute()[attribute_type]);
80 assert(0);
81 }
82
83 _qinfo_type = qinfo_type;
84 switch (qinfo_type)
85 {
86 case QuantInfo_NONE:
87 _qinfo = new TosaNoneQuantInfo();
88 break;
89#define DEF_QUANTIZATION_INFO(NAME, ...) \
90 case QuantInfo_##NAME##QuantInfo: \
91 _qinfo = new Tosa##NAME##QuantInfo(qinfo); \
92 break;
93#include "quant_info.def"
94#undef DEF_QUANTIZATION_INFO
95 default:
96 printf("TosaSerializationOperator::TosaSerializationOperator(): QuantInfo %s not implemented yet\n",
97 EnumNamesQuantInfo()[qinfo_type]);
98 assert(0);
99 }
100
101 assert(_attribute && _qinfo);
Kevin Cheng545a5082021-11-11 01:36:33 +0000102}
Eric Kunze2364dcd2021-04-26 11:06:57 -0700103
Kevin Cheng545a5082021-11-11 01:36:33 +0000104TosaSerializationOperator::TosaSerializationOperator(Op op,
105 Attribute attribute_type,
106 const TosaAttributeBase* attribute,
107 QuantInfo qinfo_type,
108 const TosaQuantInfoBase* qinfo,
109 const std::vector<std::string>& input_tensor_names,
110 const std::vector<std::string>& output_tensor_names)
111{
112 _op = op;
Eric Kunze2364dcd2021-04-26 11:06:57 -0700113 _input_tensor_names = input_tensor_names;
114 _output_tensor_names = output_tensor_names;
Kevin Cheng545a5082021-11-11 01:36:33 +0000115
116 InitializeAttributeQinfo(attribute_type, attribute, qinfo_type, qinfo);
117}
118
119TosaSerializationOperator::TosaSerializationOperator(Op op,
120 Attribute attribute_type,
121 const TosaAttributeBase* attribute,
122 QuantInfo qinfo_type,
123 const TosaQuantInfoBase* qinfo,
124 std::vector<std::string>&& input_tensor_names,
125 std::vector<std::string>&& output_tensor_names)
126{
127 _op = op;
128 _input_tensor_names = std::move(input_tensor_names);
129 _output_tensor_names = std::move(output_tensor_names);
130
131 InitializeAttributeQinfo(attribute_type, attribute, qinfo_type, qinfo);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700132}
133
134TosaSerializationOperator::~TosaSerializationOperator()
135{
136 delete _attribute;
137 delete _qinfo;
Eric Kunze2364dcd2021-04-26 11:06:57 -0700138}
139
Kevin Cheng545a5082021-11-11 01:36:33 +0000140TosaSerializationBasicBlock::TosaSerializationBasicBlock(const std::string& name,
141 const std::vector<TosaSerializationOperator*>& operators,
142 const std::vector<TosaSerializationTensor*>& tensors,
143 const std::vector<std::string>& inputs,
144 const std::vector<std::string>& outputs)
Eric Kunze2364dcd2021-04-26 11:06:57 -0700145{
Eric Kunze2364dcd2021-04-26 11:06:57 -0700146 _name = name;
147 _operators = operators;
148 _tensors = tensors;
149 _inputs = inputs;
150 _outputs = outputs;
151}
152
Kevin Cheng545a5082021-11-11 01:36:33 +0000153TosaSerializationBasicBlock::TosaSerializationBasicBlock(std::string&& name,
154 std::vector<TosaSerializationOperator*>&& operators,
155 std::vector<TosaSerializationTensor*>&& tensors,
156 std::vector<std::string>&& inputs,
157 std::vector<std::string>&& outputs)
158{
159 _name = std::move(name);
160 _operators = std::move(operators);
161 _tensors = std::move(tensors);
162 _inputs = std::move(inputs);
163 _outputs = std::move(outputs);
164}
165
Eric Kunze2364dcd2021-04-26 11:06:57 -0700166TosaSerializationBasicBlock::~TosaSerializationBasicBlock()
167{
168 // deallocate all operators
169 for (auto op : GetOperators())
170 {
171 delete op; // ~TosaSerializationOperator()
172 }
173
174 // deallocate all tensors
175 for (auto ts : GetTensors())
176 {
177 delete ts; // ~TosaSerializationTensor()
178 }
179}
180
181TosaSerializationHandler::TosaSerializationHandler()
182{
183 _schemaLoaded = false;
Kevin Chenge6563f52021-10-20 12:12:02 -0700184 _version = TosaVersion(TOSA_VERSION_MAJOR, TOSA_VERSION_MINOR, TOSA_VERSION_PATCH, TOSA_VERSION_DRAFT);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700185}
186
187TosaSerializationHandler::~TosaSerializationHandler()
188{
189 Clear(); // deallocate all basic blocks
190}
191
Eric Kunze2364dcd2021-04-26 11:06:57 -0700192tosa_err_t TosaSerializationHandler::LoadFileSchema(const char* schema_filename)
193{
194 std::string schema;
195 bool ok;
196
197 ok = flatbuffers::LoadFile(schema_filename, false, &schema);
198 if (!ok)
199 {
200 printf("Error loading schema file: %s\n", schema_filename);
201 return TOSA_FILE_ERROR;
202 }
203
204 ok = _parser.Parse(schema.c_str());
205 if (!ok)
206 {
207 printf("Error parsing ISA schema file: %s\n", schema_filename);
208 return TOSA_FILE_ERROR;
209 }
210 _schemaLoaded = true;
211
212 return TOSA_OK;
213}
214
215tosa_err_t TosaSerializationHandler::LoadFileJson(const char* filename)
216{
217 std::string jsonfile;
218 bool ok;
219 tosa_err_t err;
220
221 if (!_schemaLoaded)
222 {
223 return TOSA_SCHEMA_MISSING;
224 }
225
226 ok = flatbuffers::LoadFile(filename, false, &jsonfile);
227 if (!ok)
228 {
229 printf("Error loading json file: %s\n", filename);
230 return TOSA_FILE_ERROR;
231 }
232
233 ok = _parser.Parse(jsonfile.c_str());
234 if (!ok)
235 {
236 printf("Error parsing json file: %s\n", filename);
237 return TOSA_FILE_ERROR;
238 }
239
240 uint8_t* buf = _parser.builder_.GetBufferPointer();
241
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700242 err = Deserialize(buf);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700243 if (err != TOSA_OK)
244 {
245 return err;
246 }
247
248 return TOSA_OK;
249}
250
251tosa_err_t TosaSerializationHandler::SaveFileJson(const char* filename)
252{
253 std::string jsongen;
254 tosa_err_t err;
255
256 if (!_schemaLoaded)
257 {
258 return TOSA_SCHEMA_MISSING;
259 }
260
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700261 err = Serialize();
Eric Kunze2364dcd2021-04-26 11:06:57 -0700262 if (err != TOSA_OK)
263 {
264 return err;
265 }
266
267 uint8_t* buf = _builder.GetBufferPointer();
268
269 if (!GenerateText(_parser, buf, &jsongen))
270 {
271 printf("Couldn't serialize parsed data to JSON!\n");
272 return TOSA_FILE_ERROR;
273 }
274
275 FILE* file = fopen(filename, "wb");
276
277 if (!file)
278 {
279 printf("Couldn't open output file: %s\n", filename);
280 return TOSA_FILE_ERROR;
281 }
282
283 if (fwrite(jsongen.c_str(), sizeof(char), jsongen.size(), file) != jsongen.size())
284 {
285 printf("Error writing to json output file: %s\n", filename);
286 fclose(file);
287 return TOSA_FILE_ERROR;
288 }
289
290 if (file)
291 fclose(file);
292
293 return TOSA_OK;
294}
295
296tosa_err_t TosaSerializationHandler::LoadFileTosaFlatbuffer(const char* filename)
297{
298 std::string read_buffer;
299 tosa_err_t err;
300 uint8_t* buf;
301 bool ok;
302
303 ok = flatbuffers::LoadFile(filename, false, &read_buffer);
304 if (!ok)
305 {
306 printf("Error loading flatbuffer file: %s\n", filename);
307 return TOSA_FILE_ERROR;
308 }
309
310 buf = (uint8_t*)read_buffer.data();
311
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700312 err = Deserialize(buf);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700313 if (err != TOSA_OK)
314 {
315 return err;
316 }
317
318 return TOSA_OK;
319}
320
321tosa_err_t TosaSerializationHandler::SaveFileTosaFlatbuffer(const char* filename)
322{
323 tosa_err_t err;
324
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700325 err = Serialize();
Eric Kunze2364dcd2021-04-26 11:06:57 -0700326 if (err != TOSA_OK)
327 {
328 return err;
329 }
330
331 uint8_t* buf = _builder.GetBufferPointer();
332
333 bool ok = flatbuffers::SaveFile(filename, (const char*)buf, _builder.GetSize(), false);
334 if (!ok)
335 {
336 printf("Error saving floatbuffer file: %s\n", filename);
337 return TOSA_FILE_ERROR;
338 }
339
340 return TOSA_OK;
341}
342
343tosa_err_t TosaSerializationHandler::Clear()
344{
345 // deallocate all basic blocks
346 for (auto bb : GetBlocks())
347 {
348 delete bb;
349 }
350 _blocks.clear();
351
352 return TOSA_OK;
353}
354
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700355tosa_err_t TosaSerializationHandler::Deserialize(const uint8_t* buf)
Eric Kunze2364dcd2021-04-26 11:06:57 -0700356{
Frederick Liardet62c1e952022-08-24 10:07:25 +0100357 if (!TosaGraphBufferHasIdentifier(buf))
358 {
359 printf("WARNING: TOSA file does not have TOSA file identifier\n");
360 }
Eric Kunze2364dcd2021-04-26 11:06:57 -0700361 auto fb_tosa_graph = GetTosaGraph(buf);
362 auto fb_tosa_version = fb_tosa_graph->version();
363 auto fb_tosa_blocks = fb_tosa_graph->blocks();
364
365 std::vector<std::string> operator_inputs_container;
366 std::vector<std::string> operator_outputs_container;
367
368 std::vector<TosaSerializationOperator*> block_operators_container;
369 std::vector<TosaSerializationTensor*> block_tensors_container;
370 std::vector<std::string> block_inputs_container;
371 std::vector<std::string> block_outputs_container;
372
373 TosaAttributeBase* typed_attribute = NULL;
374 TosaQuantInfoBase* typed_qinfo = NULL;
375 TosaSerializationOperator* new_operator = NULL;
376 TosaSerializationBasicBlock* new_block = NULL;
377 TosaSerializationTensor* new_tensor = NULL;
378
379 // erase container
380 Clear();
381
Kevin Chenge6563f52021-10-20 12:12:02 -0700382 TosaVersion read_version(fb_tosa_version->_major(), fb_tosa_version->_minor(), fb_tosa_version->_patch(),
383 fb_tosa_version->_draft());
Eric Kunze2364dcd2021-04-26 11:06:57 -0700384
Kevin Chenge6563f52021-10-20 12:12:02 -0700385 TosaVersion::compat_t is_compat = read_version.is_compatible(GetVersion());
386 switch (is_compat)
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700387 {
Kevin Chenge6563f52021-10-20 12:12:02 -0700388 case TosaVersion::compat_t::COMPLETELY_COMPATIBLE:
389 break;
390 case TosaVersion::compat_t::PARTIALLY_COMPATIBLE:
391 printf("WARNING: Read flatbuffer version %s is partially compatible with serializer version %s\n",
392 read_version.to_string().c_str(), GetVersion().to_string().c_str());
393 break;
394 case TosaVersion::compat_t::NOT_COMPATIBLE:
395 printf("ERROR: Read flatbuffer version %s is not compatible with serializer version %s\n",
396 read_version.to_string().c_str(), GetVersion().to_string().c_str());
397 return TOSA_VERSION_MISMATCH;
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700398 }
Eric Kunze2364dcd2021-04-26 11:06:57 -0700399
400 for (size_t i = 0; i < fb_tosa_blocks->size(); i++)
401 {
402 auto curr_block = fb_tosa_blocks->Get(i);
403
404 auto block_name = curr_block->name()->str();
405
406 auto fb_tosa_operators = curr_block->operators();
407 block_operators_container.clear();
408 for (size_t j = 0; j < fb_tosa_operators->size(); j++)
409 {
410 auto curr_operator = fb_tosa_operators->Get(j);
411
412 auto operator_op = curr_operator->op();
413 auto attribute_type = curr_operator->attribute_type();
414 auto attribute = curr_operator->attribute();
415 auto operator_qinfo_type = curr_operator->quant_info_type();
416 auto operator_qinfo = curr_operator->quant_info();
417
418 // input tensors
419 auto operator_inputs = curr_operator->inputs();
420 operator_inputs_container.clear();
421 if (operator_inputs)
422 {
423 for (size_t k = 0; k < operator_inputs->size(); k++)
424 {
425 auto curr_input = operator_inputs->Get(k);
426 operator_inputs_container.push_back(curr_input->str());
427 }
428 }
429
430 // output tensors
431 auto operator_outputs = curr_operator->outputs();
432 operator_outputs_container.clear();
433 if (operator_outputs)
434 {
435 for (size_t k = 0; k < operator_outputs->size(); k++)
436 {
437 auto curr_output = operator_outputs->Get(k);
438 operator_outputs_container.push_back(curr_output->str());
439 }
440 }
441
442 switch (attribute_type)
443 {
444 case Attribute_NONE:
445 typed_attribute = new TosaNoneAttribute();
446 break;
447#define DEF_ATTRIBUTE(NAME, ...) \
448 case Attribute_##NAME##Attribute: \
449 typed_attribute = new Tosa##NAME##Attribute(attribute); \
450 break;
451#include "attribute.def"
452#undef DEF_ATTRIBUTE
453 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700454 printf("TosaSerializationHandler::Deserialize(): Attribute %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700455 EnumNamesAttribute()[attribute_type]);
456 return TOSA_INTERNAL_ERROR;
457 }
458
459 switch (operator_qinfo_type)
460 {
461 case QuantInfo_NONE:
462 typed_qinfo = new TosaNoneQuantInfo();
463 break;
464#define DEF_QUANTIZATION_INFO(NAME, ...) \
465 case QuantInfo_##NAME##QuantInfo: \
466 typed_qinfo = new Tosa##NAME##QuantInfo(operator_qinfo); \
467 break;
468
469#include "quant_info.def"
470#undef DEF_QUANTIZATION_INFO
471 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700472 printf("TosaSerializationHandler::Deserialize(): QuantInfo %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700473 EnumNamesQuantInfo()[operator_qinfo_type]);
474 return TOSA_INTERNAL_ERROR;
475 }
476
477 new_operator =
478 new TosaSerializationOperator(operator_op, attribute_type, typed_attribute, operator_qinfo_type,
479 typed_qinfo, operator_inputs_container, operator_outputs_container);
480 if (new_operator)
481 {
482 block_operators_container.push_back(new_operator);
483 }
484 else
485 {
486 return TOSA_MEMORY_ERROR;
487 }
488
489 if (typed_attribute)
490 delete typed_attribute;
491 if (typed_qinfo)
492 delete typed_qinfo;
493 }
494
495 auto fb_tosa_tensors = curr_block->tensors();
496 block_tensors_container.clear();
497 for (size_t j = 0; j < fb_tosa_tensors->size(); j++)
498 {
499 auto curr_tensor = fb_tosa_tensors->Get(j);
500
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700501 auto tensor_name = curr_tensor->name();
502 auto tensor_shape = curr_tensor->shape();
503 auto tensor_type = curr_tensor->type();
504 auto tensor_data = curr_tensor->data();
Eric Kunze2364dcd2021-04-26 11:06:57 -0700505
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700506 new_tensor = new TosaSerializationTensor(tensor_name, tensor_shape, tensor_type, tensor_data);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700507 if (new_tensor)
508 {
509 block_tensors_container.push_back(new_tensor);
510 }
511 else
512 {
513 return TOSA_MEMORY_ERROR;
514 }
515 }
516
517 auto block_inputs = curr_block->inputs();
518 auto block_outputs = curr_block->outputs();
519
520 block_inputs_container.clear();
521 block_outputs_container.clear();
522
523 for (size_t j = 0; j < block_inputs->size(); j++)
524 {
525 auto curr_block_input = block_inputs->Get(j);
526 block_inputs_container.push_back(curr_block_input->str());
527 }
528 for (size_t j = 0; j < block_outputs->size(); j++)
529 {
530 auto curr_block_output = block_outputs->Get(j);
531 block_outputs_container.push_back(curr_block_output->str());
532 }
533
534 new_block = new TosaSerializationBasicBlock(block_name, block_operators_container, block_tensors_container,
535 block_inputs_container, block_outputs_container);
536 if (new_block)
537 {
538 this->GetBlocks().push_back(new_block);
539 }
540 else
541 {
542 return TOSA_MEMORY_ERROR;
543 }
544 }
545
546 return TOSA_OK;
547}
548
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700549tosa_err_t TosaSerializationHandler::Serialize()
Eric Kunze2364dcd2021-04-26 11:06:57 -0700550{
551 std::vector<flatbuffers::Offset<TosaBasicBlock>> fboffset_blocks;
552
553 std::vector<flatbuffers::Offset<TosaOperator>> fboffset_block_operators;
554 std::vector<flatbuffers::Offset<TosaTensor>> fboffset_block_tensors;
555 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_block_inputs;
556 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_block_outputs;
557
558 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_operator_inputs;
559 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_operator_outputs;
560
561 // translate TosaFlatbufferOperator to flatbuffers::Offset<TosaOperator>
562 for (auto block : GetBlocks())
563 {
564 fboffset_block_operators.clear();
565 fboffset_block_tensors.clear();
566 fboffset_block_inputs.clear();
567 fboffset_block_outputs.clear();
568
569 auto block_name = _builder.CreateString(block->GetName().c_str());
570
571 for (auto tensor_str : block->GetInputs())
572 {
573 auto tensor_name = _builder.CreateString(tensor_str.c_str());
574 fboffset_block_inputs.push_back(tensor_name);
575 }
576
577 for (auto tensor_str : block->GetOutputs())
578 {
579 auto tensor_name = _builder.CreateString(tensor_str.c_str());
580 fboffset_block_outputs.push_back(tensor_name);
581 }
582
583 auto fb_block_inputs = _builder.CreateVector(fboffset_block_inputs);
584 auto fb_block_outputs = _builder.CreateVector(fboffset_block_outputs);
585
586 for (auto op : block->GetOperators())
587 {
588 fboffset_operator_inputs.clear();
589 fboffset_operator_outputs.clear();
590
591 auto operator_op = op->GetOp();
592 auto attribute_type = op->GetAttributeType();
593
594 for (auto tensor_str : op->GetInputTensorNames())
595 {
596 auto tensor_name = _builder.CreateString(tensor_str.c_str());
597 fboffset_operator_inputs.push_back(tensor_name);
598 }
599
600 for (auto tensor_str : op->GetOutputTensorNames())
601 {
602 auto tensor_name = _builder.CreateString(tensor_str.c_str());
603 fboffset_operator_outputs.push_back(tensor_name);
604 }
605
606 auto fb_operator_inputs = _builder.CreateVector(fboffset_operator_inputs);
607 auto fb_operator_outputs = _builder.CreateVector(fboffset_operator_outputs);
608
609 flatbuffers::Offset<void> fb_attribute;
610 switch (attribute_type)
611 {
612 case Attribute_NONE:
613 fb_attribute = 0;
614 break;
615
616#define DEF_ARGS_S_STR(NAME, V) , _builder.CreateString(reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V().c_str())
617#define DEF_ARGS_S_DEFAULT(NAME, V) , reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V()
618
619#define DEF_ARGS_S_int32_t(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
620#define DEF_ARGS_S_float(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
621#define DEF_ARGS_S_bool(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
622#define DEF_ARGS_S_ResizeMode(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
623#define DEF_ARGS_S_string(NAME, V) DEF_ARGS_S_STR(NAME, V)
624
625#define DEF_ARGS_S(NAME, T, V) DEF_ARGS_S_##T(NAME, V)
626#define DEF_ARGS_V(NAME, T, V) , _builder.CreateVector<T>(reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V())
627
628#define DEF_ARGS_1(NAME, T0, F0, V0) DEF_ARGS_##F0(NAME, T0, V0)
629#define DEF_ARGS_2(NAME, T0, F0, V0, T1, F1, V1) DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1)
630#define DEF_ARGS_3(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2) \
631 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2)
632#define DEF_ARGS_4(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3) \
633 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3)
634#define DEF_ARGS_5(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4) \
635 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
636 DEF_ARGS_##F4(NAME, T4, V4)
637#define DEF_ARGS_6(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5) \
638 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
639 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5)
640#define DEF_ARGS_7(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5, T6, F6, V6) \
641 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
642 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6)
643#define DEF_ATTRIBUTE(NAME, NUM_ARGS, ...) \
644 case Attribute_##NAME##Attribute: \
645 fb_attribute = Create##NAME##Attribute(_builder DEF_ARGS_##NUM_ARGS(NAME##Attribute, __VA_ARGS__)).Union(); \
646 break;
647
648#include "attribute.def"
649#undef DEF_ATTRIBUTE
650#undef DEF_ARGS_1
651#undef DEF_ARGS_2
652#undef DEF_ARGS_3
653#undef DEF_ARGS_4
654#undef DEF_ARGS_5
655#undef DEF_ARGS_6
656#undef DEF_ARGS_7
657#undef DEF_ARGS_S
658#undef DEF_ARGS_V
659#undef DEF_ARGS_S_int32_t
660#undef DEF_ARGS_S_float
661#undef DEF_ARGS_S_bool
662#undef DEF_ARGS_S_ResizeMode
663#undef DEF_ARGS_S_string
664#undef DEF_ARGS_S_STR
665#undef DEF_ARGS_S_DEFAULT
666 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700667 printf("TosaSerializationHandler::Serialize(): Attribute %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700668 EnumNamesAttribute()[attribute_type]);
669 return TOSA_INTERNAL_ERROR;
670 }
671
672 auto qinfo_type = op->GetQInfoType();
673 flatbuffers::Offset<void> fb_operator_qinfo;
674 switch (qinfo_type)
675 {
676 case QuantInfo_NONE:
677 fb_operator_qinfo = 0;
678 break;
679#define DEF_ARGS_S(NAME, T, V) , reinterpret_cast<Tosa##NAME*>(op->GetQInfo())->V()
680#define DEF_ARGS_V(NAME, T, V) , _builder.CreateVector<T>(reinterpret_cast<Tosa##NAME*>(op->GetQInfo())->V())
681
682#define DEF_ARGS_1(NAME, T0, F0, V0) DEF_ARGS_##F0(NAME, T0, V0)
683#define DEF_ARGS_2(NAME, T0, F0, V0, T1, F1, V1) DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1)
684#define DEF_ARGS_3(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2) \
685 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2)
686#define DEF_ARGS_4(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3) \
687 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3)
688#define DEF_ARGS_5(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4) \
689 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
690 DEF_ARGS_##F4(NAME, T4, V4)
691#define DEF_ARGS_6(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5) \
692 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
693 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5)
694#define DEF_ARGS_7(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5, T6, F6, V6) \
695 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
696 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6)
697#define DEF_ARGS_8(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5, T6, F6, V6, T7, F7, \
698 V7) \
699 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
700 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6) \
701 DEF_ARGS_##F7(NAME, T7, V7)
702#define DEF_ARGS_9(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5, T6, F6, V6, T7, F7, \
703 V7, T8, F8, V8) \
704 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
705 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6) \
706 DEF_ARGS_##F7(NAME, T7, V7) DEF_ARGS_##F8(NAME, T8, V8)
707#define DEF_ARGS_10(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5, T6, F6, V6, T7, F7, \
708 V7, T8, F8, V8, T9, F9, V9) \
709 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
710 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6) \
711 DEF_ARGS_##F7(NAME, T7, V7) DEF_ARGS_##F8(NAME, T8, V8) DEF_ARGS_##F9(NAME, T9, V9)
712#define DEF_QUANTIZATION_INFO(NAME, NUM_ARGS, ...) \
713 case QuantInfo_##NAME##QuantInfo: \
714 fb_operator_qinfo = \
715 Create##NAME##QuantInfo(_builder DEF_ARGS_##NUM_ARGS(NAME##QuantInfo, __VA_ARGS__)).Union(); \
716 break;
717
718#include "quant_info.def"
719#undef DEF_QUANTIZATION_INFO
720#undef DEF_ARGS_1
721#undef DEF_ARGS_2
722#undef DEF_ARGS_3
723#undef DEF_ARGS_4
724#undef DEF_ARGS_5
725#undef DEF_ARGS_6
726#undef DEF_ARGS_7
727#undef DEF_ARGS_8
728#undef DEF_ARGS_9
729#undef DEF_ARGS_10
730#undef DEF_ARGS_S
731#undef DEF_ARGS_V
732 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700733 printf("TosaSerializationHandler::Serialize(): Attribute %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700734 EnumNamesAttribute()[attribute_type]);
735 return TOSA_INTERNAL_ERROR;
736 }
737
738 auto fboffset_operator =
739 CreateTosaOperator(_builder, operator_op, attribute_type, fb_attribute, fb_operator_inputs,
740 fb_operator_outputs, qinfo_type, fb_operator_qinfo);
741 fboffset_block_operators.push_back(fboffset_operator);
742 }
743
744 auto fb_block_operators = _builder.CreateVector(fboffset_block_operators);
745
746 for (auto tensor : block->GetTensors())
747 {
748
749 auto tensor_name = _builder.CreateString(tensor->GetName().c_str());
750 auto tensor_shape = _builder.CreateVector(tensor->GetShape());
751 auto tensor_dtype = tensor->GetDtype();
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700752 auto tensor_data = _builder.CreateVector(tensor->GetData());
Eric Kunze2364dcd2021-04-26 11:06:57 -0700753
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700754 auto fboffset_tensor = CreateTosaTensor(_builder, tensor_name, tensor_shape, tensor_dtype, tensor_data);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700755 fboffset_block_tensors.push_back(fboffset_tensor);
756 }
757
758 auto fb_block_tensors = _builder.CreateVector(fboffset_block_tensors);
759
760 auto fboffset_block = CreateTosaBasicBlock(_builder, block_name, fb_block_operators, fb_block_tensors,
761 fb_block_inputs, fb_block_outputs);
762 fboffset_blocks.push_back(fboffset_block);
763 }
764
765 auto fb_blocks = _builder.CreateVector(fboffset_blocks);
766
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700767 auto fb_version =
768 CreateVersion(_builder, TOSA_VERSION_MAJOR, TOSA_VERSION_MINOR, TOSA_VERSION_PATCH, TOSA_VERSION_DRAFT);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700769
770 auto fb_graph = CreateTosaGraph(_builder, fb_version, fb_blocks);
Frederick Liardet62c1e952022-08-24 10:07:25 +0100771 _builder.Finish(fb_graph, TosaGraphIdentifier());
Eric Kunze2364dcd2021-04-26 11:06:57 -0700772
773 return TOSA_OK;
774}
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700775
776void zero_pad(std::vector<uint8_t>& buf)
777{
778 while ((buf.size() % TENSOR_BUFFER_FORCE_ALIGNMENT) != 0)
779 {
780 buf.push_back(0);
781 }
782}
783
784tosa_err_t TosaSerializationHandler::ConvertF32toU8(const std::vector<float>& in, std::vector<uint8_t>& out)
785{
786 out.clear();
787 for (auto val : in)
788 {
789 uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
790 out.push_back(*val_u32 & 0xFF);
791 out.push_back((*val_u32 >> 8) & 0xFF);
792 out.push_back((*val_u32 >> 16) & 0xFF);
793 out.push_back((*val_u32 >> 24) & 0xFF);
794 }
795 zero_pad(out);
796 return TOSA_OK;
797}
798
799tosa_err_t TosaSerializationHandler::ConvertI48toU8(const std::vector<int64_t>& in, std::vector<uint8_t>& out)
800{
801 out.clear();
802 for (auto val : in)
803 {
804 uint64_t* val_u64 = reinterpret_cast<uint64_t*>(&val);
805 out.push_back(*val_u64 & 0xFF);
806 out.push_back((*val_u64 >> 8) & 0xFF);
807 out.push_back((*val_u64 >> 16) & 0xFF);
808 out.push_back((*val_u64 >> 24) & 0xFF);
809 out.push_back((*val_u64 >> 32) & 0xFF);
810 out.push_back((*val_u64 >> 40) & 0xFF);
811 }
812 zero_pad(out);
813 return TOSA_OK;
814}
815
816tosa_err_t TosaSerializationHandler::ConvertI32toU8(const std::vector<int32_t>& in, std::vector<uint8_t>& out)
817{
818 out.clear();
819 for (auto val : in)
820 {
821 uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
822 out.push_back(*val_u32 & 0xFF);
823 out.push_back((*val_u32 >> 8) & 0xFF);
824 out.push_back((*val_u32 >> 16) & 0xFF);
825 out.push_back((*val_u32 >> 24) & 0xFF);
826 }
827 zero_pad(out);
828 return TOSA_OK;
829}
830
831tosa_err_t TosaSerializationHandler::ConvertI16toU8(const std::vector<int16_t>& in, std::vector<uint8_t>& out)
832{
833 out.clear();
834 for (auto val : in)
835 {
836 uint16_t* val_u16 = reinterpret_cast<uint16_t*>(&val);
837 out.push_back(*val_u16 & 0xFF);
838 out.push_back((*val_u16 >> 8) & 0xFF);
839 }
840 zero_pad(out);
841 return TOSA_OK;
842}
843
844tosa_err_t TosaSerializationHandler::ConvertI8toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out)
845{
846 out.clear();
847 for (auto val : in)
848 {
849 uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
850 out.push_back(*val_u8);
851 }
852 zero_pad(out);
853 return TOSA_OK;
854}
855
Kevin Cheng3ce56342021-07-28 13:42:29 -0700856// Two int4 values are packed into one byte out.
857// For given input value val_0 = in[2*i], and val_1 = in[2*i+1],
858// they'll be packed as out[3:0] = val_0, and out[7:4] = val_1
859tosa_err_t TosaSerializationHandler::ConvertI4toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out)
860{
861 out.clear();
862 uint32_t in_size = in.size();
863 uint32_t out_size = (in_size % 2 == 0) ? (in_size / 2) : ((in_size + 1) / 2);
864 for (int i = 0; i < out_size; i++)
865 {
866 int8_t val_0 = in[2 * i];
867 int8_t val_1 = 0;
868 if (2 * i + 1 < in_size)
869 {
870 val_1 = in[2 * i + 1];
871 }
872 // In TOSA spec, int4 ranges [-7, 7]
873 if (val_0 < -7 || val_0 > 7 || val_1 < -7 || val_1 > 7)
874 {
875 printf("TosaSerializationHandler::ConvertI4toU8(): element in input array (%d or %d) exceeds int4 range.\n",
876 val_0, val_1);
877 return TOSA_USER_ERROR;
878 }
879 int8_t val_packed = (val_0 & 0xF) | ((val_1 & 0xF) << 4);
880 uint8_t val_u8 = static_cast<uint8_t>(val_packed);
881 out.push_back(val_u8);
882 }
883 zero_pad(out);
884 return TOSA_OK;
885}
886
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700887tosa_err_t TosaSerializationHandler::ConvertBooltoU8(const std::vector<bool>& in, std::vector<uint8_t>& out)
888{
889 out.clear();
890 for (auto val : in)
891 {
892 uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
893 out.push_back(*val_u8);
894 }
895 zero_pad(out);
896 return TOSA_OK;
897}
898
899tosa_err_t
900 TosaSerializationHandler::ConvertU8toF32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<float>& out)
901{
902 out.clear();
903 if (in.size() < out_size * sizeof(float))
904 {
905 printf("TosaSerializationHandler::ConvertU8toF32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
906 out_size * sizeof(float));
907 return TOSA_USER_ERROR;
908 }
909 for (int i = 0; i < out_size; i++)
910 {
911 uint32_t byte0 = in[i * sizeof(float)];
912 uint32_t byte1 = in[i * sizeof(float) + 1];
913 uint32_t byte2 = in[i * sizeof(float) + 2];
914 uint32_t byte3 = in[i * sizeof(float) + 3];
915 uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
916 float* val_fp32 = reinterpret_cast<float*>(&val_u32);
917 out.push_back(*val_fp32);
918 }
919 return TOSA_OK;
920}
921
922tosa_err_t TosaSerializationHandler::ConvertU8toI48(const std::vector<uint8_t>& in,
923 uint32_t out_size,
924 std::vector<int64_t>& out)
925{
926 out.clear();
927 if (in.size() < out_size * 6 /* sizeof(int48) */)
928 {
929 printf("TosaSerializationHandler::ConvertU8toI48(): uint8 buffer size %ld must >= target size %d\n", in.size(),
930 out_size * 6);
931 return TOSA_USER_ERROR;
932 }
933 for (int i = 0; i < out_size; i++)
934 {
935 uint64_t byte0 = in[i * 6];
936 uint64_t byte1 = in[i * 6 + 1];
937 uint64_t byte2 = in[i * 6 + 2];
938 uint64_t byte3 = in[i * 6 + 3];
939 uint64_t byte4 = in[i * 6 + 4];
940 uint64_t byte5 = in[i * 6 + 5];
941 bool sign = ((byte5 >> 7) & 1) == 1 ? true : false;
942 uint64_t val_u64 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24) + (byte4 << 32) + (byte5 << 40);
943 if (sign)
944 {
945 uint64_t sext_mask = (0xFFFFUL << 48);
946 val_u64 |= sext_mask;
947 }
948 int64_t* val_i64 = reinterpret_cast<int64_t*>(&val_u64);
949 out.push_back(*val_i64);
950 }
951 return TOSA_OK;
952}
953
954tosa_err_t TosaSerializationHandler::ConvertU8toI32(const std::vector<uint8_t>& in,
955 uint32_t out_size,
956 std::vector<int32_t>& out)
957{
958 out.clear();
959 if (in.size() < out_size * sizeof(int32_t))
960 {
961 printf("TosaSerializationHandler::ConvertU8toI32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
962 out_size * sizeof(int32_t));
963 return TOSA_USER_ERROR;
964 }
965 for (int i = 0; i < out_size; i++)
966 {
967 uint32_t byte0 = in[i * sizeof(int32_t)];
968 uint32_t byte1 = in[i * sizeof(int32_t) + 1];
969 uint32_t byte2 = in[i * sizeof(int32_t) + 2];
970 uint32_t byte3 = in[i * sizeof(int32_t) + 3];
971 uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
972 int32_t* val_i32 = reinterpret_cast<int32_t*>(&val_u32);
973 out.push_back(*val_i32);
974 }
975 return TOSA_OK;
976}
977
978tosa_err_t TosaSerializationHandler::ConvertU8toI16(const std::vector<uint8_t>& in,
979 uint32_t out_size,
980 std::vector<int16_t>& out)
981{
982 out.clear();
983 if (in.size() < out_size * sizeof(int16_t))
984 {
985 printf("TosaSerializationHandler::ConvertU8toI16(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
986 out_size * sizeof(int16_t));
987 return TOSA_USER_ERROR;
988 }
989 for (int i = 0; i < out_size; i++)
990 {
991 uint16_t byte0 = in[i * sizeof(int16_t)];
992 uint16_t byte1 = in[i * sizeof(int16_t) + 1];
993 uint16_t val_u16 = byte0 + (byte1 << 8);
994 int16_t* val_i16 = reinterpret_cast<int16_t*>(&val_u16);
995 out.push_back(*val_i16);
996 }
997 return TOSA_OK;
998}
999
1000tosa_err_t
1001 TosaSerializationHandler::ConvertU8toI8(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out)
1002{
1003 out.clear();
1004 if (in.size() < out_size * sizeof(int8_t))
1005 {
1006 printf("TosaSerializationHandler::ConvertU8toI8(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
Kevin Cheng3ce56342021-07-28 13:42:29 -07001007 out_size * sizeof(int8_t));
Kevin Cheng3bb1bc12021-06-17 15:57:08 -07001008 return TOSA_USER_ERROR;
1009 }
1010 for (int i = 0; i < out_size; i++)
1011 {
1012 uint8_t val_u8 = in[i];
1013 int8_t* val_i8 = reinterpret_cast<int8_t*>(&val_u8);
1014 out.push_back(*val_i8);
1015 }
1016 return TOSA_OK;
1017}
1018
1019tosa_err_t
Kevin Cheng3ce56342021-07-28 13:42:29 -07001020 TosaSerializationHandler::ConvertU8toI4(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out)
1021{
1022 out.clear();
1023 if (out_size > in.size() * 2)
1024 {
1025 printf("TosaSerializationHandler::ConvertU8toI4(): output size %u must <= uint8 buffer size %ld x 2.\n",
1026 out_size, in.size());
1027 return TOSA_USER_ERROR;
1028 }
1029 for (int i = 0; i < in.size(); i++)
1030 {
1031 uint8_t val_u8 = in[i];
1032 uint8_t val_0_u4 = val_u8 & 0xF;
1033 uint8_t val_1_u4 = val_u8 >> 4;
1034 uint8_t val_0_u8_sext = (val_0_u4 & 0x08) ? (val_0_u4 | 0xF0) : val_0_u4;
1035 uint8_t val_1_u8_sext = (val_1_u4 & 0x08) ? (val_1_u4 | 0xF0) : val_1_u4;
1036 int8_t val_0 = static_cast<int8_t>(val_0_u8_sext);
1037 int8_t val_1 = static_cast<int8_t>(val_1_u8_sext);
1038 // In TOSA spec, int4 ranges [-7, 7]
1039 if (val_0 < -7 || val_0 > 7 || val_1 < -7 || val_1 > 7)
1040 {
1041 printf(
1042 "TosaSerializationHandler::ConvertU8toI4(): element in output array (%d or %d) exceeds int4 range.\n",
1043 val_0, val_1);
1044 return TOSA_USER_ERROR;
1045 }
1046 out.push_back(val_0);
1047 if (2 * i + 1 < out_size)
1048 out.push_back(val_1);
1049 }
1050 return TOSA_OK;
1051}
1052
1053tosa_err_t
Kevin Cheng3bb1bc12021-06-17 15:57:08 -07001054 TosaSerializationHandler::ConvertU8toBool(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<bool>& out)
1055{
1056 out.clear();
1057 if (in.size() < out_size * sizeof(bool))
1058 {
1059 printf("TosaSerializationHandler::ConvertU8toBool(): uint8 buffer size %ld must >= target size %ld\n",
1060 in.size(), out_size * sizeof(bool));
1061 return TOSA_USER_ERROR;
1062 }
1063 for (int i = 0; i < out_size; i++)
1064 {
1065 uint8_t val_u8 = in[i];
1066 bool* val_bool = reinterpret_cast<bool*>(&val_u8);
1067 out.push_back(*val_bool);
1068 }
1069 return TOSA_OK;
1070}