summaryrefslogtreecommitdiff
path: root/compiler/enco/core/src/Support/Debugging.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/enco/core/src/Support/Debugging.cpp')
-rw-r--r--compiler/enco/core/src/Support/Debugging.cpp533
1 files changed, 533 insertions, 0 deletions
diff --git a/compiler/enco/core/src/Support/Debugging.cpp b/compiler/enco/core/src/Support/Debugging.cpp
new file mode 100644
index 000000000..bd65a27d8
--- /dev/null
+++ b/compiler/enco/core/src/Support/Debugging.cpp
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2018 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.
+ */
+
+#include "Debugging.h"
+
+#include <pp/LinearDocument.h>
+#include <pp/MultiLineTextUtils.h>
+
+#include <stack>
+
+#include <iostream>
+
+#define DEBUGGING_API_P(NAME, TYPE, VAR) \
+ static void _##NAME(const TYPE *); \
+ void NAME(long p) { NAME(reinterpret_cast<const TYPE *>(p)); } \
+ void NAME(const TYPE *p) \
+ { \
+ if (p == nullptr) \
+ { \
+ std::cout << "(nullptr)" << std::endl; \
+ } \
+ else \
+ { \
+ _##NAME(p); \
+ } \
+ } \
+ void _##NAME(const TYPE *VAR)
+
+namespace
+{
+
+class SectionBuilder
+{
+public:
+ SectionBuilder(const std::string &tag) : _tag{tag}
+ {
+ // DO NOTHING
+ }
+
+public:
+ template <typename Callback> pp::LinearDocument build(Callback cb) const
+ {
+ pp::LinearDocument res;
+
+ res.append(_tag, " {");
+ res.indent();
+
+ cb(res);
+
+ res.unindent();
+ res.append("}");
+
+ return res;
+ }
+
+private:
+ std::string _tag;
+};
+
+template <typename Callback>
+pp::LinearDocument operator<<(const SectionBuilder &builder, Callback cb)
+{
+ return builder.build(std::forward<Callback>(cb));
+}
+
+SectionBuilder section(const std::string &tag) { return SectionBuilder{tag}; }
+}
+
+/**
+ * SECTION: Bag
+ */
+namespace
+{
+
+pp::LinearDocument describe(const coco::Bag *bag)
+{
+ pp::LinearDocument doc;
+
+ doc.append("addr: ", bag);
+ doc.append("size: ", bag->size());
+ // TODO Print Read
+ // TODO Print Update
+ // TODO Print Dep
+ return doc;
+}
+
+} // namespace
+
+DEBUGGING_API_P(enco_dump_all_bags, coco::Module, m)
+{
+ for (uint32_t n = 0; n < m->entity()->bag()->size(); ++n)
+ {
+ auto bag = m->entity()->bag()->at(n);
+ assert(bag != nullptr);
+
+ auto set = [bag](pp::LinearDocument &doc) { doc.append(describe(bag)); };
+ auto desc = section("bag").build(set);
+
+ std::cout << desc << std::endl;
+ }
+}
+
+/**
+ * SECTION: Object
+ */
+namespace
+{
+std::string op_kind(const coco::Op *op);
+
+/**
+ * @brief Return the def(producer) type of object
+ */
+std::string def_kind(const coco::Def *def)
+{
+ if (def)
+ {
+ if (auto instr = dynamic_cast<coco::Instr *>(def->producer()))
+ {
+ std::stringstream ss;
+
+ if (auto eval = instr->asEval())
+ {
+ ss << op_kind(eval->op()) << "(" << instr << ")";
+ return ss.str();
+ }
+ else if (instr->asCopy())
+ {
+ ss << "Copy(" << instr << ")";
+ return ss.str();
+ }
+ else if (instr->asShuffle())
+ {
+ ss << "Shuffle(" << instr << ")";
+ return ss.str();
+ }
+ }
+ else
+ {
+ return "(unknown)";
+ }
+ }
+
+ return "(none)";
+}
+
+pp::LinearDocument describe(const coco::Object *obj)
+{
+ pp::LinearDocument doc;
+
+ doc.append("addr: ", obj);
+ doc.append("bag: ", obj->bag());
+ doc.append("producer: ", def_kind(obj->def()));
+ // TODO Show Uses
+ // TODO Show FeatureObject/KernelObect info
+
+ return doc;
+}
+
+} // namespace
+
+DEBUGGING_API_P(enco_dump_all_objects, coco::Module, m)
+{
+ for (uint32_t n = 0; n < m->entity()->object()->size(); ++n)
+ {
+ auto obj = m->entity()->object()->at(n);
+ assert(obj != nullptr);
+
+ auto set = [obj](pp::LinearDocument &doc) { doc.append(describe(obj)); };
+ auto desc = section("object").build(set);
+
+ std::cout << desc << std::endl;
+ }
+}
+
+/**
+ * SECTION: Op
+ */
+namespace
+{
+
+struct OpTree
+{
+public:
+ OpTree(const coco::Op *op) : _op{op}
+ {
+ // DO NOTHING
+ }
+
+public:
+ const coco::Op *root(void) const { return _op; }
+
+private:
+ const coco::Op *_op;
+};
+
+std::string op_kind(const coco::Op *op)
+{
+ struct OpKind : public coco::Op::Visitor<std::string>
+ {
+ std::string visit(const coco::Load *) override { return "Load"; }
+ std::string visit(const coco::Conv2D *) override { return "Conv2D"; }
+ std::string visit(const coco::MaxPool2D *) override { return "MaxPool2D"; }
+ std::string visit(const coco::AvgPool2D *) override { return "AvgPool2D"; }
+ std::string visit(const coco::PadF *) override { return "PadF"; }
+ std::string visit(const coco::ReLU *) override { return "ReLU"; }
+ std::string visit(const coco::Add *) override { return "Add"; }
+ std::string visit(const coco::Mul *) override { return "Mul"; }
+ std::string visit(const coco::ConcatF *) override { return "ConcatF"; }
+ std::string visit(const coco::Sub *) override { return "Sub"; }
+ std::string visit(const coco::Sqrt *) override { return "Sqrt"; }
+ std::string visit(const coco::Div *) override { return "Div"; }
+ };
+
+ OpKind v;
+
+ return op->accept(v);
+}
+
+pp::LinearDocument describe(const coco::Padding2D *pad)
+{
+ pp::LinearDocument doc;
+
+ doc.append("top: ", pad->top());
+ doc.append("bottom: ", pad->bottom());
+ doc.append("left: ", pad->left());
+ doc.append("right: ", pad->right());
+
+ return doc;
+}
+
+pp::LinearDocument describe(const coco::Stride2D *stride)
+{
+ pp::LinearDocument doc;
+
+ doc.append("vertical: ", stride->vertical());
+ doc.append("horizontal ", stride->horizontal());
+
+ return doc;
+}
+
+pp::LinearDocument describe(const coco::Conv2D *conv)
+{
+ pp::LinearDocument doc;
+
+ doc.append("arg: ", conv->arg());
+ doc.append("ker: ", conv->ker());
+ doc.append("group: ", conv->group());
+
+ if (auto pad = conv->pad())
+ {
+ auto set = [pad](pp::LinearDocument &doc) { doc.append(describe(pad)); };
+ auto desc = section("pad").build(set);
+ doc.append(desc);
+ }
+
+ if (auto stride = conv->stride())
+ {
+ auto set = [stride](pp::LinearDocument &doc) { doc.append(describe(stride)); };
+ auto desc = section("stride").build(set);
+ doc.append(desc);
+ }
+
+ return doc;
+}
+
+pp::LinearDocument describe(const coco::Op *op)
+{
+ pp::LinearDocument doc;
+
+ doc.append("addr: ", op);
+ doc.append("kind: ", op_kind(op));
+ doc.append("parent(instr): ", op->parent());
+ doc.append("up(op): ", op->up());
+
+ if (auto conv = op->asConv2D())
+ {
+ auto set = [conv](pp::LinearDocument &doc) { doc.append(describe(conv)); };
+ auto desc = section("conv2d").build(set);
+ doc.append(desc);
+ }
+ else if (auto load = op->asLoad())
+ {
+ auto set = [load](pp::LinearDocument &doc) { doc.append(describe(load->object())); };
+ auto desc = section("load").build(set);
+ doc.append(desc);
+ }
+
+ return doc;
+}
+
+pp::LinearDocument describe(const OpTree &t, bool verbose = false)
+{
+ pp::LinearDocument doc;
+
+ struct Frame
+ {
+ public:
+ Frame(const coco::Op *op) : _op{op}, _indicator{0}
+ {
+ // op SHOULD BE valid
+ assert(_op != nullptr);
+ }
+
+ public:
+ /**
+ * @brief Return a pointer to coco::Op of interest
+ */
+ const coco::Op *op(void) const { return _op; }
+
+ /**
+ * @brief Return the indicator
+ *
+ * Let's assume that the arity of a coco::Op of interest is N
+ * INDICATOR 0 -> Print the op itself
+ * INDICATOR 1 -> Print the first argument
+ * ...
+ * INDICATOR N -> Print the N-th argument
+ * INDICATOR N + 1 -> Done
+ */
+ uint32_t indicator(void) const { return _indicator; }
+
+ public:
+ void advance(void) { _indicator += 1; }
+
+ private:
+ const coco::Op *_op;
+ uint32_t _indicator;
+ };
+
+ std::stack<Frame> stack;
+
+ stack.emplace(t.root());
+
+ while (stack.size() > 0)
+ {
+ auto op = stack.top().op();
+ uint32_t indicator = stack.top().indicator();
+
+ if (indicator == 0)
+ {
+ doc.append(op_kind(op), " (", op, ")");
+
+ doc.indent();
+ stack.top().advance();
+
+ // TODO Need to update it to better design for verbose flag
+ if (verbose)
+ {
+ auto set = [op](pp::LinearDocument &doc) { doc.append(describe(op)); };
+ auto desc = section("op").build(set);
+ doc.append(desc);
+ }
+ }
+ else if (indicator < op->arity() + 1)
+ {
+ stack.top().advance();
+ stack.emplace(op->arg(indicator - 1));
+ }
+ else
+ {
+ assert(indicator == op->arity() + 1);
+ doc.unindent();
+ stack.pop();
+ }
+ }
+
+ return doc;
+}
+
+} // namespace
+
+DEBUGGING_API_P(enco_dump_op, coco::Op, op)
+{
+ {
+ std::cout << describe(op) << std::endl;
+ }
+}
+
+DEBUGGING_API_P(enco_dump_op_tree, coco::Op, op)
+{
+ {
+ std::cout << describe(OpTree(op)) << std::endl;
+ }
+}
+
+DEBUGGING_API_P(enco_dump_all_ops, coco::Module, m)
+{
+ SectionBuilder section_builder{"op"};
+
+ for (uint32_t n = 0; n < m->entity()->op()->size(); ++n)
+ {
+ auto op = m->entity()->op()->at(n);
+ assert(op != nullptr);
+
+ auto desc = section("op").build([op](pp::LinearDocument &doc) { doc.append(describe(op)); });
+
+ std::cout << desc << std::endl;
+ }
+}
+
+/**
+ * SECTION: Instr
+ */
+namespace
+{
+
+std::string kind(const coco::Instr *ins)
+{
+ struct InstrKind : public coco::Instr::Visitor<std::string>
+ {
+ std::string visit(const coco::Eval *) override { return "Eval"; }
+ std::string visit(const coco::Copy *) override { return "Copy"; }
+ std::string visit(const coco::Shuffle *) override { return "Shuffle"; }
+ };
+
+ InstrKind v;
+
+ return ins->accept(v);
+}
+
+pp::LinearDocument describe(const coco::Instr *ins, bool verbose = false)
+{
+ pp::LinearDocument doc;
+
+ doc.append("addr: ", ins);
+ doc.append("kind: ", kind(ins));
+ doc.append("parent: ", ins->parent());
+
+ // TODO Need to update it to better design for verbose flag
+ if (verbose)
+ {
+ if (auto eval = ins->asEval())
+ {
+ auto optset = [eval, verbose](pp::LinearDocument &doc) {
+ doc.append(describe(OpTree(eval->op()), verbose));
+ };
+ auto optdesc = section("op").build(optset);
+ doc.append(optdesc);
+
+ auto outset = [eval](pp::LinearDocument &doc) { doc.append(describe(eval->out())); };
+ auto outdesc = section("out").build(outset);
+ doc.append(outdesc);
+ }
+ else if (auto copy = ins->asCopy())
+ {
+ auto from = [copy](pp::LinearDocument &doc) { doc.append(describe(copy->from())); };
+ auto into = [copy](pp::LinearDocument &doc) { doc.append(describe(copy->into())); };
+
+ auto fdesc = section("from").build(from);
+ doc.append(fdesc);
+
+ auto idesc = section("into").build(into);
+ doc.append(idesc);
+ }
+ }
+
+ return doc;
+}
+
+} // namespace
+
+DEBUGGING_API_P(enco_dump_all_instrs, coco::Module, m)
+{
+ for (uint32_t n = 0; n < m->entity()->instr()->size(); ++n)
+ {
+ auto ins = m->entity()->instr()->at(n);
+ assert(ins != nullptr);
+
+ auto setter = [ins](pp::LinearDocument &doc) { doc.append(describe(ins)); };
+ auto desc = section("instr").build(setter);
+
+ std::cout << desc << std::endl;
+ }
+}
+
+DEBUGGING_API_P(enco_dump_all_instrs_v, coco::Module, m)
+{
+ for (uint32_t n = 0; n < m->entity()->instr()->size(); ++n)
+ {
+ auto ins = m->entity()->instr()->at(n);
+ assert(ins != nullptr);
+
+ auto setter = [ins](pp::LinearDocument &doc) { doc.append(describe(ins, true)); };
+ auto desc = section("instr").build(setter);
+
+ std::cout << desc << std::endl;
+ }
+}
+
+DEBUGGING_API_P(enco_dump_instr, coco::Instr, ins)
+{
+ auto setter = [ins](pp::LinearDocument &doc) { doc.append(describe(ins, true)); };
+ auto desc = section("instr").build(setter);
+
+ std::cout << desc << std::endl;
+}
+
+/**
+ * SECTION: Block
+ */
+namespace
+{
+
+pp::LinearDocument describe(const coco::Block *blk)
+{
+ pp::LinearDocument doc;
+
+ for (auto ins = blk->instr()->head(); ins; ins = ins->next())
+ {
+ auto setter = [ins](pp::LinearDocument &doc) { doc.append(describe(ins)); };
+ auto desc = section("instr").build(setter);
+ doc.append(desc);
+ }
+
+ return doc;
+}
+
+} // namespace
+
+DEBUGGING_API_P(enco_dump_block, coco::Block, blk) { std::cout << describe(blk) << std::endl; }