blob: 12d55c6b9d995d790d05c9cd0bed3bd69530b72a [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
Kevin Chenga81a7a12021-11-10 14:07:34 -0800192TosaVersion TosaSerializationHandler::ParseTosaSchemaVersion(std::string schema)
193{
194 // Parse all 4 version fields in schema file
195 static const char* keywords[4] = { "major: int32 = ", "minor: int32 = ", "patch: int32 = ", "draft: bool = " };
196 string keyword_str[4];
197 size_t search_pos = 0;
198 size_t keyword_pos;
199 size_t semicolon_pos;
200 // parse integer field first
201 for (int32_t i = 0; i < 4; i++)
202 {
203 keyword_pos = schema.find(keywords[i], search_pos);
204 if (keyword_pos == std::string::npos)
205 {
206 printf("ERROR: can't find keyword \"%s\" in schema\n", keywords[i]);
207 assert(0);
208 }
209 semicolon_pos = schema.find(';', keyword_pos);
210 if (keyword_pos == std::string::npos)
211 {
212 printf("ERROR: can't find ';' in schema\n");
213 assert(0);
214 }
215 keyword_str[i] =
216 schema.substr(keyword_pos + strlen(keywords[i]), semicolon_pos - keyword_pos - strlen(keywords[i]));
217 search_pos = semicolon_pos;
218 }
219
220 int32_t schema_major = 0;
221 int32_t schema_minor = 0;
222 int32_t schema_patch = 0;
223 bool schema_draft = false;
224 try
225 {
226 schema_major = stoi(keyword_str[0]);
227 schema_minor = stoi(keyword_str[1]);
228 schema_patch = stoi(keyword_str[2]);
229 schema_draft = (keyword_str[3] == "true") ? true : false;
230 }
231 catch (std::invalid_argument& e)
232 {
233 printf("ERROR: fail at stoi(): %s\n", e.what());
234 assert(0);
235 }
236
237 TosaVersion schema_version(schema_major, schema_minor, schema_patch, schema_draft);
238
239 return schema_version;
240}
241
Eric Kunze2364dcd2021-04-26 11:06:57 -0700242tosa_err_t TosaSerializationHandler::LoadFileSchema(const char* schema_filename)
243{
244 std::string schema;
245 bool ok;
246
247 ok = flatbuffers::LoadFile(schema_filename, false, &schema);
248 if (!ok)
249 {
250 printf("Error loading schema file: %s\n", schema_filename);
251 return TOSA_FILE_ERROR;
252 }
253
254 ok = _parser.Parse(schema.c_str());
Kevin Chenga81a7a12021-11-10 14:07:34 -0800255
256 TosaVersion schema_version = ParseTosaSchemaVersion(schema);
257
258 TosaVersion::compat_t is_compat = schema_version.is_compatible(GetVersion());
259 switch (is_compat)
260 {
261 case TosaVersion::compat_t::COMPLETELY_COMPATIBLE:
262 break;
263 case TosaVersion::compat_t::PARTIALLY_COMPATIBLE:
264 printf("WARNING: Schema flatbuffer version %s is partially compatible with serializer version %s\n",
265 schema_version.to_string().c_str(), GetVersion().to_string().c_str());
266 break;
267 case TosaVersion::compat_t::NOT_COMPATIBLE:
268 printf("ERROR: Schema flatbuffer version %s is not compatible with serializer version %s\n",
269 schema_version.to_string().c_str(), GetVersion().to_string().c_str());
270 return TOSA_VERSION_MISMATCH;
271 }
272
Eric Kunze2364dcd2021-04-26 11:06:57 -0700273 if (!ok)
274 {
275 printf("Error parsing ISA schema file: %s\n", schema_filename);
276 return TOSA_FILE_ERROR;
277 }
278 _schemaLoaded = true;
279
280 return TOSA_OK;
281}
282
283tosa_err_t TosaSerializationHandler::LoadFileJson(const char* filename)
284{
285 std::string jsonfile;
286 bool ok;
287 tosa_err_t err;
288
289 if (!_schemaLoaded)
290 {
291 return TOSA_SCHEMA_MISSING;
292 }
293
294 ok = flatbuffers::LoadFile(filename, false, &jsonfile);
295 if (!ok)
296 {
297 printf("Error loading json file: %s\n", filename);
298 return TOSA_FILE_ERROR;
299 }
300
301 ok = _parser.Parse(jsonfile.c_str());
302 if (!ok)
303 {
304 printf("Error parsing json file: %s\n", filename);
305 return TOSA_FILE_ERROR;
306 }
307
308 uint8_t* buf = _parser.builder_.GetBufferPointer();
309
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700310 err = Deserialize(buf);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700311 if (err != TOSA_OK)
312 {
313 return err;
314 }
315
316 return TOSA_OK;
317}
318
319tosa_err_t TosaSerializationHandler::SaveFileJson(const char* filename)
320{
321 std::string jsongen;
322 tosa_err_t err;
323
324 if (!_schemaLoaded)
325 {
326 return TOSA_SCHEMA_MISSING;
327 }
328
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700329 err = Serialize();
Eric Kunze2364dcd2021-04-26 11:06:57 -0700330 if (err != TOSA_OK)
331 {
332 return err;
333 }
334
335 uint8_t* buf = _builder.GetBufferPointer();
336
337 if (!GenerateText(_parser, buf, &jsongen))
338 {
339 printf("Couldn't serialize parsed data to JSON!\n");
340 return TOSA_FILE_ERROR;
341 }
342
343 FILE* file = fopen(filename, "wb");
344
345 if (!file)
346 {
347 printf("Couldn't open output file: %s\n", filename);
348 return TOSA_FILE_ERROR;
349 }
350
351 if (fwrite(jsongen.c_str(), sizeof(char), jsongen.size(), file) != jsongen.size())
352 {
353 printf("Error writing to json output file: %s\n", filename);
354 fclose(file);
355 return TOSA_FILE_ERROR;
356 }
357
358 if (file)
359 fclose(file);
360
361 return TOSA_OK;
362}
363
364tosa_err_t TosaSerializationHandler::LoadFileTosaFlatbuffer(const char* filename)
365{
366 std::string read_buffer;
367 tosa_err_t err;
368 uint8_t* buf;
369 bool ok;
370
371 ok = flatbuffers::LoadFile(filename, false, &read_buffer);
372 if (!ok)
373 {
374 printf("Error loading flatbuffer file: %s\n", filename);
375 return TOSA_FILE_ERROR;
376 }
377
378 buf = (uint8_t*)read_buffer.data();
379
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700380 err = Deserialize(buf);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700381 if (err != TOSA_OK)
382 {
383 return err;
384 }
385
386 return TOSA_OK;
387}
388
389tosa_err_t TosaSerializationHandler::SaveFileTosaFlatbuffer(const char* filename)
390{
391 tosa_err_t err;
392
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700393 err = Serialize();
Eric Kunze2364dcd2021-04-26 11:06:57 -0700394 if (err != TOSA_OK)
395 {
396 return err;
397 }
398
399 uint8_t* buf = _builder.GetBufferPointer();
400
401 bool ok = flatbuffers::SaveFile(filename, (const char*)buf, _builder.GetSize(), false);
402 if (!ok)
403 {
404 printf("Error saving floatbuffer file: %s\n", filename);
405 return TOSA_FILE_ERROR;
406 }
407
408 return TOSA_OK;
409}
410
411tosa_err_t TosaSerializationHandler::Clear()
412{
413 // deallocate all basic blocks
414 for (auto bb : GetBlocks())
415 {
416 delete bb;
417 }
418 _blocks.clear();
419
420 return TOSA_OK;
421}
422
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700423tosa_err_t TosaSerializationHandler::Deserialize(const uint8_t* buf)
Eric Kunze2364dcd2021-04-26 11:06:57 -0700424{
425 auto fb_tosa_graph = GetTosaGraph(buf);
426 auto fb_tosa_version = fb_tosa_graph->version();
427 auto fb_tosa_blocks = fb_tosa_graph->blocks();
428
429 std::vector<std::string> operator_inputs_container;
430 std::vector<std::string> operator_outputs_container;
431
432 std::vector<TosaSerializationOperator*> block_operators_container;
433 std::vector<TosaSerializationTensor*> block_tensors_container;
434 std::vector<std::string> block_inputs_container;
435 std::vector<std::string> block_outputs_container;
436
437 TosaAttributeBase* typed_attribute = NULL;
438 TosaQuantInfoBase* typed_qinfo = NULL;
439 TosaSerializationOperator* new_operator = NULL;
440 TosaSerializationBasicBlock* new_block = NULL;
441 TosaSerializationTensor* new_tensor = NULL;
442
443 // erase container
444 Clear();
445
Kevin Chenge6563f52021-10-20 12:12:02 -0700446 TosaVersion read_version(fb_tosa_version->_major(), fb_tosa_version->_minor(), fb_tosa_version->_patch(),
447 fb_tosa_version->_draft());
Eric Kunze2364dcd2021-04-26 11:06:57 -0700448
Kevin Chenge6563f52021-10-20 12:12:02 -0700449 TosaVersion::compat_t is_compat = read_version.is_compatible(GetVersion());
450 switch (is_compat)
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700451 {
Kevin Chenge6563f52021-10-20 12:12:02 -0700452 case TosaVersion::compat_t::COMPLETELY_COMPATIBLE:
453 break;
454 case TosaVersion::compat_t::PARTIALLY_COMPATIBLE:
455 printf("WARNING: Read flatbuffer version %s is partially compatible with serializer version %s\n",
456 read_version.to_string().c_str(), GetVersion().to_string().c_str());
457 break;
458 case TosaVersion::compat_t::NOT_COMPATIBLE:
459 printf("ERROR: Read flatbuffer version %s is not compatible with serializer version %s\n",
460 read_version.to_string().c_str(), GetVersion().to_string().c_str());
461 return TOSA_VERSION_MISMATCH;
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700462 }
Eric Kunze2364dcd2021-04-26 11:06:57 -0700463
464 for (size_t i = 0; i < fb_tosa_blocks->size(); i++)
465 {
466 auto curr_block = fb_tosa_blocks->Get(i);
467
468 auto block_name = curr_block->name()->str();
469
470 auto fb_tosa_operators = curr_block->operators();
471 block_operators_container.clear();
472 for (size_t j = 0; j < fb_tosa_operators->size(); j++)
473 {
474 auto curr_operator = fb_tosa_operators->Get(j);
475
476 auto operator_op = curr_operator->op();
477 auto attribute_type = curr_operator->attribute_type();
478 auto attribute = curr_operator->attribute();
479 auto operator_qinfo_type = curr_operator->quant_info_type();
480 auto operator_qinfo = curr_operator->quant_info();
481
482 // input tensors
483 auto operator_inputs = curr_operator->inputs();
484 operator_inputs_container.clear();
485 if (operator_inputs)
486 {
487 for (size_t k = 0; k < operator_inputs->size(); k++)
488 {
489 auto curr_input = operator_inputs->Get(k);
490 operator_inputs_container.push_back(curr_input->str());
491 }
492 }
493
494 // output tensors
495 auto operator_outputs = curr_operator->outputs();
496 operator_outputs_container.clear();
497 if (operator_outputs)
498 {
499 for (size_t k = 0; k < operator_outputs->size(); k++)
500 {
501 auto curr_output = operator_outputs->Get(k);
502 operator_outputs_container.push_back(curr_output->str());
503 }
504 }
505
506 switch (attribute_type)
507 {
508 case Attribute_NONE:
509 typed_attribute = new TosaNoneAttribute();
510 break;
511#define DEF_ATTRIBUTE(NAME, ...) \
512 case Attribute_##NAME##Attribute: \
513 typed_attribute = new Tosa##NAME##Attribute(attribute); \
514 break;
515#include "attribute.def"
516#undef DEF_ATTRIBUTE
517 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700518 printf("TosaSerializationHandler::Deserialize(): Attribute %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700519 EnumNamesAttribute()[attribute_type]);
520 return TOSA_INTERNAL_ERROR;
521 }
522
523 switch (operator_qinfo_type)
524 {
525 case QuantInfo_NONE:
526 typed_qinfo = new TosaNoneQuantInfo();
527 break;
528#define DEF_QUANTIZATION_INFO(NAME, ...) \
529 case QuantInfo_##NAME##QuantInfo: \
530 typed_qinfo = new Tosa##NAME##QuantInfo(operator_qinfo); \
531 break;
532
533#include "quant_info.def"
534#undef DEF_QUANTIZATION_INFO
535 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700536 printf("TosaSerializationHandler::Deserialize(): QuantInfo %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700537 EnumNamesQuantInfo()[operator_qinfo_type]);
538 return TOSA_INTERNAL_ERROR;
539 }
540
541 new_operator =
542 new TosaSerializationOperator(operator_op, attribute_type, typed_attribute, operator_qinfo_type,
543 typed_qinfo, operator_inputs_container, operator_outputs_container);
544 if (new_operator)
545 {
546 block_operators_container.push_back(new_operator);
547 }
548 else
549 {
550 return TOSA_MEMORY_ERROR;
551 }
552
553 if (typed_attribute)
554 delete typed_attribute;
555 if (typed_qinfo)
556 delete typed_qinfo;
557 }
558
559 auto fb_tosa_tensors = curr_block->tensors();
560 block_tensors_container.clear();
561 for (size_t j = 0; j < fb_tosa_tensors->size(); j++)
562 {
563 auto curr_tensor = fb_tosa_tensors->Get(j);
564
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700565 auto tensor_name = curr_tensor->name();
566 auto tensor_shape = curr_tensor->shape();
567 auto tensor_type = curr_tensor->type();
568 auto tensor_data = curr_tensor->data();
Eric Kunze2364dcd2021-04-26 11:06:57 -0700569
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700570 new_tensor = new TosaSerializationTensor(tensor_name, tensor_shape, tensor_type, tensor_data);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700571 if (new_tensor)
572 {
573 block_tensors_container.push_back(new_tensor);
574 }
575 else
576 {
577 return TOSA_MEMORY_ERROR;
578 }
579 }
580
581 auto block_inputs = curr_block->inputs();
582 auto block_outputs = curr_block->outputs();
583
584 block_inputs_container.clear();
585 block_outputs_container.clear();
586
587 for (size_t j = 0; j < block_inputs->size(); j++)
588 {
589 auto curr_block_input = block_inputs->Get(j);
590 block_inputs_container.push_back(curr_block_input->str());
591 }
592 for (size_t j = 0; j < block_outputs->size(); j++)
593 {
594 auto curr_block_output = block_outputs->Get(j);
595 block_outputs_container.push_back(curr_block_output->str());
596 }
597
598 new_block = new TosaSerializationBasicBlock(block_name, block_operators_container, block_tensors_container,
599 block_inputs_container, block_outputs_container);
600 if (new_block)
601 {
602 this->GetBlocks().push_back(new_block);
603 }
604 else
605 {
606 return TOSA_MEMORY_ERROR;
607 }
608 }
609
610 return TOSA_OK;
611}
612
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700613tosa_err_t TosaSerializationHandler::Serialize()
Eric Kunze2364dcd2021-04-26 11:06:57 -0700614{
615 std::vector<flatbuffers::Offset<TosaBasicBlock>> fboffset_blocks;
616
617 std::vector<flatbuffers::Offset<TosaOperator>> fboffset_block_operators;
618 std::vector<flatbuffers::Offset<TosaTensor>> fboffset_block_tensors;
619 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_block_inputs;
620 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_block_outputs;
621
622 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_operator_inputs;
623 std::vector<flatbuffers::Offset<flatbuffers::String>> fboffset_operator_outputs;
624
625 // translate TosaFlatbufferOperator to flatbuffers::Offset<TosaOperator>
626 for (auto block : GetBlocks())
627 {
628 fboffset_block_operators.clear();
629 fboffset_block_tensors.clear();
630 fboffset_block_inputs.clear();
631 fboffset_block_outputs.clear();
632
633 auto block_name = _builder.CreateString(block->GetName().c_str());
634
635 for (auto tensor_str : block->GetInputs())
636 {
637 auto tensor_name = _builder.CreateString(tensor_str.c_str());
638 fboffset_block_inputs.push_back(tensor_name);
639 }
640
641 for (auto tensor_str : block->GetOutputs())
642 {
643 auto tensor_name = _builder.CreateString(tensor_str.c_str());
644 fboffset_block_outputs.push_back(tensor_name);
645 }
646
647 auto fb_block_inputs = _builder.CreateVector(fboffset_block_inputs);
648 auto fb_block_outputs = _builder.CreateVector(fboffset_block_outputs);
649
650 for (auto op : block->GetOperators())
651 {
652 fboffset_operator_inputs.clear();
653 fboffset_operator_outputs.clear();
654
655 auto operator_op = op->GetOp();
656 auto attribute_type = op->GetAttributeType();
657
658 for (auto tensor_str : op->GetInputTensorNames())
659 {
660 auto tensor_name = _builder.CreateString(tensor_str.c_str());
661 fboffset_operator_inputs.push_back(tensor_name);
662 }
663
664 for (auto tensor_str : op->GetOutputTensorNames())
665 {
666 auto tensor_name = _builder.CreateString(tensor_str.c_str());
667 fboffset_operator_outputs.push_back(tensor_name);
668 }
669
670 auto fb_operator_inputs = _builder.CreateVector(fboffset_operator_inputs);
671 auto fb_operator_outputs = _builder.CreateVector(fboffset_operator_outputs);
672
673 flatbuffers::Offset<void> fb_attribute;
674 switch (attribute_type)
675 {
676 case Attribute_NONE:
677 fb_attribute = 0;
678 break;
679
680#define DEF_ARGS_S_STR(NAME, V) , _builder.CreateString(reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V().c_str())
681#define DEF_ARGS_S_DEFAULT(NAME, V) , reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V()
682
683#define DEF_ARGS_S_int32_t(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
684#define DEF_ARGS_S_float(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
685#define DEF_ARGS_S_bool(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
686#define DEF_ARGS_S_ResizeMode(NAME, V) DEF_ARGS_S_DEFAULT(NAME, V)
687#define DEF_ARGS_S_string(NAME, V) DEF_ARGS_S_STR(NAME, V)
688
689#define DEF_ARGS_S(NAME, T, V) DEF_ARGS_S_##T(NAME, V)
690#define DEF_ARGS_V(NAME, T, V) , _builder.CreateVector<T>(reinterpret_cast<Tosa##NAME*>(op->GetAttribute())->V())
691
692#define DEF_ARGS_1(NAME, T0, F0, V0) DEF_ARGS_##F0(NAME, T0, V0)
693#define DEF_ARGS_2(NAME, T0, F0, V0, T1, F1, V1) DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1)
694#define DEF_ARGS_3(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2) \
695 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2)
696#define DEF_ARGS_4(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3) \
697 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3)
698#define DEF_ARGS_5(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4) \
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)
701#define DEF_ARGS_6(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5) \
702 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
703 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5)
704#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) \
705 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
706 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6)
707#define DEF_ATTRIBUTE(NAME, NUM_ARGS, ...) \
708 case Attribute_##NAME##Attribute: \
709 fb_attribute = Create##NAME##Attribute(_builder DEF_ARGS_##NUM_ARGS(NAME##Attribute, __VA_ARGS__)).Union(); \
710 break;
711
712#include "attribute.def"
713#undef DEF_ATTRIBUTE
714#undef DEF_ARGS_1
715#undef DEF_ARGS_2
716#undef DEF_ARGS_3
717#undef DEF_ARGS_4
718#undef DEF_ARGS_5
719#undef DEF_ARGS_6
720#undef DEF_ARGS_7
721#undef DEF_ARGS_S
722#undef DEF_ARGS_V
723#undef DEF_ARGS_S_int32_t
724#undef DEF_ARGS_S_float
725#undef DEF_ARGS_S_bool
726#undef DEF_ARGS_S_ResizeMode
727#undef DEF_ARGS_S_string
728#undef DEF_ARGS_S_STR
729#undef DEF_ARGS_S_DEFAULT
730 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700731 printf("TosaSerializationHandler::Serialize(): Attribute %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700732 EnumNamesAttribute()[attribute_type]);
733 return TOSA_INTERNAL_ERROR;
734 }
735
736 auto qinfo_type = op->GetQInfoType();
737 flatbuffers::Offset<void> fb_operator_qinfo;
738 switch (qinfo_type)
739 {
740 case QuantInfo_NONE:
741 fb_operator_qinfo = 0;
742 break;
743#define DEF_ARGS_S(NAME, T, V) , reinterpret_cast<Tosa##NAME*>(op->GetQInfo())->V()
744#define DEF_ARGS_V(NAME, T, V) , _builder.CreateVector<T>(reinterpret_cast<Tosa##NAME*>(op->GetQInfo())->V())
745
746#define DEF_ARGS_1(NAME, T0, F0, V0) DEF_ARGS_##F0(NAME, T0, V0)
747#define DEF_ARGS_2(NAME, T0, F0, V0, T1, F1, V1) DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1)
748#define DEF_ARGS_3(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2) \
749 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2)
750#define DEF_ARGS_4(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3) \
751 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3)
752#define DEF_ARGS_5(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4) \
753 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
754 DEF_ARGS_##F4(NAME, T4, V4)
755#define DEF_ARGS_6(NAME, T0, F0, V0, T1, F1, V1, T2, F2, V2, T3, F3, V3, T4, F4, V4, T5, F5, V5) \
756 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
757 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5)
758#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) \
759 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
760 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6)
761#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, \
762 V7) \
763 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
764 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6) \
765 DEF_ARGS_##F7(NAME, T7, V7)
766#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, \
767 V7, T8, F8, V8) \
768 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
769 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6) \
770 DEF_ARGS_##F7(NAME, T7, V7) DEF_ARGS_##F8(NAME, T8, V8)
771#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, \
772 V7, T8, F8, V8, T9, F9, V9) \
773 DEF_ARGS_##F0(NAME, T0, V0) DEF_ARGS_##F1(NAME, T1, V1) DEF_ARGS_##F2(NAME, T2, V2) DEF_ARGS_##F3(NAME, T3, V3) \
774 DEF_ARGS_##F4(NAME, T4, V4) DEF_ARGS_##F5(NAME, T5, V5) DEF_ARGS_##F6(NAME, T6, V6) \
775 DEF_ARGS_##F7(NAME, T7, V7) DEF_ARGS_##F8(NAME, T8, V8) DEF_ARGS_##F9(NAME, T9, V9)
776#define DEF_QUANTIZATION_INFO(NAME, NUM_ARGS, ...) \
777 case QuantInfo_##NAME##QuantInfo: \
778 fb_operator_qinfo = \
779 Create##NAME##QuantInfo(_builder DEF_ARGS_##NUM_ARGS(NAME##QuantInfo, __VA_ARGS__)).Union(); \
780 break;
781
782#include "quant_info.def"
783#undef DEF_QUANTIZATION_INFO
784#undef DEF_ARGS_1
785#undef DEF_ARGS_2
786#undef DEF_ARGS_3
787#undef DEF_ARGS_4
788#undef DEF_ARGS_5
789#undef DEF_ARGS_6
790#undef DEF_ARGS_7
791#undef DEF_ARGS_8
792#undef DEF_ARGS_9
793#undef DEF_ARGS_10
794#undef DEF_ARGS_S
795#undef DEF_ARGS_V
796 default:
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700797 printf("TosaSerializationHandler::Serialize(): Attribute %s not implemented yet\n",
Eric Kunze2364dcd2021-04-26 11:06:57 -0700798 EnumNamesAttribute()[attribute_type]);
799 return TOSA_INTERNAL_ERROR;
800 }
801
802 auto fboffset_operator =
803 CreateTosaOperator(_builder, operator_op, attribute_type, fb_attribute, fb_operator_inputs,
804 fb_operator_outputs, qinfo_type, fb_operator_qinfo);
805 fboffset_block_operators.push_back(fboffset_operator);
806 }
807
808 auto fb_block_operators = _builder.CreateVector(fboffset_block_operators);
809
810 for (auto tensor : block->GetTensors())
811 {
812
813 auto tensor_name = _builder.CreateString(tensor->GetName().c_str());
814 auto tensor_shape = _builder.CreateVector(tensor->GetShape());
815 auto tensor_dtype = tensor->GetDtype();
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700816 auto tensor_data = _builder.CreateVector(tensor->GetData());
Eric Kunze2364dcd2021-04-26 11:06:57 -0700817
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700818 auto fboffset_tensor = CreateTosaTensor(_builder, tensor_name, tensor_shape, tensor_dtype, tensor_data);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700819 fboffset_block_tensors.push_back(fboffset_tensor);
820 }
821
822 auto fb_block_tensors = _builder.CreateVector(fboffset_block_tensors);
823
824 auto fboffset_block = CreateTosaBasicBlock(_builder, block_name, fb_block_operators, fb_block_tensors,
825 fb_block_inputs, fb_block_outputs);
826 fboffset_blocks.push_back(fboffset_block);
827 }
828
829 auto fb_blocks = _builder.CreateVector(fboffset_blocks);
830
Kevin Chengb97cb1d2021-10-14 11:53:39 -0700831 auto fb_version =
832 CreateVersion(_builder, TOSA_VERSION_MAJOR, TOSA_VERSION_MINOR, TOSA_VERSION_PATCH, TOSA_VERSION_DRAFT);
Eric Kunze2364dcd2021-04-26 11:06:57 -0700833
834 auto fb_graph = CreateTosaGraph(_builder, fb_version, fb_blocks);
835 _builder.Finish(fb_graph);
836
837 return TOSA_OK;
838}
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700839
840void zero_pad(std::vector<uint8_t>& buf)
841{
842 while ((buf.size() % TENSOR_BUFFER_FORCE_ALIGNMENT) != 0)
843 {
844 buf.push_back(0);
845 }
846}
847
848tosa_err_t TosaSerializationHandler::ConvertF32toU8(const std::vector<float>& in, std::vector<uint8_t>& out)
849{
850 out.clear();
851 for (auto val : in)
852 {
853 uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
854 out.push_back(*val_u32 & 0xFF);
855 out.push_back((*val_u32 >> 8) & 0xFF);
856 out.push_back((*val_u32 >> 16) & 0xFF);
857 out.push_back((*val_u32 >> 24) & 0xFF);
858 }
859 zero_pad(out);
860 return TOSA_OK;
861}
862
863tosa_err_t TosaSerializationHandler::ConvertI48toU8(const std::vector<int64_t>& in, std::vector<uint8_t>& out)
864{
865 out.clear();
866 for (auto val : in)
867 {
868 uint64_t* val_u64 = reinterpret_cast<uint64_t*>(&val);
869 out.push_back(*val_u64 & 0xFF);
870 out.push_back((*val_u64 >> 8) & 0xFF);
871 out.push_back((*val_u64 >> 16) & 0xFF);
872 out.push_back((*val_u64 >> 24) & 0xFF);
873 out.push_back((*val_u64 >> 32) & 0xFF);
874 out.push_back((*val_u64 >> 40) & 0xFF);
875 }
876 zero_pad(out);
877 return TOSA_OK;
878}
879
880tosa_err_t TosaSerializationHandler::ConvertI32toU8(const std::vector<int32_t>& in, std::vector<uint8_t>& out)
881{
882 out.clear();
883 for (auto val : in)
884 {
885 uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
886 out.push_back(*val_u32 & 0xFF);
887 out.push_back((*val_u32 >> 8) & 0xFF);
888 out.push_back((*val_u32 >> 16) & 0xFF);
889 out.push_back((*val_u32 >> 24) & 0xFF);
890 }
891 zero_pad(out);
892 return TOSA_OK;
893}
894
895tosa_err_t TosaSerializationHandler::ConvertI16toU8(const std::vector<int16_t>& in, std::vector<uint8_t>& out)
896{
897 out.clear();
898 for (auto val : in)
899 {
900 uint16_t* val_u16 = reinterpret_cast<uint16_t*>(&val);
901 out.push_back(*val_u16 & 0xFF);
902 out.push_back((*val_u16 >> 8) & 0xFF);
903 }
904 zero_pad(out);
905 return TOSA_OK;
906}
907
908tosa_err_t TosaSerializationHandler::ConvertI8toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out)
909{
910 out.clear();
911 for (auto val : in)
912 {
913 uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
914 out.push_back(*val_u8);
915 }
916 zero_pad(out);
917 return TOSA_OK;
918}
919
Kevin Cheng3ce56342021-07-28 13:42:29 -0700920// Two int4 values are packed into one byte out.
921// For given input value val_0 = in[2*i], and val_1 = in[2*i+1],
922// they'll be packed as out[3:0] = val_0, and out[7:4] = val_1
923tosa_err_t TosaSerializationHandler::ConvertI4toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out)
924{
925 out.clear();
926 uint32_t in_size = in.size();
927 uint32_t out_size = (in_size % 2 == 0) ? (in_size / 2) : ((in_size + 1) / 2);
928 for (int i = 0; i < out_size; i++)
929 {
930 int8_t val_0 = in[2 * i];
931 int8_t val_1 = 0;
932 if (2 * i + 1 < in_size)
933 {
934 val_1 = in[2 * i + 1];
935 }
936 // In TOSA spec, int4 ranges [-7, 7]
937 if (val_0 < -7 || val_0 > 7 || val_1 < -7 || val_1 > 7)
938 {
939 printf("TosaSerializationHandler::ConvertI4toU8(): element in input array (%d or %d) exceeds int4 range.\n",
940 val_0, val_1);
941 return TOSA_USER_ERROR;
942 }
943 int8_t val_packed = (val_0 & 0xF) | ((val_1 & 0xF) << 4);
944 uint8_t val_u8 = static_cast<uint8_t>(val_packed);
945 out.push_back(val_u8);
946 }
947 zero_pad(out);
948 return TOSA_OK;
949}
950
Kevin Cheng3bb1bc12021-06-17 15:57:08 -0700951tosa_err_t TosaSerializationHandler::ConvertBooltoU8(const std::vector<bool>& in, std::vector<uint8_t>& out)
952{
953 out.clear();
954 for (auto val : in)
955 {
956 uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
957 out.push_back(*val_u8);
958 }
959 zero_pad(out);
960 return TOSA_OK;
961}
962
963tosa_err_t
964 TosaSerializationHandler::ConvertU8toF32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<float>& out)
965{
966 out.clear();
967 if (in.size() < out_size * sizeof(float))
968 {
969 printf("TosaSerializationHandler::ConvertU8toF32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
970 out_size * sizeof(float));
971 return TOSA_USER_ERROR;
972 }
973 for (int i = 0; i < out_size; i++)
974 {
975 uint32_t byte0 = in[i * sizeof(float)];
976 uint32_t byte1 = in[i * sizeof(float) + 1];
977 uint32_t byte2 = in[i * sizeof(float) + 2];
978 uint32_t byte3 = in[i * sizeof(float) + 3];
979 uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
980 float* val_fp32 = reinterpret_cast<float*>(&val_u32);
981 out.push_back(*val_fp32);
982 }
983 return TOSA_OK;
984}
985
986tosa_err_t TosaSerializationHandler::ConvertU8toI48(const std::vector<uint8_t>& in,
987 uint32_t out_size,
988 std::vector<int64_t>& out)
989{
990 out.clear();
991 if (in.size() < out_size * 6 /* sizeof(int48) */)
992 {
993 printf("TosaSerializationHandler::ConvertU8toI48(): uint8 buffer size %ld must >= target size %d\n", in.size(),
994 out_size * 6);
995 return TOSA_USER_ERROR;
996 }
997 for (int i = 0; i < out_size; i++)
998 {
999 uint64_t byte0 = in[i * 6];
1000 uint64_t byte1 = in[i * 6 + 1];
1001 uint64_t byte2 = in[i * 6 + 2];
1002 uint64_t byte3 = in[i * 6 + 3];
1003 uint64_t byte4 = in[i * 6 + 4];
1004 uint64_t byte5 = in[i * 6 + 5];
1005 bool sign = ((byte5 >> 7) & 1) == 1 ? true : false;
1006 uint64_t val_u64 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24) + (byte4 << 32) + (byte5 << 40);
1007 if (sign)
1008 {
1009 uint64_t sext_mask = (0xFFFFUL << 48);
1010 val_u64 |= sext_mask;
1011 }
1012 int64_t* val_i64 = reinterpret_cast<int64_t*>(&val_u64);
1013 out.push_back(*val_i64);
1014 }
1015 return TOSA_OK;
1016}
1017
1018tosa_err_t TosaSerializationHandler::ConvertU8toI32(const std::vector<uint8_t>& in,
1019 uint32_t out_size,
1020 std::vector<int32_t>& out)
1021{
1022 out.clear();
1023 if (in.size() < out_size * sizeof(int32_t))
1024 {
1025 printf("TosaSerializationHandler::ConvertU8toI32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
1026 out_size * sizeof(int32_t));
1027 return TOSA_USER_ERROR;
1028 }
1029 for (int i = 0; i < out_size; i++)
1030 {
1031 uint32_t byte0 = in[i * sizeof(int32_t)];
1032 uint32_t byte1 = in[i * sizeof(int32_t) + 1];
1033 uint32_t byte2 = in[i * sizeof(int32_t) + 2];
1034 uint32_t byte3 = in[i * sizeof(int32_t) + 3];
1035 uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
1036 int32_t* val_i32 = reinterpret_cast<int32_t*>(&val_u32);
1037 out.push_back(*val_i32);
1038 }
1039 return TOSA_OK;
1040}
1041
1042tosa_err_t TosaSerializationHandler::ConvertU8toI16(const std::vector<uint8_t>& in,
1043 uint32_t out_size,
1044 std::vector<int16_t>& out)
1045{
1046 out.clear();
1047 if (in.size() < out_size * sizeof(int16_t))
1048 {
1049 printf("TosaSerializationHandler::ConvertU8toI16(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
1050 out_size * sizeof(int16_t));
1051 return TOSA_USER_ERROR;
1052 }
1053 for (int i = 0; i < out_size; i++)
1054 {
1055 uint16_t byte0 = in[i * sizeof(int16_t)];
1056 uint16_t byte1 = in[i * sizeof(int16_t) + 1];
1057 uint16_t val_u16 = byte0 + (byte1 << 8);
1058 int16_t* val_i16 = reinterpret_cast<int16_t*>(&val_u16);
1059 out.push_back(*val_i16);
1060 }
1061 return TOSA_OK;
1062}
1063
1064tosa_err_t
1065 TosaSerializationHandler::ConvertU8toI8(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out)
1066{
1067 out.clear();
1068 if (in.size() < out_size * sizeof(int8_t))
1069 {
1070 printf("TosaSerializationHandler::ConvertU8toI8(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
Kevin Cheng3ce56342021-07-28 13:42:29 -07001071 out_size * sizeof(int8_t));
Kevin Cheng3bb1bc12021-06-17 15:57:08 -07001072 return TOSA_USER_ERROR;
1073 }
1074 for (int i = 0; i < out_size; i++)
1075 {
1076 uint8_t val_u8 = in[i];
1077 int8_t* val_i8 = reinterpret_cast<int8_t*>(&val_u8);
1078 out.push_back(*val_i8);
1079 }
1080 return TOSA_OK;
1081}
1082
1083tosa_err_t
Kevin Cheng3ce56342021-07-28 13:42:29 -07001084 TosaSerializationHandler::ConvertU8toI4(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out)
1085{
1086 out.clear();
1087 if (out_size > in.size() * 2)
1088 {
1089 printf("TosaSerializationHandler::ConvertU8toI4(): output size %u must <= uint8 buffer size %ld x 2.\n",
1090 out_size, in.size());
1091 return TOSA_USER_ERROR;
1092 }
1093 for (int i = 0; i < in.size(); i++)
1094 {
1095 uint8_t val_u8 = in[i];
1096 uint8_t val_0_u4 = val_u8 & 0xF;
1097 uint8_t val_1_u4 = val_u8 >> 4;
1098 uint8_t val_0_u8_sext = (val_0_u4 & 0x08) ? (val_0_u4 | 0xF0) : val_0_u4;
1099 uint8_t val_1_u8_sext = (val_1_u4 & 0x08) ? (val_1_u4 | 0xF0) : val_1_u4;
1100 int8_t val_0 = static_cast<int8_t>(val_0_u8_sext);
1101 int8_t val_1 = static_cast<int8_t>(val_1_u8_sext);
1102 // In TOSA spec, int4 ranges [-7, 7]
1103 if (val_0 < -7 || val_0 > 7 || val_1 < -7 || val_1 > 7)
1104 {
1105 printf(
1106 "TosaSerializationHandler::ConvertU8toI4(): element in output array (%d or %d) exceeds int4 range.\n",
1107 val_0, val_1);
1108 return TOSA_USER_ERROR;
1109 }
1110 out.push_back(val_0);
1111 if (2 * i + 1 < out_size)
1112 out.push_back(val_1);
1113 }
1114 return TOSA_OK;
1115}
1116
1117tosa_err_t
Kevin Cheng3bb1bc12021-06-17 15:57:08 -07001118 TosaSerializationHandler::ConvertU8toBool(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<bool>& out)
1119{
1120 out.clear();
1121 if (in.size() < out_size * sizeof(bool))
1122 {
1123 printf("TosaSerializationHandler::ConvertU8toBool(): uint8 buffer size %ld must >= target size %ld\n",
1124 in.size(), out_size * sizeof(bool));
1125 return TOSA_USER_ERROR;
1126 }
1127 for (int i = 0; i < out_size; i++)
1128 {
1129 uint8_t val_u8 = in[i];
1130 bool* val_bool = reinterpret_cast<bool*>(&val_u8);
1131 out.push_back(*val_bool);
1132 }
1133 return TOSA_OK;
1134}