* limitations under the License.
*/
+#include "Relu6.h"
+
#include "GraphBuilder.h"
+#include "Knob.h"
+
+#include "IR/TFRelu6.h"
#include <stdex/Memory.h>
/**
* @brief GraphBuilder for Relu6 node
*/
-class Relu6GraphBuilder final : public GraphBuilder
+class Relu6GraphBuilder final : public Relu6GraphBuilderBase
{
public:
- bool validate(const tensorflow::NodeDef &) const override;
void build(const tensorflow::NodeDef &, GraphBuilderContext *) const override;
};
const TensorName _name;
};
-bool Relu6GraphBuilder::validate(const tensorflow::NodeDef &node) const
+class TFRelu6GraphUpdate final : public GraphUpdate
+{
+public:
+ TFRelu6GraphUpdate(moco::tf::TFRelu6 *node, const TensorName &&name) : _node(node), _name(name) {}
+
+ void input(const SymbolTable *) const override;
+
+private:
+ moco::tf::TFRelu6 *_node;
+ const TensorName _name;
+};
+
+bool Relu6GraphBuilderBase::validate(const tensorflow::NodeDef &node) const
{
// ReLU6 node SHOULD have only one input
if (node.input_size() != 1)
{
assert(context != nullptr);
+ if (moco::tf::get<moco::tf::Knob::ImportAsTFRelu6>())
+ {
+ Relu6GraphBuilderImpl<ImportTarget::TensorFlow> builder;
+ return builder.build(node, context);
+ }
+ else
+ {
+ Relu6GraphBuilderImpl<ImportTarget::Canonical> builder;
+ return builder.build(node, context);
+ }
+}
+
+void Relu6GraphBuilderImpl<ImportTarget::Canonical>::build(const tensorflow::NodeDef &node,
+ GraphBuilderContext *context) const
+{
loco::Graph *graph = context->graph();
SymbolTable *tensor_names = context->tensor_names();
UpdateQueue *updates = context->updates();
updates->enroll(std::move(update));
}
+void Relu6GraphBuilderImpl<ImportTarget::TensorFlow>::build(const tensorflow::NodeDef &node,
+ GraphBuilderContext *context) const
+{
+ loco::Graph *graph = context->graph();
+ SymbolTable *tensor_names = context->tensor_names();
+ UpdateQueue *updates = context->updates();
+
+ // Create a "TFRelu6" node for Relu
+ auto relu_node = graph->nodes()->create<moco::tf::TFRelu6>();
+
+ // register string-name to node
+ TensorName output_name(node.name(), 0);
+ tensor_names->enroll(output_name, relu_node);
+
+ // Queue node input update
+ auto update = stdex::make_unique<TFRelu6GraphUpdate>(relu_node, TensorName(node.input(0)));
+ updates->enroll(std::move(update));
+}
+
void ReLU6GraphUpdate::input(const SymbolTable *table) const
{
loco::Node *target = table->node(_name);
_node->input(target);
}
+void TFRelu6GraphUpdate::input(const SymbolTable *table) const
+{
+ loco::Node *target = table->node(_name);
+ _node->features(target);
+}
+
} // namespace tf
} // namespace moco
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_RELU6_H__
+#define __OP_RELU6_H__
+
+#include "GraphBuilder.h"
+#include "GraphBuilderContext.h"
+#include "ImportTarget.h"
+
+namespace moco
+{
+namespace tf
+{
+
+struct Relu6GraphBuilderBase : public GraphBuilder
+{
+ virtual ~Relu6GraphBuilderBase() = default;
+
+ bool validate(const tensorflow::NodeDef &) const final;
+};
+
+template <ImportTarget T> class Relu6GraphBuilderImpl;
+
+template <>
+struct Relu6GraphBuilderImpl<ImportTarget::Canonical> final : public Relu6GraphBuilderBase
+{
+ void build(const tensorflow::NodeDef &, GraphBuilderContext *) const final;
+};
+
+template <>
+struct Relu6GraphBuilderImpl<ImportTarget::TensorFlow> final : public Relu6GraphBuilderBase
+{
+ void build(const tensorflow::NodeDef &, GraphBuilderContext *) const final;
+};
+
+} // namespace tf
+} // namespace moco
+
+#endif // __OP_RELU6_H__
* limitations under the License.
*/
+#include "Relu6.h"
+
+#include "IR/TFRelu6.h"
+
#include "TestHelper.h"
#include "Importer.h"
#include <memory>
+using namespace moco::tf;
using namespace moco::tf::test;
namespace
tensorflow::GraphDef graph_def;
EXPECT_TRUE(plier::tf::parse_graphdef(relu6_01_pbtxtdata, graph_def));
+
+ // Test "Relu6GraphBuilderImpl<ImportTarget::Canonical>"
+ {
+ // TODO: fix indentation
+ // clang-format off
+
+ using ReluGraphBuilder = Relu6GraphBuilderImpl<ImportTarget::Canonical>;
+
+ moco::tf::GraphBuilderRegistry r{&moco::tf::GraphBuilderRegistry::get()};
+ r.add("Relu6", stdex::make_unique<ReluGraphBuilder>());
+ moco::tf::Importer importer{&r};
+
std::unique_ptr<loco::Graph> graph = importer.import(signature, graph_def);
// what to test:
ASSERT_NE(relu6_node, nullptr);
ASSERT_NE(relu6_node->input(), nullptr);
+ // clang-format on
+ }
+
+ // Test "ReluGraphBuilderImpl<ImportTarget::TensorFlow>"
+ {
+ using ReluGraphBuilder = Relu6GraphBuilderImpl<ImportTarget::TensorFlow>;
+
+ moco::tf::GraphBuilderRegistry r{&moco::tf::GraphBuilderRegistry::get()};
+ r.add("Relu6", stdex::make_unique<ReluGraphBuilder>());
+ moco::tf::Importer importer{&r};
+
+ std::unique_ptr<loco::Graph> graph = importer.import(signature, graph_def);
+
+ // what to test:
+ // - there should exist TFRelu6
+ // - features node should not be null
+
+ auto relu_node = moco::tf::test::find_first_node_bytype<moco::tf::TFRelu6>(graph.get());
+
+ ASSERT_NE(relu_node, nullptr);
+ ASSERT_NE(relu_node->features(), nullptr);
+ }
}