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 options = CreateAddOptions(builder, to_circle_actfunc(node->fusedActivationFunction()));
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
circle::BuiltinOptions_AddOptions, options.Union());
gd._operators.push_back(op_offset);
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 = CreateMulOptions(builder); // dummy option
+ auto options = CreateMulOptions(builder, to_circle_actfunc(node->fusedActivationFunction()));
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
circle::BuiltinOptions_MulOptions, options.Union());
gd._operators.push_back(op_offset);
#include <loco/Service/ShapeInference.h>
+namespace
+{
+
+template <class TFLBIN> void init_fused_act_func(TFLBIN *);
+
+template <> inline void init_fused_act_func(locoex::TFLAdd *node)
+{
+ node->fusedActivationFunction(locoex::FusedActFunc::NONE);
+}
+
+template <> inline void init_fused_act_func(locoex::TFLMul *node)
+{
+ node->fusedActivationFunction(locoex::FusedActFunc::NONE);
+}
+
+template <> inline void init_fused_act_func(locoex::TFLSub *)
+{
+ /* TFLSub does not have fused activation function. Thus, nothing to do */
+}
+
+template <> inline void init_fused_act_func(locoex::TFLDiv *)
+{
+ /* TFLDic does not have fused activation function. Thus, nothing to do */
+}
+
+} // namespace
+
namespace exo
{
origin->lhs(nullptr);
origin->rhs(nullptr);
+ init_fused_act_func(tfl_bin);
+
return true;
}
else if (loco::shape_get(origin).domain() == loco::Domain::Feature)
origin->lhs(nullptr);
origin->rhs(nullptr);
+ init_fused_act_func(tfl_new);
+
return true;
}
else
#include <cassert>
+namespace
+{
+
+inline void init_fused_act_func(locoex::TFLAdd *node)
+{
+ node->fusedActivationFunction(locoex::FusedActFunc::NONE);
+}
+
+} // namespace
+
namespace exo
{
tfl_add->y(bias_dec);
+ // fused activation function
+ init_fused_act_func(tfl_add);
+
// handling output
auto fea_enc = make_feature_encode<FeatureLayout::NHWC>(tfl_add);
class TFLAdd final : public FixedArityNode<2, TFLNodeImpl<TFLOpcode::ADD>>
{
public:
- TFLAdd() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
loco::Node *y(void) const { return at(1)->node(); }
void y(loco::Node *node) { at(1)->node(node); }
+
+ FusedActFunc fusedActivationFunction() const { return _fused_act_fun; }
+ void fusedActivationFunction(FusedActFunc fused_act_fun) { _fused_act_fun = fused_act_fun; }
+
+private:
+ FusedActFunc _fused_act_fun = FusedActFunc::UNDEFINED;
};
/**
class TFLMul final : public FixedArityNode<2, TFLNodeImpl<TFLOpcode::MUL>>
{
public:
- TFLMul() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
loco::Node *y(void) const { return at(1)->node(); }
void y(loco::Node *node) { at(1)->node(node); }
+
+ FusedActFunc fusedActivationFunction() const { return _fused_act_fun; }
+ void fusedActivationFunction(FusedActFunc fused_act_fun) { _fused_act_fun = fused_act_fun; }
+
+private:
+ FusedActFunc _fused_act_fun = FusedActFunc::UNDEFINED;
};
class TFLRelu final : public FixedArityNode<1, TFLNodeImpl<TFLOpcode::RELU>>
bool TFLNodeSummaryBuilder::summary(const locoex::TFLAdd *node, locop::NodeSummary &s) const
{
+ auto fused = node->fusedActivationFunction();
+ assert(fused != locoex::FusedActFunc::UNDEFINED);
+
s.args().append("x", tbl()->lookup(node->x()));
s.args().append("y", tbl()->lookup(node->y()));
+ s.args().append("fused_activation_function", to_str(node->fusedActivationFunction()));
s.state(locop::NodeSummary::State::Complete);
return true;
}
bool TFLNodeSummaryBuilder::summary(const locoex::TFLMul *node, locop::NodeSummary &s) const
{
+ auto fused = node->fusedActivationFunction();
+ assert(fused != locoex::FusedActFunc::UNDEFINED);
+
s.args().append("x", tbl()->lookup(node->x()));
s.args().append("y", tbl()->lookup(node->y()));
+ s.args().append("fused_activation_function", to_str(node->fusedActivationFunction()));
s.state(locop::NodeSummary::State::Complete);
return true;
}
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 options = CreateAddOptions(builder, to_tflite_actfunc(node->fusedActivationFunction()));
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
tflite::BuiltinOptions_AddOptions, options.Union());
gd._operators.push_back(op_offset);
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 = CreateMulOptions(builder); // dummy option
+ auto options = CreateMulOptions(builder, to_tflite_actfunc(node->fusedActivationFunction()));
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
tflite::BuiltinOptions_MulOptions, options.Union());
gd._operators.push_back(op_offset);