[enco] Introduce OpBuilder (#2012)
author박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Fri, 26 Oct 2018 07:33:01 +0000 (16:33 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 26 Oct 2018 07:33:01 +0000 (16:33 +0900)
This commit introduces OpBuilder class, and simplifies the
implementation of caffe frontend using OpBuilder.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
contrib/enco/frontend/caffe/src/Frontend.cpp

index 0a4b5f1..3cf8024 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <map>
 #include <set>
+#include <deque>
 #include <string>
 
 #include <cassert>
@@ -121,6 +122,107 @@ private:
 LoadOpBuilder build_load(coco::Module *m) { return LoadOpBuilder{m}; }
 LoadOpBuilder build_load(const std::unique_ptr<coco::Module> &m) { return build_load(m.get()); }
 
+class OpBuilder
+{
+public:
+  OpBuilder(coco::Module *module) : _module{module}
+  {
+    // module SHOULD BE valid
+    assert(_module != nullptr);
+  }
+
+public:
+  /**
+   * @brief Return true if the internal stack is empty
+   */
+  bool empty(void) const { return _stack.empty(); }
+
+  /**
+   * @brief Return the operation at the top of the internal stack
+   */
+  coco::Op *top(void) const
+  {
+    assert(_stack.size() > 0);
+    return _stack.front();
+  }
+
+  /**
+   * @brief Push op onto the internal stack
+   *
+   * BEFORE| Stack
+   * AFTER | Op; Stack
+   */
+  OpBuilder &push(coco::Op *op)
+  {
+    _stack.push_front(op);
+    return (*this);
+  }
+
+  /**
+   * @brief Create "Load" op and push it onto the internal stack
+   *
+   * BEFORE| Stack
+   * AFTER | Load(obj); Stack
+   */
+  OpBuilder &load(coco::Object *obj)
+  {
+    push(build_load(_module).with(obj));
+    return (*this);
+  }
+
+  /**
+   * @brief Create "Add" op and push it onto the internal stack
+   *
+   * BEFORE| Left; Right; Stack
+   * AFTER | Add(Left, Right); Stack
+   */
+  OpBuilder &add(void) { return binary<coco::Add>(); }
+
+  /**
+   * @brief Create "Mul" op and push it onto the internal stack
+   *
+   * BEFORE| Left; Right; Stack
+   * AFTER | Mul(Left, Right); Stack
+   */
+  OpBuilder &mul(void) { return binary<coco::Mul>(); }
+
+  /**
+   * @brief Pop op from the internal stack
+   *
+   * BEFORE| Op; Stack
+   * AFTER | Stack
+   */
+  coco::Op *pop(void)
+  {
+    assert(_stack.size() > 0);
+    auto op = _stack.front();
+    _stack.pop_front();
+    return op;
+  }
+
+private:
+  template <typename ConcreteOp> OpBuilder &binary()
+  {
+    assert(_stack.size() >= 2);
+    auto left = pop();
+    auto right = pop();
+
+    auto op = _module->entity()->op()->create<ConcreteOp>();
+    op->left(left);
+    op->right(right);
+    push(op);
+
+    return (*this);
+  }
+
+private:
+  coco::Module *_module;
+  std::deque<coco::Op *> _stack;
+};
+
+OpBuilder op_builder(coco::Module *m) { return OpBuilder{m}; }
+OpBuilder op_builder(const std::unique_ptr<coco::Module> &m) { return op_builder(m.get()); }
+
 } // namespace
 
 Frontend::Frontend() : _prototxt{new ::caffe::NetParameter}, _caffemodel{new ::caffe::NetParameter}
@@ -359,13 +461,7 @@ enco::Bundle Frontend::load(void) const
             coco::FeatureLayouts::BCHW::create(morph::caffe::as_feature_shape(ofm_shape)));
 
         // Create Op
-        auto conv_load = build_load(m).with(ofm_obj);
-        auto bias_load = build_load(m).with(bias_obj);
-
-        auto bias_add = m->entity()->op()->create<coco::Add>();
-
-        bias_add->left(conv_load);
-        bias_add->right(bias_load);
+        auto bias_add = op_builder(m).load(bias_obj).load(ofm_obj).add().pop();
 
         // Create Instr
         auto bias_add_ins = m->entity()->instr()->create<coco::Eval>();
@@ -647,12 +743,7 @@ enco::Bundle Frontend::load(void) const
         assert(lhs->module() != nullptr);
 
         auto m = lhs->module();
-        auto add = m->entity()->op()->create<coco::Add>();
-
-        add->left(lhs);
-        add->right(rhs);
-
-        return add;
+        return op_builder(m).push(rhs).push(lhs).add().pop();
       };
 
       registry[EltwiseParameter_EltwiseOp_PROD] = [](coco::Op *lhs, coco::Op *rhs) -> coco::Op * {
@@ -667,12 +758,7 @@ enco::Bundle Frontend::load(void) const
         assert(lhs->module() != nullptr);
 
         auto m = lhs->module();
-        auto mul = m->entity()->op()->create<coco::Mul>();
-
-        mul->left(lhs);
-        mul->right(rhs);
-
-        return mul;
+        return op_builder(m).push(rhs).push(lhs).mul().pop();
       };
 
       // coeff is not supported, yet