Constant data is embedded in flatbuffer as u8 array instead of saving out as separate numpy files now.

Change-Id: I9d757ee3bdc637595732b06c5319d1dc957eaf96
diff --git a/include/tosa_generated.h b/include/tosa_generated.h
index 735aca8..0f73819 100644
--- a/include/tosa_generated.h
+++ b/include/tosa_generated.h
@@ -1951,7 +1951,7 @@
     VT_NAME = 4,
     VT_SHAPE = 6,
     VT_TYPE = 8,
-    VT_NPY_FILENAME = 10
+    VT_DATA = 10
   };
   const flatbuffers::String *name() const {
     return GetPointer<const flatbuffers::String *>(VT_NAME);
@@ -1962,8 +1962,8 @@
   tosa::DType type() const {
     return static_cast<tosa::DType>(GetField<uint32_t>(VT_TYPE, 0));
   }
-  const flatbuffers::String *npy_filename() const {
-    return GetPointer<const flatbuffers::String *>(VT_NPY_FILENAME);
+  const flatbuffers::Vector<uint8_t> *data() const {
+    return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_DATA);
   }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
@@ -1972,8 +1972,8 @@
            VerifyOffset(verifier, VT_SHAPE) &&
            verifier.VerifyVector(shape()) &&
            VerifyField<uint32_t>(verifier, VT_TYPE) &&
-           VerifyOffset(verifier, VT_NPY_FILENAME) &&
-           verifier.VerifyString(npy_filename()) &&
+           VerifyOffset(verifier, VT_DATA) &&
+           verifier.VerifyVector(data()) &&
            verifier.EndTable();
   }
 };
@@ -1991,8 +1991,8 @@
   void add_type(tosa::DType type) {
     fbb_.AddElement<uint32_t>(TosaTensor::VT_TYPE, static_cast<uint32_t>(type), 0);
   }
-  void add_npy_filename(flatbuffers::Offset<flatbuffers::String> npy_filename) {
-    fbb_.AddOffset(TosaTensor::VT_NPY_FILENAME, npy_filename);
+  void add_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data) {
+    fbb_.AddOffset(TosaTensor::VT_DATA, data);
   }
   explicit TosaTensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
         : fbb_(_fbb) {
@@ -2011,9 +2011,9 @@
     flatbuffers::Offset<flatbuffers::String> name = 0,
     flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape = 0,
     tosa::DType type = tosa::DType_UNKNOWN,
-    flatbuffers::Offset<flatbuffers::String> npy_filename = 0) {
+    flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0) {
   TosaTensorBuilder builder_(_fbb);
-  builder_.add_npy_filename(npy_filename);
+  builder_.add_data(data);
   builder_.add_type(type);
   builder_.add_shape(shape);
   builder_.add_name(name);
@@ -2025,16 +2025,17 @@
     const char *name = nullptr,
     const std::vector<int32_t> *shape = nullptr,
     tosa::DType type = tosa::DType_UNKNOWN,
-    const char *npy_filename = nullptr) {
+    const std::vector<uint8_t> *data = nullptr) {
   auto name__ = name ? _fbb.CreateString(name) : 0;
   auto shape__ = shape ? _fbb.CreateVector<int32_t>(*shape) : 0;
-  auto npy_filename__ = npy_filename ? _fbb.CreateString(npy_filename) : 0;
+  if (data) { _fbb.ForceVectorAlignment(data->size(), sizeof(uint8_t), 8); }
+  auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
   return tosa::CreateTosaTensor(
       _fbb,
       name__,
       shape__,
       type,
-      npy_filename__);
+      data__);
 }
 
 struct TosaOperator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
diff --git a/include/tosa_serialization_handler.h b/include/tosa_serialization_handler.h
index 398590d..db9481b 100644
--- a/include/tosa_serialization_handler.h
+++ b/include/tosa_serialization_handler.h
@@ -26,6 +26,8 @@
 #include <string>
 #include <vector>
 
+#define TENSOR_BUFFER_FORCE_ALIGNMENT 8
+
 namespace tosa
 {
 
@@ -108,13 +110,13 @@
 public:
     // constructor and destructor
     TosaSerializationTensor(const flatbuffers::String* name,
-                            const flatbuffers::Vector<int32_t>& shape,
+                            const flatbuffers::Vector<int32_t>* shape,
                             DType dtype,
-                            const flatbuffers::String* npy_filename);
+                            const flatbuffers::Vector<uint8_t>* data);
     TosaSerializationTensor(std::string& name,
                             const std::vector<int32_t>& shape,
                             DType dtype,
-                            const std::string& npy_filename);
+                            const std::vector<uint8_t>& data);
     TosaSerializationTensor();
     ~TosaSerializationTensor();
 
@@ -131,9 +133,9 @@
     {
         return _dtype;
     }
-    const std::string& GetNpyFilePtr() const
+    const std::vector<uint8_t>& GetData() const
     {
-        return _npy_filename;
+        return _data;
     }
 
     // modifier
@@ -150,7 +152,7 @@
     DType _dtype;                /* data type enumeration, see tosa_isa_generated.h */
     std::vector<int32_t> _shape; /* shape of the tensor */
     std::string _name;           /* name of the tensor, used for solving dependency */
-    std::string _npy_filename;   /* numpy array filename if not null. so null is the distinguisher */
+    std::vector<uint8_t> _data;  /* data array */
 };
 
 class TosaSerializationOperator
@@ -283,6 +285,21 @@
     tosa_err_t SaveFileTosaFlatbuffer(const char* filename);
     tosa_err_t LoadFileSchema(const char* schema_filename);
 
+    // data format conversion. little-endian.
+    static tosa_err_t ConvertF32toU8(const std::vector<float>& in, std::vector<uint8_t>& out);
+    static tosa_err_t ConvertI48toU8(const std::vector<int64_t>& in, std::vector<uint8_t>& out);
+    static tosa_err_t ConvertI32toU8(const std::vector<int32_t>& in, std::vector<uint8_t>& out);
+    static tosa_err_t ConvertI16toU8(const std::vector<int16_t>& in, std::vector<uint8_t>& out);
+    static tosa_err_t ConvertI8toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out);
+    static tosa_err_t ConvertBooltoU8(const std::vector<bool>& in, std::vector<uint8_t>& out);
+
+    static tosa_err_t ConvertU8toF32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<float>& out);
+    static tosa_err_t ConvertU8toI48(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int64_t>& out);
+    static tosa_err_t ConvertU8toI32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int32_t>& out);
+    static tosa_err_t ConvertU8toI16(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int16_t>& out);
+    static tosa_err_t ConvertU8toI8(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out);
+    static tosa_err_t ConvertU8toBool(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<bool>& out);
+
     // version
     const TosaVersion& GetTosaVersion() const
     {
diff --git a/python/tosa/TosaTensor.py b/python/tosa/TosaTensor.py
index 760c091..9c0b3cf 100644
--- a/python/tosa/TosaTensor.py
+++ b/python/tosa/TosaTensor.py
@@ -81,16 +81,37 @@
         return 0
 
     # TosaTensor
-    def NpyFilename(self):
+    def Data(self, j):
         o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
         if o != 0:
-            return self._tab.String(o + self._tab.Pos)
-        return None
+            a = self._tab.Vector(o)
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # TosaTensor
+    def DataAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+        return 0
+
+    # TosaTensor
+    def DataLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # TosaTensor
+    def DataIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        return o == 0
 
 def TosaTensorStart(builder): builder.StartObject(4)
 def TosaTensorAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
 def TosaTensorAddShape(builder, shape): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(shape), 0)
 def TosaTensorStartShapeVector(builder, numElems): return builder.StartVector(4, numElems, 4)
 def TosaTensorAddType(builder, type): builder.PrependUint32Slot(2, type, 0)
-def TosaTensorAddNpyFilename(builder, npyFilename): builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(npyFilename), 0)
+def TosaTensorAddData(builder, data): builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(data), 0)
+def TosaTensorStartDataVector(builder, numElems): return builder.StartVector(1, numElems, 1)
 def TosaTensorEnd(builder): return builder.EndObject()
diff --git a/schema/tosa.fbs b/schema/tosa.fbs
index d64a50c..9c8add8 100644
--- a/schema/tosa.fbs
+++ b/schema/tosa.fbs
@@ -276,10 +276,10 @@
 }
 
 table TosaTensor {
-  name:string;              // name of the tensor, used for solving dependency
-  shape:[int32];            // shape of the tensor
-  type:DType;               // data type of the tensor
-  npy_filename: string;     // numpy array filename
+  name:string;                      // name of the tensor, used for solving dependency
+  shape:[int32];                    // shape of the tensor
+  type:DType;                       // data type of the tensor
+  data: [ubyte] (force_align: 8);   // raw data array if it's a constant tensor.
 }
 
 table TosaOperator {
diff --git a/src/tosa_serialization_handler.cpp b/src/tosa_serialization_handler.cpp
index 4fe152f..d153dc5 100644
--- a/src/tosa_serialization_handler.cpp
+++ b/src/tosa_serialization_handler.cpp
@@ -19,32 +19,32 @@
 using namespace tosa;
 
 TosaSerializationTensor::TosaSerializationTensor(const flatbuffers::String* name,
-                                                 const flatbuffers::Vector<int32_t>& shape,
+                                                 const flatbuffers::Vector<int32_t>* shape,
                                                  DType dtype,
-                                                 const flatbuffers::String* npy_filename)
+                                                 const flatbuffers::Vector<uint8_t>* data)
 {
     _dtype = dtype;
 
-    std::copy(shape.begin(), shape.end(), std::back_inserter(_shape));
+    std::copy(shape->begin(), shape->end(), std::back_inserter(_shape));
 
     assert(name);
     _name = name->str();
 
-    if (npy_filename)
+    if (data)
     {
-        _npy_filename = npy_filename->str();
+        std::copy(data->begin(), data->end(), std::back_inserter(_data));
     }
 }
 
 TosaSerializationTensor::TosaSerializationTensor(std::string& name,
                                                  const std::vector<int32_t>& shape,
                                                  DType dtype,
-                                                 const std::string& npy_filename)
+                                                 const std::vector<uint8_t>& data)
 {
-    _dtype        = dtype;
-    _shape        = shape;
-    _name         = name;
-    _npy_filename = npy_filename;
+    _dtype = dtype;
+    _shape = shape;
+    _name  = name;
+    _data  = data;
 }
 
 TosaSerializationTensor::TosaSerializationTensor()
@@ -483,12 +483,12 @@
         {
             auto curr_tensor = fb_tosa_tensors->Get(j);
 
-            auto tensor_name         = curr_tensor->name();
-            auto tensor_shape        = curr_tensor->shape();
-            auto tensor_type         = curr_tensor->type();
-            auto tensor_npy_filename = curr_tensor->npy_filename();
+            auto tensor_name  = curr_tensor->name();
+            auto tensor_shape = curr_tensor->shape();
+            auto tensor_type  = curr_tensor->type();
+            auto tensor_data  = curr_tensor->data();
 
-            new_tensor = new TosaSerializationTensor(tensor_name, *tensor_shape, tensor_type, tensor_npy_filename);
+            new_tensor = new TosaSerializationTensor(tensor_name, tensor_shape, tensor_type, tensor_data);
             if (new_tensor)
             {
                 block_tensors_container.push_back(new_tensor);
@@ -734,12 +734,9 @@
             auto tensor_name  = _builder.CreateString(tensor->GetName().c_str());
             auto tensor_shape = _builder.CreateVector(tensor->GetShape());
             auto tensor_dtype = tensor->GetDtype();
-            flatbuffers::Offset<flatbuffers::String> tensor_npy_filename = 0;
-            if (!tensor->GetNpyFilePtr().empty())
-                tensor_npy_filename = _builder.CreateString(tensor->GetNpyFilePtr().c_str());
+            auto tensor_data  = _builder.CreateVector(tensor->GetData());
 
-            auto fboffset_tensor =
-                CreateTosaTensor(_builder, tensor_name, tensor_shape, tensor_dtype, tensor_npy_filename);
+            auto fboffset_tensor = CreateTosaTensor(_builder, tensor_name, tensor_shape, tensor_dtype, tensor_data);
             fboffset_block_tensors.push_back(fboffset_tensor);
         }
 
@@ -760,3 +757,234 @@
 
     return TOSA_OK;
 }
+
+void zero_pad(std::vector<uint8_t>& buf)
+{
+    while ((buf.size() % TENSOR_BUFFER_FORCE_ALIGNMENT) != 0)
+    {
+        buf.push_back(0);
+    }
+}
+
+tosa_err_t TosaSerializationHandler::ConvertF32toU8(const std::vector<float>& in, std::vector<uint8_t>& out)
+{
+    out.clear();
+    for (auto val : in)
+    {
+        uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
+        out.push_back(*val_u32 & 0xFF);
+        out.push_back((*val_u32 >> 8) & 0xFF);
+        out.push_back((*val_u32 >> 16) & 0xFF);
+        out.push_back((*val_u32 >> 24) & 0xFF);
+    }
+    zero_pad(out);
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI48toU8(const std::vector<int64_t>& in, std::vector<uint8_t>& out)
+{
+    out.clear();
+    for (auto val : in)
+    {
+        uint64_t* val_u64 = reinterpret_cast<uint64_t*>(&val);
+        out.push_back(*val_u64 & 0xFF);
+        out.push_back((*val_u64 >> 8) & 0xFF);
+        out.push_back((*val_u64 >> 16) & 0xFF);
+        out.push_back((*val_u64 >> 24) & 0xFF);
+        out.push_back((*val_u64 >> 32) & 0xFF);
+        out.push_back((*val_u64 >> 40) & 0xFF);
+    }
+    zero_pad(out);
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI32toU8(const std::vector<int32_t>& in, std::vector<uint8_t>& out)
+{
+    out.clear();
+    for (auto val : in)
+    {
+        uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
+        out.push_back(*val_u32 & 0xFF);
+        out.push_back((*val_u32 >> 8) & 0xFF);
+        out.push_back((*val_u32 >> 16) & 0xFF);
+        out.push_back((*val_u32 >> 24) & 0xFF);
+    }
+    zero_pad(out);
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI16toU8(const std::vector<int16_t>& in, std::vector<uint8_t>& out)
+{
+    out.clear();
+    for (auto val : in)
+    {
+        uint16_t* val_u16 = reinterpret_cast<uint16_t*>(&val);
+        out.push_back(*val_u16 & 0xFF);
+        out.push_back((*val_u16 >> 8) & 0xFF);
+    }
+    zero_pad(out);
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI8toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out)
+{
+    out.clear();
+    for (auto val : in)
+    {
+        uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
+        out.push_back(*val_u8);
+    }
+    zero_pad(out);
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertBooltoU8(const std::vector<bool>& in, std::vector<uint8_t>& out)
+{
+    out.clear();
+    for (auto val : in)
+    {
+        uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
+        out.push_back(*val_u8);
+    }
+    zero_pad(out);
+    return TOSA_OK;
+}
+
+tosa_err_t
+    TosaSerializationHandler::ConvertU8toF32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<float>& out)
+{
+    out.clear();
+    if (in.size() < out_size * sizeof(float))
+    {
+        printf("TosaSerializationHandler::ConvertU8toF32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+               out_size * sizeof(float));
+        return TOSA_USER_ERROR;
+    }
+    for (int i = 0; i < out_size; i++)
+    {
+        uint32_t byte0   = in[i * sizeof(float)];
+        uint32_t byte1   = in[i * sizeof(float) + 1];
+        uint32_t byte2   = in[i * sizeof(float) + 2];
+        uint32_t byte3   = in[i * sizeof(float) + 3];
+        uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
+        float* val_fp32  = reinterpret_cast<float*>(&val_u32);
+        out.push_back(*val_fp32);
+    }
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertU8toI48(const std::vector<uint8_t>& in,
+                                                    uint32_t out_size,
+                                                    std::vector<int64_t>& out)
+{
+    out.clear();
+    if (in.size() < out_size * 6 /* sizeof(int48) */)
+    {
+        printf("TosaSerializationHandler::ConvertU8toI48(): uint8 buffer size %ld must >= target size %d\n", in.size(),
+               out_size * 6);
+        return TOSA_USER_ERROR;
+    }
+    for (int i = 0; i < out_size; i++)
+    {
+        uint64_t byte0   = in[i * 6];
+        uint64_t byte1   = in[i * 6 + 1];
+        uint64_t byte2   = in[i * 6 + 2];
+        uint64_t byte3   = in[i * 6 + 3];
+        uint64_t byte4   = in[i * 6 + 4];
+        uint64_t byte5   = in[i * 6 + 5];
+        bool sign        = ((byte5 >> 7) & 1) == 1 ? true : false;
+        uint64_t val_u64 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24) + (byte4 << 32) + (byte5 << 40);
+        if (sign)
+        {
+            uint64_t sext_mask = (0xFFFFUL << 48);
+            val_u64 |= sext_mask;
+        }
+        int64_t* val_i64 = reinterpret_cast<int64_t*>(&val_u64);
+        out.push_back(*val_i64);
+    }
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertU8toI32(const std::vector<uint8_t>& in,
+                                                    uint32_t out_size,
+                                                    std::vector<int32_t>& out)
+{
+    out.clear();
+    if (in.size() < out_size * sizeof(int32_t))
+    {
+        printf("TosaSerializationHandler::ConvertU8toI32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+               out_size * sizeof(int32_t));
+        return TOSA_USER_ERROR;
+    }
+    for (int i = 0; i < out_size; i++)
+    {
+        uint32_t byte0   = in[i * sizeof(int32_t)];
+        uint32_t byte1   = in[i * sizeof(int32_t) + 1];
+        uint32_t byte2   = in[i * sizeof(int32_t) + 2];
+        uint32_t byte3   = in[i * sizeof(int32_t) + 3];
+        uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
+        int32_t* val_i32 = reinterpret_cast<int32_t*>(&val_u32);
+        out.push_back(*val_i32);
+    }
+    return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertU8toI16(const std::vector<uint8_t>& in,
+                                                    uint32_t out_size,
+                                                    std::vector<int16_t>& out)
+{
+    out.clear();
+    if (in.size() < out_size * sizeof(int16_t))
+    {
+        printf("TosaSerializationHandler::ConvertU8toI16(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+               out_size * sizeof(int16_t));
+        return TOSA_USER_ERROR;
+    }
+    for (int i = 0; i < out_size; i++)
+    {
+        uint16_t byte0   = in[i * sizeof(int16_t)];
+        uint16_t byte1   = in[i * sizeof(int16_t) + 1];
+        uint16_t val_u16 = byte0 + (byte1 << 8);
+        int16_t* val_i16 = reinterpret_cast<int16_t*>(&val_u16);
+        out.push_back(*val_i16);
+    }
+    return TOSA_OK;
+}
+
+tosa_err_t
+    TosaSerializationHandler::ConvertU8toI8(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out)
+{
+    out.clear();
+    if (in.size() < out_size * sizeof(int8_t))
+    {
+        printf("TosaSerializationHandler::ConvertU8toI8(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+               out_size * sizeof(bool));
+        return TOSA_USER_ERROR;
+    }
+    for (int i = 0; i < out_size; i++)
+    {
+        uint8_t val_u8 = in[i];
+        int8_t* val_i8 = reinterpret_cast<int8_t*>(&val_u8);
+        out.push_back(*val_i8);
+    }
+    return TOSA_OK;
+}
+
+tosa_err_t
+    TosaSerializationHandler::ConvertU8toBool(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<bool>& out)
+{
+    out.clear();
+    if (in.size() < out_size * sizeof(bool))
+    {
+        printf("TosaSerializationHandler::ConvertU8toBool(): uint8 buffer size %ld must >= target size %ld\n",
+               in.size(), out_size * sizeof(bool));
+        return TOSA_USER_ERROR;
+    }
+    for (int i = 0; i < out_size; i++)
+    {
+        uint8_t val_u8 = in[i];
+        bool* val_bool = reinterpret_cast<bool*>(&val_u8);
+        out.push_back(*val_bool);
+    }
+    return TOSA_OK;
+}