gd._operators.push_back(op_offset);
}
+void exportBiasAdd(loco::FeatureBiasAdd *node, FlatBufferBuilder &builder, SerializedModelData &gd)
+{
+ uint32_t op_idx = gd.registerBuiltinOpcode(tflite::BuiltinOperator_ADD);
+ std::vector<int32_t> inputs_vec{get_tensor_index(node->value()), get_tensor_index(node->bias())};
+ std::vector<int32_t> outputs_vec{get_tensor_index(static_cast<loco::Node *>(node))};
+ auto inputs = builder.CreateVector(inputs_vec);
+ auto outputs = builder.CreateVector(outputs_vec);
+ auto options = CreateAddOptions(builder); // dummy option
+ auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
+ tflite::BuiltinOptions_AddOptions, options.Union());
+ gd._operators.push_back(op_offset);
+}
+
/// @brief Export CONCATENATION of **TWO** tensors only
void exportConcat(loco::TensorConcat *node, FlatBufferBuilder &builder, SerializedModelData &gd)
{
{
exportBiasAdd(biasadd, builder, data);
}
+ else if (auto *biasadd = dynamic_cast<loco::FeatureBiasAdd *>(node))
+ {
+ exportBiasAdd(biasadd, builder, data);
+ }
else
{
assert(false && "unsupported node found");
return gd._node_to_type[node->input()];
}
-tflite::TensorType getOpResultType(loco::BiasAdd<loco::Domain::Tensor> *node, TypeContext &gd)
+template <loco::Domain D>
+tflite::TensorType getOpResultType(loco::BiasAdd<D> *node, TypeContext &gd)
{
tflite::TensorType value_type = gd._node_to_type[node->value()];
tflite::TensorType bias_type = gd._node_to_type[node->bias()];
NODE(TensorConcat)
NODE(BiasEncode)
NODE(TensorBiasAdd)
+ NODE(FeatureBiasAdd)
#undef NODE
private:
return value_shape;
}
+// TODO Reduce code duplication
+ShapeDescription getOpResultShape(loco::FeatureBiasAdd *node, ShapeContext &gd)
+{
+ const ShapeDescription &value_shape = gd._node_to_shape[node->value()];
+ const ShapeDescription &bias_shape = gd._node_to_shape[node->bias()];
+
+ // Bias should be rank 1
+ assert(bias_shape._dims.size() == 1);
+
+ // Channel count coherency for proper broadcast
+ // Feature in T/F Lite uses NHWC layout
+ assert(bias_shape._dims[0] == value_shape._dims[3]);
+
+ return value_shape;
+}
+
namespace
{
NODE(TensorConcat)
NODE(BiasEncode)
NODE(TensorBiasAdd)
+ NODE(FeatureBiasAdd)
#undef NODE
private: