diff options
Diffstat (limited to 'compiler/coco/core')
161 files changed, 11148 insertions, 0 deletions
diff --git a/compiler/coco/core/CMakeLists.txt b/compiler/coco/core/CMakeLists.txt new file mode 100644 index 000000000..8c6844733 --- /dev/null +++ b/compiler/coco/core/CMakeLists.txt @@ -0,0 +1,25 @@ +file(GLOB_RECURSE SOURCES "src/*.cpp") +file(GLOB_RECURSE TESTS "src/*.test.cpp") +list(REMOVE_ITEM SOURCES ${TESTS}) + +add_library(coco_core SHARED ${SOURCES}) +target_include_directories(coco_core PUBLIC include) +# NOTE Some coco_core PUBLIC headers include angkor headers +target_link_libraries(coco_core PUBLIC angkor) +target_link_libraries(coco_core PRIVATE pepper_assert) +target_link_libraries(coco_core PRIVATE stdex) +# Let's apply nncc common compile options +# NOTE This will enable strict compilation (warnings as error). +# Please refer to top-level CMakeLists.txt for details +target_link_libraries(coco_core PRIVATE nncc_common) + +if(NOT ENABLE_TEST) + return() +endif(NOT ENABLE_TEST) + +# Google Test is required for internal testing +nnas_find_package(GTest REQUIRED) + +GTest_AddTest(coco_core_test ${TESTS}) +target_link_libraries(coco_core_test coco_core) +target_link_libraries(coco_core_test stdex) diff --git a/compiler/coco/core/include/coco/ADT/DLinkedList.h b/compiler/coco/core/include/coco/ADT/DLinkedList.h new file mode 100644 index 000000000..e3c275041 --- /dev/null +++ b/compiler/coco/core/include/coco/ADT/DLinkedList.h @@ -0,0 +1,288 @@ +/* + * 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. + */ + +#ifndef __COCO_ADT_DLINKED_LIST_H__ +#define __COCO_ADT_DLINKED_LIST_H__ + +#include <cassert> +#include <type_traits> + +namespace coco +{ + +// **CAUTION** Child SHOULD inherit DLinkedList<Child, Parent>::Node +template <typename Child, typename Parent> struct DLinkedList +{ + /// @brief A hook for Child-Join event + static void joined(Parent *, Child *); + /// @brief A hook for Child-Leave event + static void leaving(Parent *, Child *); + + class Head + { + public: + Head(Parent *parent) : _parent{parent} + { + _head = nullptr; + _tail = nullptr; + } + + public: + Head(const Head &) = delete; + Head(Head &&) = delete; + + public: + Child *head(void) const { return _head; } + Child *tail(void) const { return _tail; } + + public: + bool empty(void) const + { + if (_head == nullptr) + { + assert(_head == _tail); + return true; + } + + assert(_head != nullptr); + assert(_tail != nullptr); + return false; + } + + public: + void enlist(Child *child) + { + assert((child->prev() == nullptr) || (child->prev()->parent() == _parent)); + assert((child->next() == nullptr) || (child->next()->parent() == _parent)); + + if (empty()) + { + _head = child; + _tail = child; + } + else + { + if (child->next() == _head) + { + // _child is a new head + assert(child->prev() == nullptr); + _head = child; + } + + if (child->prev() == _tail) + { + // _child is a new tail + assert(child->next() == nullptr); + _tail = child; + } + } + + // Update parent-child relation + child->parent(_parent); + + // Notify Child-Joining event + joined(_parent, child); + } + + public: + void delist(Child *child) + { + assert(child->parent() == _parent); + assert(!empty()); + + // Notify Child-Leaving event + leaving(_parent, child); + + if (child == _head) + { + _head = child->next(); + } + + if (child == _tail) + { + _tail = child->prev(); + } + + // Update parent-child relation + child->parent(nullptr); + } + + public: + void prepend(Child *child) + { + if (empty()) + { + enlist(child); + } + else + { + child->insertBefore(_head); + } + } + + public: + void append(Child *child) + { + if (empty()) + { + enlist(child); + } + else + { + child->insertAfter(_tail); + } + } + + private: + Parent *const _parent; + + private: + Child *_head; + Child *_tail; + }; + + // NOTE Client SHOULD implement this static method + static Head *head(Parent *); + + class Node + { + public: + friend class Head; + + public: + Node() + { + static_assert(std::is_base_of<Node, Child>::value, + "Type `Child` must be subclass of `Node`."); + + _prev = nullptr; + _next = nullptr; + } + + public: + virtual ~Node() + { + // Each Child should unlink itself on destruction + // + // NOTE detach invokes "leaving" hook which may access the internal of each Child, + // so it is not safe to invoke detach here + assert(parent() == nullptr); + } + + public: + Parent *parent(void) const { return _parent; } + + private: + Child *curr(void) { return reinterpret_cast<Child *>(this); } + const Child *curr(void) const { return reinterpret_cast<const Child *>(this); } + + public: + Child *prev(void) const { return _prev; } + Child *next(void) const { return _next; } + + public: + void insertBefore(Node *next) + { + assert(next != nullptr); + assert(next->parent() != nullptr); + assert(head(next->parent()) != nullptr); + + assert(_prev == nullptr); + assert(_next == nullptr); + + // Update the link of the current node + _prev = next->prev(); + _next = next->curr(); + + if (auto prev = next->prev()) + { + prev->_next = curr(); + } + next->_prev = curr(); + + // Update parent-child relation + assert(parent() == nullptr); + head(next->parent())->enlist(curr()); + assert(parent() == next->parent()); + } + + public: + void insertAfter(Node *prev) + { + assert(prev != nullptr); + assert(prev->parent() != nullptr); + assert(head(prev->parent()) != nullptr); + + assert(_prev == nullptr); + assert(_next == nullptr); + + // Update the link of the current node + _prev = prev->curr(); + _next = prev->next(); + + // Update the link of the sibling nodes + if (auto next = prev->next()) + { + next->_prev = curr(); + } + prev->_next = curr(); + + // Update parent-child relation + assert(parent() == nullptr); + head(prev->parent())->enlist(curr()); + assert(parent() == prev->parent()); + }; + + public: + void detach(void) + { + // Update parent-child relation + assert(parent() != nullptr); + assert(head(parent()) != nullptr); + head(parent())->delist(curr()); + assert(parent() == nullptr); + + // Update the link of sibling nodes + if (prev()) + { + prev()->_next = next(); + } + + if (next()) + { + next()->_prev = prev(); + } + + // Update the link of the current node + _prev = nullptr; + _next = nullptr; + } + + private: + // WARN Do NOT invoke this method outside Head::enlist + void parent(Parent *p) { _parent = p; } + + private: + // WARN Do NOT modify this field inside Node. + Parent *_parent = nullptr; + Child *_prev; + Child *_next; + }; +}; + +} // namespace coco + +#endif // __COCO_ADT_DLINKED_LIST_H__ diff --git a/compiler/coco/core/include/coco/ADT/PtrList.h b/compiler/coco/core/include/coco/ADT/PtrList.h new file mode 100644 index 000000000..37fead728 --- /dev/null +++ b/compiler/coco/core/include/coco/ADT/PtrList.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef __COCO_ADT_PTR_LIST_H__ +#define __COCO_ADT_PTR_LIST_H__ + +#include <vector> + +#include <cstdint> + +namespace coco +{ + +template <typename T> class PtrList +{ +public: + PtrList() = default; + +public: + PtrList(const PtrList &) = delete; + PtrList(PtrList &&) = delete; + +public: + virtual ~PtrList() = default; + +public: + uint32_t size(void) const { return _ptrs.size(); } + +public: + T *at(uint32_t n) const { return _ptrs.at(n); } + +public: + void insert(T *ptr) { _ptrs.emplace_back(ptr); } + +private: + std::vector<T *> _ptrs; +}; + +} // namespace coco + +#endif // __COCO_ADT_PTR_LIST_H__ diff --git a/compiler/coco/core/include/coco/ADT/PtrManager.h b/compiler/coco/core/include/coco/ADT/PtrManager.h new file mode 100644 index 000000000..2b254c70a --- /dev/null +++ b/compiler/coco/core/include/coco/ADT/PtrManager.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef __COCO_ADT_PTR_MANAGER_H__ +#define __COCO_ADT_PTR_MANAGER_H__ + +#include <vector> + +#include <memory> +#include <stdexcept> + +namespace coco +{ + +template <typename T> class PtrManager +{ +public: + /// @brief Return the number of managed objects + uint32_t size(void) const { return _ptrs.size(); } + +public: + T *at(uint32_t n) const { return _ptrs.at(n).get(); } + +protected: + template <typename U> U *take(std::unique_ptr<U> &&o) + { + auto res = o.get(); + _ptrs.emplace_back(std::move(o)); + return res; + } + +protected: + std::unique_ptr<T> release(T *ptr) + { + for (auto it = _ptrs.begin(); it != _ptrs.end(); ++it) + { + if (it->get() == ptr) + { + std::unique_ptr<T> res = std::move(*it); + _ptrs.erase(it); + return res; + } + } + + throw std::invalid_argument{"ptr"}; + } + +private: + std::vector<std::unique_ptr<T>> _ptrs; +}; + +} // namespace coco + +#endif // __COCO_ADT_PTR_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR.h b/compiler/coco/core/include/coco/IR.h new file mode 100644 index 000000000..aa7ad5727 --- /dev/null +++ b/compiler/coco/core/include/coco/IR.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_H__ +#define __COCO_IR_H__ + +#include "coco/IR/Bag.h" +#include "coco/IR/Object.h" +#include "coco/IR/FeatureLayouts.h" +#include "coco/IR/KernelLayouts.h" + +#include "coco/IR/Op.h" +#include "coco/IR/Instr.h" +#include "coco/IR/Block.h" + +#include "coco/IR/Input.h" +#include "coco/IR/Output.h" + +#include "coco/IR/Module.h" + +#endif // __COCO_IR_H__ diff --git a/compiler/coco/core/include/coco/IR/Arg.h b/compiler/coco/core/include/coco/IR/Arg.h new file mode 100644 index 000000000..fc451a231 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Arg.h @@ -0,0 +1,80 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_ARG_H__ +#define __COCO_IR_ARG_H__ + +#include "coco/IR/Bag.h" +#include "coco/IR/ElemID.h" + +#include <nncc/core/ADT/tensor/Shape.h> +#include <nncc/core/ADT/tensor/Index.h> +#include <nncc/core/ADT/tensor/Layout.h> + +#include <string> +#include <vector> + +namespace coco +{ + +/** + * @brief Base class for NN model arguments (Input/Output) + */ +class Arg +{ +public: + explicit Arg(const nncc::core::ADT::tensor::Shape &shape); + +public: + virtual ~Arg() = default; + +public: + const nncc::core::ADT::tensor::Shape &shape(void) const { return _shape; } + +public: + const std::string &name(void) const { return _name; } + void name(const std::string &s) { _name = s; } + +protected: + virtual void onTake(Bag *) { return; } + virtual void onRelease(Bag *) { return; } + +public: + Bag *bag(void) const { return _bag; } + void bag(Bag *); + +public: + ElemID &at(const nncc::core::ADT::tensor::Index &); + const ElemID &at(const nncc::core::ADT::tensor::Index &) const; + +public: + void reorder(const nncc::core::ADT::tensor::Layout &l); + template <typename LayoutImpl> void reorder(void) { reorder(LayoutImpl{}); } + +private: + nncc::core::ADT::tensor::Shape const _shape; + +private: + std::string _name; + +private: + Bag *_bag; + std::vector<ElemID> _map; +}; + +} // namespace coco + +#endif // __COCO_IR_ARG_H__ diff --git a/compiler/coco/core/include/coco/IR/Bag.h b/compiler/coco/core/include/coco/IR/Bag.h new file mode 100644 index 000000000..1c86899d7 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Bag.h @@ -0,0 +1,164 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_BAG_H__ +#define __COCO_IR_BAG_H__ + +#include "coco/IR/Entity.h" +#include "coco/IR/ObjectSet.h" +#include "coco/IR/DepSet.h" +#include "coco/IR/ReadSet.h" +#include "coco/IR/UpdateSet.h" +#include "coco/IR/Input.forward.h" +#include "coco/IR/Output.forward.h" +#include "coco/IR/Locatable.h" + +#include <set> + +#include <memory> + +namespace coco +{ + +/** + * @brief A collection of (abstracted) elements of the same type + * + * When there are N elements in a bag, we refer to N as the size of this bag, and every + * element in a bag has a unique numeric ID whose range is [0, N). + * + * NOTE 'Bag' is not a container (such as std::vector). 'Bag' just assures that there are + * N elements. It does not state about its value. + * + * NOTE coco IR treats Bag as virtual memory allocation + */ +class Bag final : public Entity +{ +public: + struct Updater : public Locatable + { + virtual ~Updater() = default; + }; + + using UpdaterSet = std::set<Updater *>; + + struct Reader : public Locatable + { + virtual ~Reader() = default; + }; + + using ReaderSet = std::set<Reader *>; + +public: + friend class Dep; + friend class Read; + friend class Update; + friend class Input; + friend class Output; + +public: + explicit Bag(uint32_t size); + +public: + ~Bag(); + +public: + uint32_t size(void) const; + +public: + bool isInput(void) const; + bool isOutput(void) const; + +public: + /// @brief Return the set of Dep links that point to this bag + const DepSet *deps(void) const; + /// @brief Return the set of Read links that point to this bag + const ReadSet *reads(void) const; + /// @brief Return the set of Update links that point to this bag + const UpdateSet *updates(void) const; + +public: + /// @brief Return a valid pointer if this bag is marked as an input of the model + Input *input(void) const { return _input; } + /// @brief Return a valid pointer if this bag is marked as an output of the model + Output *output(void) const { return _output; } + +public: + /** + * @brief Replace all the occurence of a bag (except those in Input/Output) with another bag + * + * NOTE reaplceWith(b) works correctly only when b is neither Input nor Output + */ + void replaceWith(Bag *b); + + /** + * @brief Replace all the occurence of a bag in Object with another bag + * + * NOTE Unlike replaceWith(b), replaceAllDepsWith(b) has no restriction + */ + void replaceAllDepsWith(Bag *); + +private: + // "mutable_" prefix is deliberately introduced below to avoid resolution issue. + // + // Let's assume that two "deps" are overloaded in Bag as follows: + // class Bag + // { + // private: + // DepSet *deps(void); <-- 1 + // public: + // const DepSet *deps(void) const; <-- 2 + // }; + // + // C++ compiler tries to invoke method 1 unless a bag itself is const. Thus, any "deps" calls + // over non-const bags except those calls from friend classes will introduce build error. + + // WARN Only Dep is allowed to access this method + DepSet *mutable_deps(void) { return &_deps; } + // WARN Only Read is allowed to access this method + ReadSet *mutable_reads(void) { return &_reads; } + // WARN Only Update is allowed to access this method + UpdateSet *mutable_updates(void) { return &_updates; } + +private: + // WARN Only Input is allowed to access this method + void input(Input *i) { _input = i; } + // WARN Only Output is allowed to access this method + void output(Output *o) { _output = o; } + +private: + uint32_t _size; + + /** @brief Links to dependent Object(s) */ + DepSet _deps; + /** @brief Direct reads (not through Object) */ + ReadSet _reads; + /** @brief Direct updates (not through Object) */ + UpdateSet _updates; + + Input *_input = nullptr; + Output *_output = nullptr; +}; + +/// @brief Return a set of objects that depends on a given bag +ObjectSet dependent_objects(const Bag *); +/// @brief Return a set of readers that reads a given bag +Bag::ReaderSet readers(const Bag *); +/// @brief Return a set of updaters that updates a given bag +Bag::UpdaterSet updaters(const Bag *); + +} // namespace coco + +#endif // __COCO_IR_BAG_H__ diff --git a/compiler/coco/core/include/coco/IR/BagManager.h b/compiler/coco/core/include/coco/IR/BagManager.h new file mode 100644 index 000000000..6ba644101 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/BagManager.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_BAG_MANAGER_H__ +#define __COCO_IR_BAG_MANAGER_H__ + +#include "coco/IR/Bag.h" +#include "coco/IR/EntityBuilder.h" + +#include "coco/ADT/PtrManager.h" + +namespace coco +{ + +class BagManager final : public PtrManager<Bag>, public EntityBuilder +{ +public: + BagManager(Module *m = nullptr) { module(m); } + +public: + Bag *create(uint32_t size); + +public: + /** + * @brief Destroy (= deallocate) a Bag entity + * + * NOTE A Bag SHOULD BE detached from IR before destruction + */ + void destroy(Bag *b); +}; + +} // namespace coco + +#endif // __COCO_IR_BAG_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/Block.forward.h b/compiler/coco/core/include/coco/IR/Block.forward.h new file mode 100644 index 000000000..6d1793141 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Block.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_BLOCK_FORWARD_H__ +#define __COCO_IR_BLOCK_FORWARD_H__ + +namespace coco +{ + +class Block; + +} // namespace coco + +#endif // __COCO_IR_BLOCK_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Block.h b/compiler/coco/core/include/coco/IR/Block.h new file mode 100644 index 000000000..1bb3f47c7 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Block.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_BLOCK_H__ +#define __COCO_IR_BLOCK_H__ + +#include "coco/IR/Module.forward.h" +#include "coco/IR/Block.forward.h" +#include "coco/IR/BlockIndex.h" +#include "coco/IR/Instr.h" +#include "coco/IR/Entity.h" + +#include "coco/ADT/DLinkedList.h" + +namespace coco +{ + +using BlockList = DLinkedList<Block, Module>::Head; + +/** + * @brief A unit of (grouped) instructions + * + * Block allows backend to manage a set of instructions as one unit, which is useful for H/W that + * has a restriction on code size + */ +class Block final : public DLinkedList<Block, Module>::Node, public Entity +{ +public: + friend void DLinkedList<Block, Module>::joined(Module *, Block *); + friend void DLinkedList<Block, Module>::leaving(Module *, Block *); + +public: + Block() : _instr{this} + { + // DO NOTHING + } + +public: + Block(const Block &) = delete; + Block(Block &&) = delete; + +public: + ~Block() + { + if (parent()) + { + detach(); + } + } + +public: + InstrList *instr(void) { return &_instr; } + const InstrList *instr(void) const { return &_instr; } + +public: + const BlockIndex &index(void) const { return _index; } + +private: + BlockIndex _index; + DLinkedList<Instr, Block>::Head _instr; +}; + +} // namespace coco + +#endif // __COCO_IR_BLOCK_H__ diff --git a/compiler/coco/core/include/coco/IR/BlockIndex.h b/compiler/coco/core/include/coco/IR/BlockIndex.h new file mode 100644 index 000000000..7deabf488 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/BlockIndex.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_BLOCK_INDEX_H__ +#define __COCO_IR_BLOCK_INDEX_H__ + +#include <cstdint> + +namespace coco +{ + +/** + * @brief A BlockIndex denotes the index of a block in a block list + */ +class BlockIndex final +{ +private: + static const uint32_t undefined = 0xffffffff; + +public: + BlockIndex() : _value{undefined} + { + // DO NOTHING + } + +public: + BlockIndex(uint32_t value) { set(value); } + +public: + bool valid(void) const { return _value != undefined; } + +public: + uint32_t value(void) const { return _value; } + +public: + void set(uint32_t value); + void reset(void) { _value = undefined; } + +private: + uint32_t _value; +}; + +static inline bool operator<(const BlockIndex &lhs, const BlockIndex &rhs) +{ + return lhs.value() < rhs.value(); +} + +} // namespace coco + +#endif // __COCO_IR_BLOCK_INDEX_H__ diff --git a/compiler/coco/core/include/coco/IR/BlockManager.h b/compiler/coco/core/include/coco/IR/BlockManager.h new file mode 100644 index 000000000..f81f1f22b --- /dev/null +++ b/compiler/coco/core/include/coco/IR/BlockManager.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_BLOCK_MANAGER_H__ +#define __COCO_IR_BLOCK_MANAGER_H__ + +#include "coco/IR/Block.h" +#include "coco/IR/EntityBuilder.h" + +#include "coco/ADT/PtrManager.h" + +namespace coco +{ + +class BlockManager final : public PtrManager<Block>, public EntityBuilder +{ +public: + BlockManager(Module *m = nullptr) { module(m); } + +public: + Block *create(void); + +public: + /** + * @brief Free 'Block' object + * + * NOTE Block SHOULD be detached from any list before it is destructed + */ + void destroy(Block *); +}; + +} // namespace coco + +#endif // __COCO_IR_BLOCK_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/Def.forward.h b/compiler/coco/core/include/coco/IR/Def.forward.h new file mode 100644 index 000000000..93878c658 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Def.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_DEF_FORWARD_H__ +#define __COCO_IR_DEF_FORWARD_H__ + +namespace coco +{ + +class Def; + +} // namespace coco + +#endif // __COCO_IR_DEF_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Def.h b/compiler/coco/core/include/coco/IR/Def.h new file mode 100644 index 000000000..d9b1567e5 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Def.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_DEF_H__ +#define __COCO_IR_DEF_H__ + +#include "coco/IR/Object.h" + +namespace coco +{ + +class Def final +{ +public: + Def(Object::Producer *producer) : _producer{producer} + { + // DO NOTHING + } + +public: + ~Def() { value(nullptr); } + +public: + Object *value(void) const { return _value; } + +public: + void value(Object *value); + +public: + Object::Producer *producer(void) const { return _producer; } + +private: + Object *_value = nullptr; + Object::Producer *_producer = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_DEF_H__ diff --git a/compiler/coco/core/include/coco/IR/Dep.forward.h b/compiler/coco/core/include/coco/IR/Dep.forward.h new file mode 100644 index 000000000..596ee3126 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Dep.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_DEP_FORWARD_H__ +#define __COCO_IR_DEP_FORWARD_H__ + +namespace coco +{ + +class Dep; + +} // namespace coco + +#endif // __COCO_IR_DEP_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Dep.h b/compiler/coco/core/include/coco/IR/Dep.h new file mode 100644 index 000000000..645c3befe --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Dep.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_DEP_H__ +#define __COCO_IR_DEP_H__ + +#include "coco/IR/Bag.h" +#include "coco/IR/Object.forward.h" + +namespace coco +{ + +/** + * @brief A Dep represents the edge between a Bag and its dependent Object + * + * WARNING A Dep will update dependent Object set (stored BagInfo) only when + * users properly initialize object and link values. + */ +class Dep final +{ +public: + Dep() = default; + +public: + Dep(const Dep &) = delete; + Dep(Dep &&) = delete; + +public: + ~Dep(); + +public: + Bag *bag(void) const { return _bag; } + void bag(Bag *); + +public: + Object *object(void) const { return _object; } + void object(Object *object) { _object = object; } + +private: + Bag *_bag = nullptr; + Object *_object = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_DEP_H__ diff --git a/compiler/coco/core/include/coco/IR/DepSet.h b/compiler/coco/core/include/coco/IR/DepSet.h new file mode 100644 index 000000000..c4e2df979 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/DepSet.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_DEP_SET_H__ +#define __COCO_IR_DEP_SET_H__ + +#include "coco/IR/Dep.forward.h" + +#include <set> + +namespace coco +{ + +using DepSet = std::set<Dep *>; + +} // namespace coco + +#endif // __COCO_IR_DEP_SET_H__ diff --git a/compiler/coco/core/include/coco/IR/ElemID.h b/compiler/coco/core/include/coco/IR/ElemID.h new file mode 100644 index 000000000..7065d13eb --- /dev/null +++ b/compiler/coco/core/include/coco/IR/ElemID.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_ELEM_ID_H__ +#define __COCO_IR_ELEM_ID_H__ + +#include <cstdint> + +namespace coco +{ + +class ElemID final +{ +public: + ElemID() : _value{0xffffffff} + { + // DO NOTHING + } + +public: + explicit ElemID(uint32_t value) : _value{value} + { + // DO NOTHING + } + +public: + uint32_t value(void) const { return _value; } + +private: + uint32_t _value; +}; + +bool operator==(const ElemID &lhs, const ElemID &rhs); +bool operator<(const ElemID &lhs, const ElemID &rhs); + +} // namespace coco + +#endif // __COCO_IR_ELEM_ID_H__ diff --git a/compiler/coco/core/include/coco/IR/Entity.h b/compiler/coco/core/include/coco/IR/Entity.h new file mode 100644 index 000000000..4bf9df651 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Entity.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_ENTITY_H__ +#define __COCO_IR_ENTITY_H__ + +#include "coco/IR/Module.forward.h" + +namespace coco +{ + +/** + * @brief A base class for IR entities + * + * NOTE Each IR entity has a link to a module that it belongs to + */ +class Entity +{ +public: + friend class EntityBuilder; + +public: + virtual ~Entity() = default; + +public: + Module *module(void) const { return _module; } + +private: + // WARN Only EntityBuilder is allowed to access this method + void module(Module *m) { _module = m; } + +private: + Module *_module = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_ENTITY_H__ diff --git a/compiler/coco/core/include/coco/IR/EntityBuilder.h b/compiler/coco/core/include/coco/IR/EntityBuilder.h new file mode 100644 index 000000000..161f3f294 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/EntityBuilder.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_ENTITY_BUILDER_H__ +#define __COCO_IR_ENTITY_BUILDER_H__ + +#include "coco/IR/Entity.h" +#include "coco/IR/Module.forward.h" + +namespace coco +{ + +/** + * @brief A base class for IR entity builders + * + * NOTE Only EntityBuilder is allowed to update module field of each Entity + */ +class EntityBuilder +{ +public: + virtual ~EntityBuilder() = default; + +protected: + Module *module(void) const { return _module; } + + void module(Module *m) { _module = m; } + void modulize(Entity *entity) const { entity->module(_module); } + +private: + Module *_module = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_ENTITY_BUILDER_H__ diff --git a/compiler/coco/core/include/coco/IR/EntityManager.h b/compiler/coco/core/include/coco/IR/EntityManager.h new file mode 100644 index 000000000..e76dec7aa --- /dev/null +++ b/compiler/coco/core/include/coco/IR/EntityManager.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_ENTITY_MANAGER_H__ +#define __COCO_IR_ENTITY_MANAGER_H__ + +#include "coco/IR/BagManager.h" +#include "coco/IR/ObjectManager.h" + +#include "coco/IR/OpManager.h" +#include "coco/IR/InstrManager.h" +#include "coco/IR/BlockManager.h" + +#include "coco/IR/InputManager.h" +#include "coco/IR/OutputManager.h" + +namespace coco +{ + +/** + * @brief Meta (lifetime) manager interface + * + * EntityManager is referred as meta manager as it is a gateway to other + * managers. + */ +struct EntityManager +{ + virtual ~EntityManager() = default; + + virtual BagManager *bag(void) = 0; + virtual const BagManager *bag(void) const = 0; + + virtual ObjectManager *object(void) = 0; + virtual const ObjectManager *object(void) const = 0; + + virtual OpManager *op(void) = 0; + virtual const OpManager *op(void) const = 0; + + virtual InstrManager *instr(void) = 0; + virtual const InstrManager *instr(void) const = 0; + + virtual BlockManager *block(void) = 0; + virtual const BlockManager *block(void) const = 0; + + virtual InputManager *input(void) = 0; + virtual const InputManager *input(void) const = 0; + + virtual OutputManager *output(void) = 0; + virtual const OutputManager *output(void) const = 0; +}; + +} // namespace coco + +#endif // __COCO_IR_ENTITY_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/FeatureLayout.h b/compiler/coco/core/include/coco/IR/FeatureLayout.h new file mode 100644 index 000000000..63f02c8ba --- /dev/null +++ b/compiler/coco/core/include/coco/IR/FeatureLayout.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_FEATURE_LAYOUT_H__ +#define __COCO_IR_FEATURE_LAYOUT_H__ + +#include "coco/IR/ElemID.h" +#include "coco/IR/FeatureShape.h" + +namespace coco +{ + +/** + * @brief A FeatureLayout connects each feature index to a Bag element + * + * NOTE FeatureLayout is an immutable interface + */ +struct FeatureLayout +{ + struct ID + { + virtual ~ID() = default; + }; + + virtual ~FeatureLayout() = default; + + virtual const ID *id(void) const = 0; + + virtual const FeatureShape &shape(void) const = 0; + + uint32_t batch(void) const { return shape().batch(); } + uint32_t depth(void) const { return shape().depth(); } + uint32_t height(void) const { return shape().height(); } + uint32_t width(void) const { return shape().width(); } + + virtual ElemID at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const = 0; +}; + +} // namespace coco + +#endif // __COCO_IR_FEATURE_LAYOUT_H__ diff --git a/compiler/coco/core/include/coco/IR/FeatureLayouts.h b/compiler/coco/core/include/coco/IR/FeatureLayouts.h new file mode 100644 index 000000000..23b9c4919 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/FeatureLayouts.h @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_FEATURE_LAYOUTS_H__ +#define __COCO_IR_FEATURE_LAYOUTS_H__ + +#include "coco/IR/FeatureLayout.h" + +#include <nncc/core/ADT/feature/Layout.h> + +#include <vector> +#include <memory> + +namespace coco +{ +namespace FeatureLayouts +{ + +/** + * @brief BCHW Feature Layout + */ +class BCHW final : public FeatureLayout +{ +private: + BCHW(const FeatureShape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + static const FeatureLayout::ID *uid(void); + const FeatureLayout::ID *id(void) const override { return uid(); } + + const FeatureShape &shape(void) const override { return _shape; } + + ElemID at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const override; + +private: + FeatureShape _shape; + +public: + static std::unique_ptr<BCHW> create(const nncc::core::ADT::feature::Shape &shape); +}; + +/** + * @brief BHWC Feature Layout + */ +class BHWC : public coco::FeatureLayout +{ +private: + BHWC(const FeatureShape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + static const FeatureLayout::ID *uid(void); + const FeatureLayout::ID *id(void) const override { return uid(); } + + const FeatureShape &shape(void) const override { return _shape; } + + coco::ElemID at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const override; + +private: + FeatureShape _shape; + +public: + static std::unique_ptr<BHWC> create(const nncc::core::ADT::feature::Shape &shape); + static std::unique_ptr<BHWC> create(const FeatureShape &shape); +}; + +/** + * @brief BC (Channel-wise Channel-major) Feature Layout + * + * 1. A layout is said to be channel-wise if the following holds: + * + * For each pair of valid feature index I and J, + * at(I) == at(J) if batch(I) == batch(J) and channel(I) == channel(J) + * + * 2. A layout is said to be channel-major if the followings hold: + * + * For each pair of valid feature index I and J, + * at(I) + 1 == at(J) if batch(I) == batch(J) and channel(I) + 1 == channel(J) + * + * For each pair of valid feature index I and J, + * at(I) + 1 == at(J) if batch(I) + 1 == batch(J), channel(I) == depth - 1, and channel(J) == 0 + */ +class BC : public coco::FeatureLayout +{ +private: + BC(const FeatureShape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + static const FeatureLayout::ID *uid(void); + const FeatureLayout::ID *id(void) const override { return uid(); } + + const FeatureShape &shape(void) const override { return _shape; } + + coco::ElemID at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const override; + +private: + FeatureShape _shape; + +public: + static std::unique_ptr<BC> create(const nncc::core::ADT::feature::Shape &shape); +}; + +/** + * @brief Generic Feature Layout + */ +class Generic final : public FeatureLayout +{ +private: + Generic(const FeatureShape &shape); + +public: + static const FeatureLayout::ID *uid(void); + const FeatureLayout::ID *id(void) const override { return uid(); } + + const FeatureShape &shape(void) const override { return _shape; } + + ElemID &at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col); + ElemID at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const override; + + void reorder(const nncc::core::ADT::feature::Layout &l); + +private: + uint32_t offset(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const; + +private: + FeatureShape _shape; + +private: + std::vector<ElemID> _content; + +public: + static std::unique_ptr<Generic> create(const nncc::core::ADT::feature::Shape &shape); +}; + +} // namespace FeatureLayouts +} // namespace coco + +#endif // __COCO_IR_FEATURE_LAYOUTS_H__ diff --git a/compiler/coco/core/include/coco/IR/FeatureObject.forward.h b/compiler/coco/core/include/coco/IR/FeatureObject.forward.h new file mode 100644 index 000000000..41477e853 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/FeatureObject.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_FEATURE_OBJECT_FORWARD_H__ +#define __COCO_IR_FEATURE_OBJECT_FORWARD_H__ + +namespace coco +{ + +class FeatureObject; + +} // namespace coco + +#endif // __COCO_IR_FEATURE_OBJECT_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/FeatureObject.h b/compiler/coco/core/include/coco/IR/FeatureObject.h new file mode 100644 index 000000000..f4244d9be --- /dev/null +++ b/compiler/coco/core/include/coco/IR/FeatureObject.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_FEATURE_OBJECT_H__ +#define __COCO_IR_FEATURE_OBJECT_H__ + +#include "coco/IR/Object.h" +#include "coco/IR/FeatureShape.h" +#include "coco/IR/FeatureLayout.h" +#include "coco/IR/ElemID.h" + +#include <nncc/core/ADT/feature/Layout.h> + +#include <vector> + +namespace coco +{ + +/** + * @brief FeatureMap values (used in CNN) + */ +class FeatureObject final : public Object +{ +public: + FeatureObject() = default; + +public: + ~FeatureObject(); + +public: + Object::Kind kind(void) const override { return Object::Kind::Feature; } + +public: + FeatureObject *asFeature(void) override { return this; } + const FeatureObject *asFeature(void) const override { return this; } + +public: + const FeatureShape &shape(void) const; + +public: + const FeatureLayout *layout(void) const { return _layout.get(); } + void layout(std::unique_ptr<FeatureLayout> &&l) { _layout = std::move(l); } + +private: + std::unique_ptr<FeatureLayout> _layout; +}; + +} // namespace coco + +#endif // __COCO_IR_FEATURE_OBJECT_H__ diff --git a/compiler/coco/core/include/coco/IR/FeatureShape.h b/compiler/coco/core/include/coco/IR/FeatureShape.h new file mode 100644 index 000000000..015fc709d --- /dev/null +++ b/compiler/coco/core/include/coco/IR/FeatureShape.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_FEATURE_SHAPE_H__ +#define __COCO_IR_FEATURE_SHAPE_H__ + +#include <nncc/core/ADT/feature/Shape.h> + +namespace coco +{ + +/** + * @brief The shape of a feature map + * + * TODO Implement coco's own FeatureShape without "nncc::core::ADT::feature::Shape" + */ +class FeatureShape : public nncc::core::ADT::feature::Shape +{ +public: + FeatureShape(uint32_t depth, uint32_t height, uint32_t width) + : Shape{depth, height, width}, _batch{1} + { + // DO NOTHING + } + + FeatureShape(uint32_t batch, uint32_t depth, uint32_t height, uint32_t width) + : Shape{depth, height, width}, _batch{batch} + { + // DO NOTHING + } + + FeatureShape(const nncc::core::ADT::feature::Shape &shape) : Shape{shape}, _batch{1} + { + // DO NOTHING + } + +public: + uint32_t batch(void) const { return _batch; } + +private: + uint32_t _batch; +}; + +static inline bool operator==(const FeatureShape &lhs, const FeatureShape &rhs) +{ + return (lhs.batch() == rhs.batch()) && (lhs.depth() == rhs.depth()) && + (lhs.height() == rhs.height()) && (lhs.width() == rhs.width()); +} + +static inline bool operator!=(const FeatureShape &lhs, const FeatureShape &rhs) +{ + return !(lhs == rhs); +} + +} // namespace coco + +#endif // __COCO_IR_FEATURE_SHAPE_H__ diff --git a/compiler/coco/core/include/coco/IR/Input.forward.h b/compiler/coco/core/include/coco/IR/Input.forward.h new file mode 100644 index 000000000..4b529cddf --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Input.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INPUT_FORWARD_H__ +#define __COCO_IR_INPUT_FORWARD_H__ + +namespace coco +{ + +class Input; + +} // namespace coco + +#endif // __COCO_IR_INPUT_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Input.h b/compiler/coco/core/include/coco/IR/Input.h new file mode 100644 index 000000000..ef8e88c9d --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Input.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INPUT_H__ +#define __COCO_IR_INPUT_H__ + +#include "coco/IR/Arg.h" +#include "coco/IR/Entity.h" + +#include <nncc/core/ADT/tensor/Shape.h> +#include <nncc/core/ADT/tensor/Index.h> + +#include <string> +#include <vector> + +namespace coco +{ + +class Input final : public Arg, public Entity +{ +public: + Input(const nncc::core::ADT::tensor::Shape &shape); + +private: + void onTake(Bag *) override; + void onRelease(Bag *) override; +}; + +} // namespace coco + +#endif // __COCO_IR_INPUT_H__ diff --git a/compiler/coco/core/include/coco/IR/InputList.h b/compiler/coco/core/include/coco/IR/InputList.h new file mode 100644 index 000000000..cd6337a5a --- /dev/null +++ b/compiler/coco/core/include/coco/IR/InputList.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INPUT_LIST_H__ +#define __COCO_IR_INPUT_LIST_H__ + +#include "coco/IR/Input.h" + +#include "coco/ADT/PtrList.h" + +namespace coco +{ + +using InputList = PtrList<Input>; + +} // namespace coco + +#endif // __COCO_IR_INPUT_LIST_H__ diff --git a/compiler/coco/core/include/coco/IR/InputManager.h b/compiler/coco/core/include/coco/IR/InputManager.h new file mode 100644 index 000000000..bfbd712b5 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/InputManager.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INPUT_MANAGER_H__ +#define __COCO_IR_INPUT_MANAGER_H__ + +#include "coco/IR/Input.h" +#include "coco/IR/EntityBuilder.h" + +#include "coco/ADT/PtrManager.h" + +namespace coco +{ + +class InputManager final : public PtrManager<Input>, public EntityBuilder +{ +public: + InputManager(Module *m = nullptr) { module(m); } + +public: + Input *create(const nncc::core::ADT::tensor::Shape &); +}; + +} // namespace coco + +#endif // __COCO_IR_INPUT_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/Instr.forward.h b/compiler/coco/core/include/coco/IR/Instr.forward.h new file mode 100644 index 000000000..4043970db --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Instr.forward.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INSTR_FORWARD_H__ +#define __COCO_IR_INSTR_FORWARD_H__ + +namespace coco +{ + +// WARNING This header should be aligned with Instr.h +class Instr; + +} // namespace coco + +#endif // __COCO_IR_INSTR_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Instr.h b/compiler/coco/core/include/coco/IR/Instr.h new file mode 100644 index 000000000..fc1cc332d --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Instr.h @@ -0,0 +1,161 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INSTR_H__ +#define __COCO_IR_INSTR_H__ + +#include "coco/IR/Bag.h" +#include "coco/IR/Block.forward.h" +#include "coco/IR/Instr.forward.h" +#include "coco/IR/InstrIndex.h" +#include "coco/IR/Entity.h" + +#include "coco/ADT/DLinkedList.h" + +#include <cassert> +#include <stdexcept> + +namespace coco +{ + +#define INSTR(Name) class Name; +#include "coco/IR/Instr.lst" +#undef INSTR + +using InstrList = coco::DLinkedList<Instr, Block>::Head; + +/** + * @brief Base interface on explicit computation steps in coco IR + * + * NOTE Input/output is explicit in Instr, but implicit in Op + * NOTE Instr is may (not always) be a combination of multiple NN operations + * + * One may find a set of supported instructions from "Instrs.h" + * + * >> How to add a new base instruction in coco IR << + * + * To introduce a new instruction (whose name is INS), + * 1. Append "INSTR(INS)" to "Instr.lst" + * 2. Declare class INS which inherits Instr class in "Instrs.h" + * NOTE This class SHOULD be default constructible + * + */ +class Instr : public coco::DLinkedList<Instr, Block>::Node, public Entity +{ +public: + friend void DLinkedList<Instr, Block>::joined(Block *, Instr *); + friend void DLinkedList<Instr, Block>::leaving(Block *, Instr *); + +public: + Instr() = default; + +public: + Instr(const Instr &) = delete; + Instr(Instr &&) = delete; + +public: + virtual ~Instr() + { + if (parent()) + { + // NOTE It is safe to invoke detach here (although "Instr" is not a final class) + // as "leaving" hook accesses only the internal of "Instr" class + detach(); + } + } + +public: +#define INSTR(Name) \ + virtual Name *as##Name(void) { return nullptr; } \ + virtual const Name *as##Name(void) const { return nullptr; } +#include "coco/IR/Instr.lst" +#undef INSTR + +public: + /** + * @brief Instr visitor interface + * + * WARN Use this interface only for coco-internal classes + * (to minimize changes upon Instr extension) + */ + template <typename T> struct IVisitor + { + virtual ~IVisitor() = default; + +#define INSTR(Name) virtual T visit(const Name *) = 0; +#include "coco/IR/Instr.lst" +#undef INSTR + }; + + template <typename T> struct Visitor : public IVisitor<T> + { + virtual ~Visitor() = default; + +#define INSTR(Name) \ + T visit(const Name *) override { throw std::runtime_error{"NYI"}; } +#include "coco/IR/Instr.lst" +#undef INSTR + }; + +public: + template <typename T> T accept(IVisitor<T> *v) const + { +#define INSTR(Name) \ + if (auto ins = as##Name()) \ + { \ + return v->visit(ins); \ + } +#include "coco/IR/Instr.lst" +#undef INSTR + throw std::runtime_error{"unreachable"}; + } + + template <typename T> T accept(IVisitor<T> &v) const { return accept(&v); } + template <typename T> T accept(IVisitor<T> &&v) const { return accept(&v); } + +public: + const InstrIndex &index(void) const { return _index; } + +private: + InstrIndex _index; +}; + +/** + * @brief Return true if a given instruction is of T type + * + * @note "ins" cannot be a null pointer + */ +template <typename T> bool isa(const Instr *ins) +{ + assert(ins != nullptr); + return dynamic_cast<const T *>(ins) != nullptr; +} + +/** + * @brief Cast as a derived instruction + * + * @note "safe_cast<T>(ins)" returns a null pointer if "ins" is not of T type + * @note "safe_cast<T>(ins)" returns a null pointer if "ins" is a null pointer + */ +template <typename T> T *safe_cast(Instr *ins) +{ + // NOTE dynamic_cast<T *>(nullptr) returns nullptr + return dynamic_cast<T *>(ins); +} + +} // namespace coco + +#endif // __COCO_IR_INSTR_H__ diff --git a/compiler/coco/core/include/coco/IR/Instr.lst b/compiler/coco/core/include/coco/IR/Instr.lst new file mode 100644 index 000000000..f13a65bf2 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Instr.lst @@ -0,0 +1,9 @@ +#ifndef INSTR +#error Define INSTR first +#endif // INSTR + +// INSTR(Name) + +INSTR(Eval) +INSTR(Shuffle) +INSTR(Copy) diff --git a/compiler/coco/core/include/coco/IR/InstrIndex.h b/compiler/coco/core/include/coco/IR/InstrIndex.h new file mode 100644 index 000000000..a61d97cad --- /dev/null +++ b/compiler/coco/core/include/coco/IR/InstrIndex.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INSTR_INDEX_H__ +#define __COCO_IR_INSTR_INDEX_H__ + +#include <cstdint> + +namespace coco +{ + +/** + * @brief A InstrIndex denotes the index of an instruction in an instruction list + */ +class InstrIndex final +{ +private: + static const uint32_t undefined = 0xffffffff; + +public: + InstrIndex() : _value{undefined} + { + // DO NOTHING + } + +public: + InstrIndex(uint32_t value) { set(value); } + +public: + bool valid(void) const { return _value != undefined; } + +public: + uint32_t value(void) const { return _value; } + +public: + void set(uint32_t value); + void reset(void) { _value = undefined; } + +private: + uint32_t _value; +}; + +static inline bool operator<(const InstrIndex &lhs, const InstrIndex &rhs) +{ + return lhs.value() < rhs.value(); +} + +} // namespace coco + +#endif // __COCO_IR_INSTR_INDEX_H__ diff --git a/compiler/coco/core/include/coco/IR/InstrManager.h b/compiler/coco/core/include/coco/IR/InstrManager.h new file mode 100644 index 000000000..537467ae2 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/InstrManager.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INSTR_MANAGER_H__ +#define __COCO_IR_INSTR_MANAGER_H__ + +#include "coco/IR/Instr.h" +#include "coco/IR/Instrs.h" + +#include "coco/IR/Op.forward.h" + +#include "coco/IR/Bag.h" + +#include "coco/IR/Object.forward.h" + +#include "coco/IR/EntityBuilder.h" + +#include "coco/ADT/PtrManager.h" + +namespace coco +{ + +class InstrManager final : public PtrManager<Instr>, public EntityBuilder +{ +public: + InstrManager(Module *m = nullptr) { module(m); } + +public: + template <typename Ins> Ins *create(void); + +public: + /** + * @brief Destroy (= deallocate) an Instr instance + * + * NOTE destroy(ins) WILL NOT update ins->parent(). An Instruction SHOULD BE detacted from a + * module before destroy call + */ + void destroy(Instr *); +}; + +// +// Every instruction class SHOULD be default constructible +// +template <typename Ins> Ins *InstrManager::create(void) +{ + auto ins = new Ins; + modulize(ins); + return take(std::unique_ptr<Ins>(ins)); +} + +} // namespace coco + +#endif // __COCO_IR_INSTR_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/Instrs.h b/compiler/coco/core/include/coco/IR/Instrs.h new file mode 100644 index 000000000..9245443e9 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Instrs.h @@ -0,0 +1,175 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_INSTRS_H__ +#define __COCO_IR_INSTRS_H__ + +#include "coco/IR/Instr.h" + +#include "coco/IR/ElemID.h" + +#include "coco/IR/Bag.h" +#include "coco/IR/Object.h" + +#include "coco/IR/Def.h" +#include "coco/IR/Use.h" +#include "coco/IR/Read.h" +#include "coco/IR/Update.h" + +#include "coco/IR/Step.h" + +#include <map> + +namespace coco +{ + +/** + * @brief Evaluate an Object from a given Op + */ +class Eval final : public Instr, public Object::Producer +{ +public: + explicit Eval(); + +public: + Eval *asEval(void) override { return this; } + const Eval *asEval(void) const override { return this; } + +public: + Instr *loc(void) override { return this; } + +public: + Object *out(void) const { return _out.value(); } + void out(Object *obj) { _out.value(obj); } + +public: + Op *op(void) const { return _step.op(); } + void op(Op *op) { _step.op(op); } + +private: + Def _out; + Step _step; +}; + +/** + * @brief Index-wise element transfer between two objects + * + * Given two objects "src" and "dst" of the same kind/shape, "copy(src, dst)" + * denotes index-wise element transfer. + * + * For example, the following pseudo-code describes "copy(src, dat)" + * when both src and dst are a feature map of the shape B x C x H x W: + * + * for each valid index b, ch, row, col: + * load the "src->at(b, ch, row, col)"-th element from bag(src) + * store it as the "dst->at(b, ch, row, col)"-th element of bag(dst) + * + * In principle, "copy" is unnecessary as it is always possible to rewrite "copy" + * as a "shuffle" below. However, "shuffle"-based optimization is too heavy as it + * requires much of iterations. + */ +class Copy final : public Instr, public Object::Producer, public Object::Consumer +{ +public: + Copy() : _from{this}, _into{this} + { + // DO NOTHING + } + +public: + Copy *asCopy(void) override { return this; } + const Copy *asCopy(void) const override { return this; } + +public: + Instr *loc(void) override { return this; } + +public: + Object *from(void) const { return _from.value(); } + void from(Object *o) { _from.value(o); } + +public: + Object *into(void) const { return _into.value(); } + void into(Object *o) { _into.value(o); } + +private: + Use _from; + Def _into; +}; + +/** + * @brief Generic element transfer + */ +class Shuffle final : public Instr, public Bag::Reader, public Bag::Updater +{ +public: + Shuffle() : _from{this}, _into{this} + { + // DO NOTHING + } + +public: + Shuffle *asShuffle(void) override { return this; } + const Shuffle *asShuffle(void) const override { return this; } + +public: + Instr *loc(void) override { return this; } + +public: + Bag *from(void) const { return _from.bag(); } + void from(Bag *bag); + +public: + Bag *into(void) const { return _into.bag(); } + void into(Bag *); + +public: + /** + * @brief Return the number of Element-wise transfers + * + * NOTE size() SHOULD BE identical to range().size() + */ + uint32_t size(void) const; + + /// @brief Return a set of elements in the destination bag that Shuffle will update + std::set<ElemID> range(void) const; + +public: + /// @brief Return true if a given elem is updated after execution + bool defined(const ElemID &dst) const { return _content.find(dst) != _content.end(); } + +public: + /** + * Let M be the return of at(N). This means that N-th element in the destination + * bag will be filled with the value of M-th element in the source bag. + * + * NOTE at(n) may be undefined on partial shuffle + */ + const ElemID &at(const ElemID &dst) const { return _content.at(dst); } + +public: + void insert(const ElemID &from, const ElemID &into); + +private: + Read _from; + Update _into; + +private: + std::map<ElemID /* DST */, ElemID /* SRC */> _content; +}; + +} // namespace coco + +#endif // __COCO_IR_INSTRS_H__ diff --git a/compiler/coco/core/include/coco/IR/KernelLayout.h b/compiler/coco/core/include/coco/IR/KernelLayout.h new file mode 100644 index 000000000..49aaf1a81 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/KernelLayout.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_KERNEL_LAYOUT_H__ +#define __COCO_IR_KERNEL_LAYOUT_H__ + +#include "coco/IR/ElemID.h" + +#include <nncc/core/ADT/kernel/Shape.h> + +namespace coco +{ + +/** + * @brief A KernelLayout connectes each kernel index to an element (in a bag) + * + * NOTE KernelLayout is an immutable interface + */ +struct KernelLayout +{ + struct ID + { + virtual ~ID() = default; + }; + + virtual ~KernelLayout() = default; + + /** + * @brief Return the identifier of each layout + * + * REQUIRED + * + * Given l1 and l2 of KernelLayout * type, + * typeid(*l1) == typeif(*l2) SHOULD hold if l1->id() == l2->id() holds. + */ + virtual const ID *id(void) const = 0; + + virtual const nncc::core::ADT::kernel::Shape &shape(void) const = 0; + + virtual ElemID at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const = 0; +}; + +} // namespace coco + +#endif // __COCO_IR_KERNEL_LAYOUT_H__ diff --git a/compiler/coco/core/include/coco/IR/KernelLayouts.h b/compiler/coco/core/include/coco/IR/KernelLayouts.h new file mode 100644 index 000000000..0a04cf163 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/KernelLayouts.h @@ -0,0 +1,117 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_KERNEL_LAYOUTS_H__ +#define __COCO_IR_KERNEL_LAYOUTS_H__ + +#include "coco/IR/KernelLayout.h" + +#include <nncc/core/ADT/kernel/Layout.h> + +#include <vector> +#include <memory> + +namespace coco +{ +namespace KernelLayouts +{ + +/** + * @brief NCHW Kernel Layout + */ +class NCHW final : public KernelLayout +{ +private: + NCHW(const nncc::core::ADT::kernel::Shape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + static const KernelLayout::ID *uid(void); + const KernelLayout::ID *id(void) const override { return uid(); } + + const nncc::core::ADT::kernel::Shape &shape(void) const override { return _shape; } + + ElemID at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const override; + +private: + nncc::core::ADT::kernel::Shape _shape; + +public: + static std::unique_ptr<NCHW> create(const nncc::core::ADT::kernel::Shape &shape); +}; + +/** + * @brief NHWC Kernel Layout + */ +class NHWC final : public KernelLayout +{ +private: + NHWC(const nncc::core::ADT::kernel::Shape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + static const KernelLayout::ID *uid(void); + const KernelLayout::ID *id(void) const override { return uid(); } + + const nncc::core::ADT::kernel::Shape &shape(void) const override { return _shape; } + + ElemID at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const override; + +private: + nncc::core::ADT::kernel::Shape _shape; + +public: + static std::unique_ptr<NHWC> create(const nncc::core::ADT::kernel::Shape &shape); +}; + +/** + * @brief Generic Kernel Layout + */ +class Generic final : public KernelLayout +{ +private: + Generic(const nncc::core::ADT::kernel::Shape &shape); + +public: + static const KernelLayout::ID *uid(void); + const KernelLayout::ID *id(void) const override { return uid(); } + + const nncc::core::ADT::kernel::Shape &shape(void) const override { return _shape; } + + ElemID &at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col); + ElemID at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const override; + + void reorder(const nncc::core::ADT::kernel::Layout &l); + template <typename LayoutImpl> void reorder(void) { reorder(LayoutImpl{}); } + +private: + nncc::core::ADT::kernel::Shape _shape; + +private: + std::vector<ElemID> _content; + +public: + static std::unique_ptr<Generic> create(const nncc::core::ADT::kernel::Shape &shape); +}; + +} // namespace KernelLayouts +} // namespace coco + +#endif // __COCO_IR_KERNEL_LAYOUTS_H__ diff --git a/compiler/coco/core/include/coco/IR/KernelObject.forward.h b/compiler/coco/core/include/coco/IR/KernelObject.forward.h new file mode 100644 index 000000000..10fbac4ca --- /dev/null +++ b/compiler/coco/core/include/coco/IR/KernelObject.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_KERNEL_OBJECT_FORWARD_H__ +#define __COCO_IR_KERNEL_OBJECT_FORWARD_H__ + +namespace coco +{ + +class KernelObject; + +} // namespace coco + +#endif // __COCO_IR_KERNEL_OBJECT_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/KernelObject.h b/compiler/coco/core/include/coco/IR/KernelObject.h new file mode 100644 index 000000000..2ec0cee0b --- /dev/null +++ b/compiler/coco/core/include/coco/IR/KernelObject.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_KERNEL_OBJECT_H__ +#define __COCO_IR_KERNEL_OBJECT_H__ + +#include "coco/IR/Object.h" +#include "coco/IR/KernelLayout.h" +#include "coco/IR/ElemID.h" + +#include <nncc/core/ADT/kernel/Shape.h> +#include <nncc/core/ADT/kernel/Layout.h> + +namespace coco +{ + +/** + * @brief Convolution Kernel (in CNN) values + */ +class KernelObject final : public Object +{ +public: + KernelObject() = default; + explicit KernelObject(const nncc::core::ADT::kernel::Shape &shape); + +public: + virtual ~KernelObject(); + +public: + Object::Kind kind(void) const override { return Object::Kind::Kernel; } + +public: + KernelObject *asKernel(void) override { return this; } + const KernelObject *asKernel(void) const override { return this; } + +public: + const nncc::core::ADT::kernel::Shape &shape(void) const; + +public: + ElemID at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const; + +public: + const KernelLayout *layout(void) const { return _layout.get(); } + void layout(std::unique_ptr<KernelLayout> &&l) { _layout = std::move(l); } + +private: + std::unique_ptr<KernelLayout> _layout; +}; + +} // namespace coco + +#endif // __COCO_IR_KERNEL_OBJECT_H__ diff --git a/compiler/coco/core/include/coco/IR/Locatable.h b/compiler/coco/core/include/coco/IR/Locatable.h new file mode 100644 index 000000000..b80a4a360 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Locatable.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_LOCATABLE_H__ +#define __COCO_IR_LOCATABLE_H__ + +#include "coco/IR/Instr.forward.h" + +namespace coco +{ + +/** + * @brief Return the associated instruction if exists. + */ +struct Locatable +{ + virtual ~Locatable() = default; + + virtual Instr *loc(void) = 0; +}; + +} // namespace coco + +#endif // __COCO_IR_LOCATABLE_H__ diff --git a/compiler/coco/core/include/coco/IR/Module.forward.h b/compiler/coco/core/include/coco/IR/Module.forward.h new file mode 100644 index 000000000..94f8cc7d2 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Module.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_MODULE_FORWARD_H__ +#define __COCO_IR_MODULE_FORWARD_H__ + +namespace coco +{ + +class Module; + +} // namespace coco + +#endif // __COCO_IR_MODULE_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Module.h b/compiler/coco/core/include/coco/IR/Module.h new file mode 100644 index 000000000..9eb0b248b --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Module.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_MODULE_H__ +#define __COCO_IR_MODULE_H__ + +#include "coco/IR/EntityManager.h" +#include "coco/IR/Block.h" +#include "coco/IR/InputList.h" +#include "coco/IR/OutputList.h" + +#include <memory> + +namespace coco +{ + +/** + * @brief Top-level element of coco IR which represents a neural network + */ +class Module +{ +public: + Module() = default; + +public: + Module(const Module &) = delete; + Module(Module &&) = delete; + +public: + virtual ~Module() = default; + +public: + virtual EntityManager *entity(void) = 0; + virtual const EntityManager *entity(void) const = 0; + +public: + virtual BlockList *block(void) = 0; + virtual const BlockList *block(void) const = 0; + +public: + virtual InputList *input(void) = 0; + virtual const InputList *input(void) const = 0; + +public: + virtual OutputList *output(void) = 0; + virtual const OutputList *output(void) const = 0; + +public: + static std::unique_ptr<Module> create(void); +}; + +} // namespace coco + +#endif // __COCO_IR_MODULE_H__ diff --git a/compiler/coco/core/include/coco/IR/Object.forward.h b/compiler/coco/core/include/coco/IR/Object.forward.h new file mode 100644 index 000000000..d9a6c0422 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Object.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OBJECT_FORWARD_H__ +#define __COCO_IR_OBJECT_FORWARD_H__ + +namespace coco +{ + +class Object; + +} // namespace coco + +#endif // __COCO_IR_OBJECT_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Object.h b/compiler/coco/core/include/coco/IR/Object.h new file mode 100644 index 000000000..617e8a198 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Object.h @@ -0,0 +1,144 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OBJECT_H__ +#define __COCO_IR_OBJECT_H__ + +#include "coco/IR/Entity.h" +#include "coco/IR/Bag.h" +#include "coco/IR/Dep.h" +#include "coco/IR/Def.forward.h" +#include "coco/IR/UseSet.h" + +#include "coco/IR/FeatureObject.forward.h" +#include "coco/IR/KernelObject.forward.h" + +#include <set> + +namespace coco +{ + +/** + * @brief Base interface on all typed NN values + */ +class Object : public Entity +{ +public: + friend class Def; + friend class Use; + +public: + enum class Kind + { + Unknown, + Feature, + Kernel, + }; + +public: + struct Producer : public Bag::Updater + { + virtual ~Producer() = default; + }; + + struct Consumer : public Bag::Reader + { + virtual ~Consumer() = default; + }; + + using ConsumerSet = std::set<Consumer *>; + +public: + Object(); + +public: + virtual ~Object() = default; + +public: + virtual Kind kind(void) const { return Kind::Unknown; } + +public: + coco::Bag *bag(void) const { return _dep.bag(); } + void bag(coco::Bag *bag) { _dep.bag(bag); } + +public: + virtual FeatureObject *asFeature(void) { return nullptr; } + virtual const FeatureObject *asFeature(void) const { return nullptr; } + + virtual KernelObject *asKernel(void) { return nullptr; } + virtual const KernelObject *asKernel(void) const { return nullptr; } + +public: + Def *def(void) const; + const UseSet *uses(void) const; + +private: + /** + * @brief Update the link to a producer + * + * WARN Only Def class is allowed to access this method + */ + void def(Def *d); + + // NOTE "mutable_" prefix is introduced to avoid resolution issue similarly as in Bag + // WARN Only Use class is allowed to access this method + UseSet *mutable_uses(void); + +private: + Dep _dep; + Def *_def = nullptr; + UseSet _uses; +}; + +/** + * @brief Check whether a given object is of type T + * + * The example below shows how to use this "isa<T>" helper: + * auto obj = new FeatureObject{}; + * + * if (isa<FeatureObject>()) + * { + * std::cout << "FeatureObject" << std::endl; + * } + */ +template <typename T> bool isa(const Object *); + +/** + * @brief Cast a generic object as a specific one + * + * "cast<T>(o)" accepts only a valid object pointer "o" that "isa<T>(o)" holds + * - Then, "cast<T>(o)" always returns a valid object pointer. + */ +template <typename T> T *cast(Object *); + +/** + * @brief Cast a generic object as a specific one + * + * Unlike "cast<T>", "safe_cast<T>" accepts any object pointer + * - "safe_cast<T>(nullptr)" returns "nullptr" + * - "safe_cast<T>(o)" returns "nullptr" if "isa<T>(o)" does not hold + */ +template <typename T> T *safe_cast(Object *); + +/// @brief Return the producer of a given object if it exists +Object::Producer *producer(const Object *); + +/// @brief Return a set of consumers of a given object. +Object::ConsumerSet consumers(const Object *); + +} // namespace coco + +#endif // __COCO_IR_OBJECT_H__ diff --git a/compiler/coco/core/include/coco/IR/ObjectManager.h b/compiler/coco/core/include/coco/IR/ObjectManager.h new file mode 100644 index 000000000..a05b724ce --- /dev/null +++ b/compiler/coco/core/include/coco/IR/ObjectManager.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OBJECT_MANAGER_H__ +#define __COCO_IR_OBJECT_MANAGER_H__ + +#include "coco/IR/Object.h" +#include "coco/IR/FeatureShape.h" +#include "coco/IR/FeatureObject.h" +#include "coco/IR/KernelObject.forward.h" +#include "coco/IR/EntityBuilder.h" + +#include "coco/ADT/PtrManager.h" + +#include <nncc/core/ADT/kernel/Shape.h> + +namespace coco +{ + +class ObjectManager final : public PtrManager<Object>, public EntityBuilder +{ +public: + ObjectManager(Module *m = nullptr) { module(m); } + +public: + template <typename T> T *create(void); + +public: + /** + * @brief Destroy (= deallocate) an Object entity + * + * NOTE An Object SHOULD HAVE NO DEF & USES to be destructed + * NOTE An Object WILL BE unlinked from its dependent bag (if has) on destruction + */ + void destroy(Object *o); +}; + +} // namespace coco + +#endif // __COCO_IR_OBJECT_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/ObjectSet.h b/compiler/coco/core/include/coco/IR/ObjectSet.h new file mode 100644 index 000000000..d97781996 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/ObjectSet.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OBJECT_SET_H__ +#define __COCO_IR_OBJECT_SET_H__ + +#include "coco/IR/Object.forward.h" + +#include <set> + +namespace coco +{ + +using ObjectSet = std::set<Object *>; + +} // namespace coco + +#endif // __COCO_IR_OBJECT_SET_H__ diff --git a/compiler/coco/core/include/coco/IR/Op.forward.h b/compiler/coco/core/include/coco/IR/Op.forward.h new file mode 100644 index 000000000..9ba3c94e3 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Op.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OP_FORWARD_H__ +#define __COCO_IR_OP_FORWARD_H__ + +namespace coco +{ + +struct Op; + +} // namespace coco + +#endif // __COCO_IR_OP_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Op.h b/compiler/coco/core/include/coco/IR/Op.h new file mode 100644 index 000000000..090527e2f --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Op.h @@ -0,0 +1,255 @@ +/* + * 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. + */ + +/** + * @file Op.h + * @brief This header file declares "Op" class and several traits related with "Op" + */ +#ifndef __COCO_IR_OP_H__ +#define __COCO_IR_OP_H__ + +#include "coco/IR/Object.forward.h" +#include "coco/IR/Instr.forward.h" +#include "coco/IR/Step.forward.h" +#include "coco/IR/Part.h" +#include "coco/IR/Entity.h" + +#include <set> + +#include <stdexcept> + +namespace coco +{ + +#define OP(Name) class Name; +#include "coco/IR/Op.lst" +#undef OP + +/** + * @brief Base interface on all supported NN operations + */ +struct Op : public Entity +{ + friend class Step; + friend class Part; + + virtual ~Op(); + + /** + * @brief Return the number of arguments (# of child Ops) + */ + virtual uint32_t arity(void) const = 0; + + /** + * @brief Return N-th argument + * + * @note The behavior of arg(n) is defined only when n < artiy() + */ + virtual Op *arg(uint32_t n) const = 0; + + /** + * @brief Return a set of object(s) used during execution + * + * NOTE There is no 'def' method as Op is not allowed to define a new object + */ + virtual std::set<Object *> uses(void) const = 0; + +#define OP(Name) \ + virtual Name *as##Name(void) { return nullptr; } \ + virtual const Name *as##Name(void) const { return nullptr; } +#include "coco/IR/Op.lst" +#undef OP + + /** + * @brief Op visitor interface + * + * WARN Use this interface only for coco-internal classes + * (to minimize changes upon Op extension) + */ + template <typename T> struct IVisitor + { + virtual ~IVisitor() = default; + +#define OP(Name) virtual T visit(const Name *) = 0; +#include "coco/IR/Op.lst" +#undef OP + }; + + template <typename T> struct Visitor : public IVisitor<T> + { + virtual ~Visitor() = default; + +#define OP(Name) \ + T visit(const Name *) override { throw std::runtime_error{"NYI"}; } +#include "coco/IR/Op.lst" +#undef OP + }; + + template <typename T> T accept(IVisitor<T> *v) const + { +#define OP(Name) \ + if (auto op = as##Name()) \ + { \ + return v->visit(op); \ + } +#include "coco/IR/Op.lst" +#undef OP + throw std::runtime_error{"unreachable"}; + } + + template <typename T> T accept(IVisitor<T> &v) const { return accept(&v); } + template <typename T> T accept(IVisitor<T> &&v) const { return accept(&v); } + +public: + /** + * @brief Op mutator interface + * + * WARN Use this interface only for coco-internal classes + * (to minimize changes upon Instr extension) + */ + struct IMutator + { + virtual ~IMutator() = default; + +#define OP(Name) virtual void mutate(Name *) = 0; +#include "coco/IR/Op.lst" +#undef OP + }; + + struct Mutator : public IMutator + { + virtual ~Mutator() = default; + +#define OP(Name) \ + void mutate(Name *) override { throw std::runtime_error{"NYI"}; } +#include "coco/IR/Op.lst" +#undef OP + }; + + void accept(IMutator *m) + { +#define OP(Name) \ + if (auto op = as##Name()) \ + { \ + return m->mutate(op); \ + } +#include "coco/IR/Op.lst" +#undef OP + throw std::runtime_error{"unreachable"}; + } + + void accept(IMutator &m) { return accept(&m); } + void accept(IMutator &&m) { return accept(&m); } + +public: + Instr *parent(void) const; + + /// @brief Return a pointer to the parent Op + Op *up(void) const; + +private: + /** + * @brief A link to Instr from Op + * + * WARN Update this field only through Step + */ + Step *_step = nullptr; + + /** + * @brief A link to a parent Op + * + * WARN Update this field only through Part + * NOTE An "Op" CANNOT have a link to a parent Op if it is linked to an "Instr" + */ + Part *_part = nullptr; +}; + +/** + * @brief Op with a single argument + */ +class UnaryOp : public Op +{ +public: + explicit UnaryOp(); + +public: + UnaryOp(const UnaryOp &) = delete; + UnaryOp(UnaryOp &&) = delete; + +public: + virtual ~UnaryOp() = default; + +public: + uint32_t arity(void) const final; + Op *arg(uint32_t n) const final; + + std::set<Object *> uses(void) const final; + +public: + Op *arg(void) const { return _arg.child(); } + void arg(Op *arg) { _arg.child(arg); } + +private: + /// @brief Link to Op's argument + Part _arg; +}; + +/** + * @brief Op with two arguments + */ +class BinaryOp : public Op +{ +public: + explicit BinaryOp(); + +public: + BinaryOp(const BinaryOp &) = delete; + BinaryOp(BinaryOp &&) = delete; + +public: + virtual ~BinaryOp() = default; + +public: + uint32_t arity(void) const final; + Op *arg(uint32_t n) const final; + + std::set<Object *> uses(void) const final; + +public: + Op *left(void) const { return _left.child(); } + void left(Op *op) { _left.child(op); } + +public: + Op *right(void) const { return _right.child(); } + void right(Op *op) { _right.child(op); } + +private: + /// @brief Left-hand side (LHS) argument + Part _left; + /// @brief Right-hand side (RHS) argument + Part _right; +}; + +/** + * @brief Return the root Op from a given Op node + * + * @note root(op) == op holds for a root op + */ +Op *root(Op *); + +} // namespace coco + +#endif // __COCO_IR_OP_H__ diff --git a/compiler/coco/core/include/coco/IR/Op.lst b/compiler/coco/core/include/coco/IR/Op.lst new file mode 100644 index 000000000..a3028bde2 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Op.lst @@ -0,0 +1,19 @@ +#ifndef OP +#error OP should be defined before including this file +#endif // OP + +// OP(Name) + +OP(Load) +OP(Conv2D) +OP(MaxPool2D) +OP(AvgPool2D) +OP(PadF) +OP(ReLU) +OP(ReLU6) +OP(Add) +OP(Sqrt) +OP(Sub) +OP(Mul) +OP(Div) +OP(ConcatF) diff --git a/compiler/coco/core/include/coco/IR/OpManager.h b/compiler/coco/core/include/coco/IR/OpManager.h new file mode 100644 index 000000000..2c88867de --- /dev/null +++ b/compiler/coco/core/include/coco/IR/OpManager.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OP_MANAGER_H__ +#define __COCO_IR_OP_MANAGER_H__ + +#include "coco/IR/Op.h" +#include "coco/IR/Ops.h" + +#include "coco/IR/Instr.forward.h" + +#include "coco/IR/Object.forward.h" + +#include "coco/IR/EntityBuilder.h" + +#include "coco/ADT/PtrManager.h" + +namespace coco +{ + +class OpManager final : public PtrManager<Op>, public EntityBuilder +{ +public: + OpManager(Module *m = nullptr) { module(m); } + +public: + ~OpManager(); + +public: + template <typename T> T *create(void); + +public: + /** + * @brief Destroy (= deallocate) a Op instance + * + * NOTE destroy(op) WILL NOT update op->parent(). Client SHOULD detach op before destroy(op) call + */ + void destroy(Op *); + + /** + * @brief Destroy a Op tree + * + * @require op->parent() == nullptr && op->up() == nullptr + */ + void destroy_all(Op *); +}; + +} // namespace coco + +#endif // __COCO_IR_OP_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/Ops.h b/compiler/coco/core/include/coco/IR/Ops.h new file mode 100644 index 000000000..01ac92b7f --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Ops.h @@ -0,0 +1,412 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OPS_H__ +#define __COCO_IR_OPS_H__ + +#include "coco/IR/Op.h" +#include "coco/IR/Object.h" +#include "coco/IR/KernelObject.h" + +#include "coco/IR/Use.h" +#include "coco/IR/Part.h" + +#include "coco/IR/Padding2D.h" +#include "coco/IR/Stride2D.h" +#include "coco/IR/Window2D.h" + +namespace coco +{ + +/** + * @brief Load an Object + */ +class Load final : public Op, public Object::Consumer +{ +public: + explicit Load(); + +public: + Load(const Load &) = delete; + Load(Load &&) = delete; + +public: + uint32_t arity(void) const final; + Op *arg(uint32_t n) const final; + + std::set<Object *> uses(void) const override; + +public: + Load *asLoad(void) override { return this; } + const Load *asLoad(void) const override { return this; } + +public: + Instr *loc(void) override { return parent(); } + +public: + void object(Object *o) { _obj.value(o); } + Object *object(void) const { return _obj.value(); } + +private: + Use _obj; +}; + +/** + * @brief 2D Convolution over 3D Feature Map with 4D kernel + * + * NOTE IFM and OFM are implicit. Only 4D kernel is explicit in this class + * TODO Decide source code layout policy and extract this class if necessary + */ +class Conv2D : public Op, public Object::Consumer +{ +public: + explicit Conv2D(); + +public: + uint32_t arity(void) const final; + Op *arg(uint32_t n) const final; + + std::set<Object *> uses(void) const override; + +public: + Conv2D *asConv2D(void) override { return this; } + const Conv2D *asConv2D(void) const override { return this; } + +public: + Instr *loc(void) override { return parent(); } + +private: + Use _ker; + +public: + Op *arg(void) const { return _arg.child(); } + void arg(Op *arg) { _arg.child(arg); } + +public: + KernelObject *ker(void) const; + void ker(KernelObject *ker); + +public: + /** + * @brief Divide an input and kernel (= convolution filter) into G independent groups + * + * Given an input of shape(Ic, Ih, Iw), a kernel of shape(Kn, Kc, Kh, Kw), and group G, + * Conv2D is identical to G independent convolutions over G inputs of shape(Ic / G, Ih, Iw) + * and a kernel of shape(Kn / G, Kc, Kh, Kw) followed by concatenation. + * + * REQUIRED + * - "Ic" SHOULD BE a multiple of "G" + * - "Kc" SHOULD BE identical to "Ic /G" + * + * NOTE Depthwise convolution is a special case of group convolution where Ic == G. + */ + uint32_t group(void) const { return _group; } + void group(uint32_t g) { _group = g; } + +public: + Padding2D *pad(void) { return &_pad; } + const Padding2D *pad(void) const { return &_pad; } + +public: + Stride2D *stride(void) { return &_stride; } + const Stride2D *stride(void) const { return &_stride; } + +private: + uint32_t _group = 1; + + Padding2D _pad; + Stride2D _stride; + +private: + /// @brief Link to an argument of Conv2D operation (= IFM) + Part _arg; +}; + +/** + * @brief 2D Max Pooling + */ +class MaxPool2D final : public UnaryOp +{ +public: + explicit MaxPool2D() = default; + +public: + MaxPool2D(const MaxPool2D &) = delete; + MaxPool2D(MaxPool2D &&) = delete; + +public: + MaxPool2D *asMaxPool2D(void) override { return this; } + const MaxPool2D *asMaxPool2D(void) const override { return this; } + +public: + Window2D *window(void) { return &_window; } + const Window2D *window(void) const { return &_window; } + +public: + Stride2D *stride(void) { return &_stride; } + const Stride2D *stride(void) const { return &_stride; } + +public: + Padding2D *pad(void) { return &_pad; } + const Padding2D *pad(void) const { return &_pad; } + +private: + Window2D _window; + Stride2D _stride; + Padding2D _pad; +}; + +/** + * @brief 2D Average Pooling + */ +class AvgPool2D final : public UnaryOp +{ +public: + enum class Divisor + { + Unknown, + // Use the number of elements in each receptive field as a divisor + Static, + // Use the number of valid (non-padding) elements in each receptive field as a divisor + PaddingExcluded + }; + +public: + explicit AvgPool2D() = default; + +public: + AvgPool2D(const AvgPool2D &) = delete; + AvgPool2D(AvgPool2D &&) = delete; + +public: + AvgPool2D *asAvgPool2D(void) override { return this; } + const AvgPool2D *asAvgPool2D(void) const override { return this; } + +public: + Divisor divisor(void) const { return _divisor; } + void divisor(const Divisor &divisor) { _divisor = divisor; } + +public: + Window2D *window(void) { return &_window; } + const Window2D *window(void) const { return &_window; } + +public: + Padding2D *pad(void) { return &_pad; } + const Padding2D *pad(void) const { return &_pad; } + +public: + Stride2D *stride(void) { return &_stride; } + const Stride2D *stride(void) const { return &_stride; } + +private: + Divisor _divisor = Divisor::Unknown; + + Window2D _window; + Stride2D _stride; + Padding2D _pad; +}; + +/** + * @brief Introduce padding area + */ +class PadF final : public UnaryOp +{ +public: + explicit PadF() = default; + +public: + PadF(const PadF &) = delete; + PadF(PadF &&) = delete; + +public: + PadF *asPadF(void) override { return this; } + const PadF *asPadF(void) const override { return this; } + +public: + Padding2D *pad(void) { return &_pad; } + const Padding2D *pad(void) const { return &_pad; } + +private: + Padding2D _pad; +}; + +/** + * @brief Apply ReLU over elements + */ +class ReLU final : public UnaryOp +{ +public: + explicit ReLU() = default; + +public: + ReLU(const ReLU &) = delete; + ReLU(ReLU &&) = delete; + +public: + ReLU *asReLU(void) override { return this; } + const ReLU *asReLU(void) const override { return this; } +}; + +/** + * @brief Apply ReLU6 over elements + * @note ReLU6 is subject to change + */ +class ReLU6 final : public UnaryOp +{ +public: + explicit ReLU6() = default; + +public: + ReLU6(const ReLU6 &) = delete; + ReLU6(ReLU6 &&) = delete; + +public: + ReLU6 *asReLU6(void) override { return this; } + const ReLU6 *asReLU6(void) const override { return this; } +}; + +/** + * @brief Element-wise addition + * + * Add(L, R) is valid only when L and R have identical kind/shape/dtype + */ +class Add final : public BinaryOp +{ +public: + explicit Add() = default; + +public: + Add(const Add &) = delete; + Add(Add &&) = delete; + +public: + Add *asAdd(void) override { return this; } + const Add *asAdd(void) const override { return this; } +}; + +/** + * @brief Element-wise subtraction + * + * Sub(L, R) is valid only when L and R have identical kind/shape/dtype + */ +class Sub final : public BinaryOp +{ +public: + explicit Sub() = default; + +public: + Sub(const Sub &) = delete; + Sub(Sub &&) = delete; + +public: + Sub *asSub(void) override { return this; } + const Sub *asSub(void) const override { return this; } +}; + +/** + * @brief Element-wise multiplication + * + * Mul(L, R) is valid only when L and R have identical kind/shape/dtype + */ +class Mul final : public BinaryOp +{ +public: + explicit Mul() = default; + +public: + Mul(const Mul &) = delete; + Mul(Mul &&) = delete; + +public: + Mul *asMul(void) override { return this; } + const Mul *asMul(void) const override { return this; } +}; + +/** + * @brief Element-wise division + * + * Div(L, R) is valid only when L and R have identical kind/shape/dtype + */ +class Div final : public BinaryOp +{ +public: + explicit Div() = default; + +public: + Div(const Div &) = delete; + Div(Div &&) = delete; + +public: + Div *asDiv(void) override { return this; } + const Div *asDiv(void) const override { return this; } +}; + +/** + * @brief Concatenate two feature maps + * + * ConcatF(L, R) requires + */ +class ConcatF final : public BinaryOp +{ +public: + enum class Axis + { + Unknown = 0, + Batch = 1, + Depth = 2, + Height = 3, + Width = 4, + }; + +public: + explicit ConcatF() = default; + +public: + ConcatF(const ConcatF &) = delete; + ConcatF(ConcatF &&) = delete; + +public: + ConcatF *asConcatF(void) override { return this; } + const ConcatF *asConcatF(void) const override { return this; } + +public: + const Axis &axis(void) const { return _axis; } + void axis(const Axis &axis) { _axis = axis; } + +private: + Axis _axis = Axis::Unknown; +}; + +/** + * @brief Apply Sqrt over elements + */ +class Sqrt final : public UnaryOp +{ +public: + explicit Sqrt() = default; + +public: + Sqrt(const Sqrt &) = delete; + Sqrt(Sqrt &&) = delete; + +public: + Sqrt *asSqrt(void) override { return this; } + const Sqrt *asSqrt(void) const override { return this; } +}; + +} // namesapce coco + +#endif // __COCO_IR_OPS_H__ diff --git a/compiler/coco/core/include/coco/IR/Output.forward.h b/compiler/coco/core/include/coco/IR/Output.forward.h new file mode 100644 index 000000000..f011400c0 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Output.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OUTPUT_FORWARD_H__ +#define __COCO_IR_OUTPUT_FORWARD_H__ + +namespace coco +{ + +class Output; + +} // namespace coco + +#endif // __COCO_IR_OUTPUT_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Output.h b/compiler/coco/core/include/coco/IR/Output.h new file mode 100644 index 000000000..3f77c131d --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Output.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OUTPUT_H__ +#define __COCO_IR_OUTPUT_H__ + +#include "coco/IR/Arg.h" +#include "coco/IR/Entity.h" + +#include <nncc/core/ADT/tensor/Shape.h> +#include <nncc/core/ADT/tensor/Index.h> + +#include <string> +#include <vector> + +namespace coco +{ + +class Output final : public Arg, public Entity +{ +public: + Output(const nncc::core::ADT::tensor::Shape &shape); + +private: + void onTake(Bag *) override; + void onRelease(Bag *) override; +}; + +} // namespace coco + +#endif // __COCO_IR_OUTPUT_H__ diff --git a/compiler/coco/core/include/coco/IR/OutputList.h b/compiler/coco/core/include/coco/IR/OutputList.h new file mode 100644 index 000000000..0e2abad75 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/OutputList.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OUTPUT_LIST_H__ +#define __COCO_IR_OUTPUT_LIST_H__ + +#include "coco/IR/Output.h" + +#include "coco/ADT/PtrList.h" + +namespace coco +{ + +using OutputList = PtrList<Output>; + +} // namespace coco + +#endif // __COCO_IR_OUTPUT_LIST_H__ diff --git a/compiler/coco/core/include/coco/IR/OutputManager.h b/compiler/coco/core/include/coco/IR/OutputManager.h new file mode 100644 index 000000000..b40380388 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/OutputManager.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_OUTPUT_MANAGER_H__ +#define __COCO_IR_OUTPUT_MANAGER_H__ + +#include "coco/IR/Output.h" +#include "coco/IR/EntityBuilder.h" + +#include "coco/ADT/PtrManager.h" + +namespace coco +{ + +class OutputManager final : public PtrManager<Output>, public EntityBuilder +{ +public: + OutputManager(Module *m = nullptr) { module(m); } + +public: + Output *create(const nncc::core::ADT::tensor::Shape &); +}; + +} // namespace coco + +#endif // __COCO_IR_OUTPUT_MANAGER_H__ diff --git a/compiler/coco/core/include/coco/IR/Padding2D.h b/compiler/coco/core/include/coco/IR/Padding2D.h new file mode 100644 index 000000000..b764656cc --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Padding2D.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_PADDING_2D_H__ +#define __COCO_IR_PADDING_2D_H__ + +#include <cstdint> + +namespace coco +{ + +class Padding2D +{ +public: + Padding2D() : _top{0}, _bottom{0}, _left{0}, _right{0} + { + // DO NOTHING + } + +public: + Padding2D(uint32_t top, uint32_t bottom, uint32_t left, uint32_t right) + : _top{top}, _bottom{bottom}, _left{left}, _right{right} + { + // DO NOTHING + } + +public: + uint32_t top(void) const { return _top; } + Padding2D &top(uint32_t value); + +public: + uint32_t bottom(void) const { return _bottom; } + Padding2D &bottom(uint32_t value); + +public: + uint32_t left(void) const { return _left; } + Padding2D &left(uint32_t value); + +public: + uint32_t right(void) const { return _right; } + Padding2D &right(uint32_t value); + +private: + uint32_t _top; + uint32_t _bottom; + uint32_t _left; + uint32_t _right; +}; + +} // namespace coco + +#endif // __COCO_IR_PADDING_2D_H__ diff --git a/compiler/coco/core/include/coco/IR/Part.forward.h b/compiler/coco/core/include/coco/IR/Part.forward.h new file mode 100644 index 000000000..642ea56b5 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Part.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_PART_FORWARD_H__ +#define __COCO_IR_PART_FORWARD_H__ + +namespace coco +{ + +class Part; + +} // namespace coco + +#endif // __COCO_IR_PART_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Part.h b/compiler/coco/core/include/coco/IR/Part.h new file mode 100644 index 000000000..72af217cc --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Part.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_PART_H__ +#define __COCO_IR_PART_H__ + +#include "coco/IR/Op.forward.h" + +namespace coco +{ + +/** + * @brief A Part represents the edge between a child Op and its parent Op + */ +class Part final +{ +public: + Part(Op *parent) : _parent{parent} + { + // DO NOTHING + } + +public: + ~Part() { child(nullptr); } + +public: + Op *child(void) const { return _child; } + void child(Op *c); + +public: + Op *parent(void) const { return _parent; } + +private: + Op *_parent = nullptr; + Op *_child = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_PART_H__ diff --git a/compiler/coco/core/include/coco/IR/Read.forward.h b/compiler/coco/core/include/coco/IR/Read.forward.h new file mode 100644 index 000000000..7fd99e212 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Read.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_READ_FORWARD_H__ +#define __COCO_IR_READ_FORWARD_H__ + +namespace coco +{ + +class Read; + +} // namespace coco + +#endif // __COCO_IR_READ_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Read.h b/compiler/coco/core/include/coco/IR/Read.h new file mode 100644 index 000000000..9f62d8bf8 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Read.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_READ_H__ +#define __COCO_IR_READ_H__ + +#include "coco/IR/Bag.h" + +namespace coco +{ + +/** + * @brief A Read represents an edge between a Bag and its Reader + */ +class Read final +{ +public: + Read(Bag::Reader *r) + { + // Initialize link and reader + reader(r); + } + +public: + ~Read(); + +public: + Bag *bag(void) const { return _bag; } + void bag(Bag *bag); + +public: + Bag::Reader *reader(void) const { return _reader; } + void reader(Bag::Reader *r) { _reader = r; } + +private: + Bag *_bag = nullptr; + Bag::Reader *_reader = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_READ_H__ diff --git a/compiler/coco/core/include/coco/IR/ReadSet.h b/compiler/coco/core/include/coco/IR/ReadSet.h new file mode 100644 index 000000000..c470c4bfd --- /dev/null +++ b/compiler/coco/core/include/coco/IR/ReadSet.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_READ_SET_H__ +#define __COCO_IR_READ_SET_H__ + +#include "coco/IR/Read.forward.h" + +#include <set> + +namespace coco +{ + +using ReadSet = std::set<Read *>; + +} // namespace coco + +#endif // __COCO_IR_READ_SET_H__ diff --git a/compiler/coco/core/include/coco/IR/Step.forward.h b/compiler/coco/core/include/coco/IR/Step.forward.h new file mode 100644 index 000000000..635069122 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Step.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_STEP_FORWARD_H__ +#define __COCO_IR_STEP_FORWARD_H__ + +namespace coco +{ + +class Step; + +} // namespace coco + +#endif // __COCO_IR_STEP_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Step.h b/compiler/coco/core/include/coco/IR/Step.h new file mode 100644 index 000000000..31dad4389 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Step.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_STEP_H__ +#define __COCO_IR_STEP_H__ + +#include "coco/IR/Op.forward.h" +#include "coco/IR/Instr.forward.h" + +namespace coco +{ + +/** + * @brief A Step denotes the edge between Op and Instr + */ +class Step final +{ +public: + explicit Step(Instr *instr) : _instr{instr} + { + // DO NOTHING + } + +public: + ~Step() { op(nullptr); } + +public: + Op *op(void) const { return _op; } + void op(Op *o); + +public: + Instr *instr(void) const { return _instr; } + +private: + Op *_op = nullptr; + Instr *_instr = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_STEP_H__ diff --git a/compiler/coco/core/include/coco/IR/Stride2D.h b/compiler/coco/core/include/coco/IR/Stride2D.h new file mode 100644 index 000000000..9e69ffa40 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Stride2D.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_STRIDE_2D_H__ +#define __COCO_IR_STRIDE_2D_H__ + +#include <cstdint> + +namespace coco +{ + +class Stride2D +{ +public: + Stride2D() : _vertical{1}, _horizontal{1} + { + // DO NOTHING + } + +public: + Stride2D(uint32_t vertical, uint32_t horizontal) : _vertical{vertical}, _horizontal{horizontal} + { + // DO NOTHING + } + +public: + uint32_t vertical(void) const { return _vertical; } + Stride2D &vertical(uint32_t value); + +public: + uint32_t horizontal(void) const { return _horizontal; } + Stride2D &horizontal(uint32_t value); + +private: + uint32_t _vertical; + uint32_t _horizontal; +}; + +} // namespace coco + +#endif // __COCO_IR_STRIDE_2D_H__ diff --git a/compiler/coco/core/include/coco/IR/Update.forward.h b/compiler/coco/core/include/coco/IR/Update.forward.h new file mode 100644 index 000000000..059f318c9 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Update.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_UPDATE_FORWARD_H__ +#define __COCO_IR_UPDATE_FORWARD_H__ + +namespace coco +{ + +class Update; + +} // namespace coco + +#endif // __COCO_IR_UPDATE_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Update.h b/compiler/coco/core/include/coco/IR/Update.h new file mode 100644 index 000000000..7cf876d74 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Update.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_UPDATE_H__ +#define __COCO_IR_UPDATE_H__ + +#include "coco/IR/Bag.h" + +namespace coco +{ + +/** + * @brief A Update represents an edge between a Bag and its Updater + */ +class Update final +{ +public: + Update(Bag::Updater *u) { updater(u); } + +public: + ~Update(); + +public: + Bag *bag(void) const { return _bag; } + void bag(Bag *bag); + +public: + Bag::Updater *updater(void) const { return _updater; } + void updater(Bag::Updater *u) { _updater = u; } + +private: + Bag *_bag = nullptr; + Bag::Updater *_updater = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_UPDATE_H__ diff --git a/compiler/coco/core/include/coco/IR/UpdateSet.h b/compiler/coco/core/include/coco/IR/UpdateSet.h new file mode 100644 index 000000000..1e772adf3 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/UpdateSet.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_UPDATE_SET_H__ +#define __COCO_IR_UPDATE_SET_H__ + +#include "coco/IR/Update.forward.h" + +#include <set> + +namespace coco +{ + +using UpdateSet = std::set<Update *>; + +} // namespace coco + +#endif // __COCO_IR_UPDATE_SET_H__ diff --git a/compiler/coco/core/include/coco/IR/Use.forward.h b/compiler/coco/core/include/coco/IR/Use.forward.h new file mode 100644 index 000000000..329430bb3 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Use.forward.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_USE_FORWARD_H__ +#define __COCO_IR_USE_FORWARD_H__ + +namespace coco +{ + +class Use; + +} // namespace coco + +#endif // __COCO_IR_USE_FORWARD_H__ diff --git a/compiler/coco/core/include/coco/IR/Use.h b/compiler/coco/core/include/coco/IR/Use.h new file mode 100644 index 000000000..c4c9b98b4 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Use.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_USE_H__ +#define __COCO_IR_USE_H__ + +#include "coco/IR/Object.h" + +namespace coco +{ + +class Use final +{ +public: + Use(Object::Consumer *use) : _value{nullptr}, _consumer{use} + { + // DO NOTHING + } + +public: + ~Use() { value(nullptr); } + +public: + Object *value(void) const { return _value; } + +public: + void value(Object *value); + +public: + Object::Consumer *consumer(void) const { return _consumer; } + +private: + Object *_value; + Object::Consumer *_consumer = nullptr; +}; + +} // namespace coco + +#endif // __COCO_IR_USE_H__ diff --git a/compiler/coco/core/include/coco/IR/UseSet.h b/compiler/coco/core/include/coco/IR/UseSet.h new file mode 100644 index 000000000..a698a733f --- /dev/null +++ b/compiler/coco/core/include/coco/IR/UseSet.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_USE_SET_H__ +#define __COCO_IR_USE_SET_H__ + +#include "coco/IR/Use.forward.h" + +#include <set> + +namespace coco +{ + +using UseSet = std::set<Use *>; + +} // namespace coco + +#endif // __COCO_IR_USE_SET_H__ diff --git a/compiler/coco/core/include/coco/IR/Window2D.h b/compiler/coco/core/include/coco/IR/Window2D.h new file mode 100644 index 000000000..a434538f3 --- /dev/null +++ b/compiler/coco/core/include/coco/IR/Window2D.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_WINDOW_2D_H__ +#define __COCO_IR_WINDOW_2D_H__ + +#include <cstdint> + +namespace coco +{ + +class Window2D +{ +public: + Window2D() : _vertical{1}, _horizontal{1} + { + // DO NOTHING + } + +public: + Window2D(uint32_t vertical, uint32_t horizontal) : _vertical{vertical}, _horizontal{horizontal} + { + // DO NOTHING + } + +public: + uint32_t height(void) const { return _vertical; } + void height(uint32_t value) { _vertical = value; } + +public: + uint32_t width(void) const { return _horizontal; } + void width(uint32_t value) { _horizontal = value; } + +private: + // TODO Rename these fields as _height and _width, respectively + uint32_t _vertical; + uint32_t _horizontal; +}; + +} // namespace coco + +#endif // __COCO_IR_WINDOW_2D_H__ diff --git a/compiler/coco/core/src/ADT/DLinkedList.test.cpp b/compiler/coco/core/src/ADT/DLinkedList.test.cpp new file mode 100644 index 000000000..563a39653 --- /dev/null +++ b/compiler/coco/core/src/ADT/DLinkedList.test.cpp @@ -0,0 +1,281 @@ +/* + * 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 "coco/ADT/DLinkedList.h" + +#include <set> + +#include <gtest/gtest.h> + +namespace +{ + +class Parent; +class Child; + +using ChildList = coco::DLinkedList<Child, Parent>::Head; + +class Parent +{ +public: + friend void coco::DLinkedList<Child, Parent>::joined(Parent *, Child *); + friend void coco::DLinkedList<Child, Parent>::leaving(Parent *, Child *); + +public: + Parent() : _list{this}, _count{0} + { + // DO NOTHING + } + +public: + ChildList *children(void) { return &_list; } + uint32_t count(void) const { return _count; } + +private: + ChildList _list; + uint32_t _count; +}; + +class Child final : public coco::DLinkedList<Child, Parent>::Node +{ +public: + ~Child() + { + if (parent()) + { + detach(); + } + } +}; + +} // namespace + +namespace coco +{ + +template <> void DLinkedList<Child, Parent>::joined(Parent *p, Child *) { p->_count += 1; } +template <> void DLinkedList<Child, Parent>::leaving(Parent *p, Child *) { p->_count -= 1; } + +template <> ChildList *DLinkedList<Child, Parent>::head(Parent *p) { return p->children(); } + +} // namespace coco + +namespace +{ +class DLinkedListTest : public ::testing::Test +{ +public: + virtual ~DLinkedListTest() + { + // NOTE Child SHOULD BE freed before parent + for (auto child : _children) + { + delete child; + } + + for (auto parent : _parents) + { + delete parent; + } + } + +protected: + template <typename T> T *create(void); + + void destroy(Child *); + +private: + std::set<::Parent *> _parents; + std::set<::Child *> _children; +}; + +template <>::Parent *DLinkedListTest::create(void) +{ + auto parent = new ::Parent; + _parents.insert(parent); + return parent; +} + +template <>::Child *DLinkedListTest::create(void) +{ + auto child = new ::Child; + _children.insert(child); + return child; +} + +void DLinkedListTest::destroy(Child *child) +{ + _children.erase(child); + delete child; +} + +} // namespace + +TEST_F(DLinkedListTest, append) +{ + auto parent = create<::Parent>(); + auto child = create<::Child>(); + + parent->children()->append(child); + + ASSERT_EQ(child->parent(), parent); + ASSERT_EQ(child->prev(), nullptr); + ASSERT_EQ(child->next(), nullptr); + + ASSERT_EQ(parent->children()->head(), child); + ASSERT_EQ(parent->children()->tail(), child); + ASSERT_EQ(parent->count(), 1); +} + +TEST_F(DLinkedListTest, insert_two_elements) +{ + auto parent = create<::Parent>(); + + ASSERT_EQ(parent->children()->head(), nullptr); + ASSERT_EQ(parent->children()->tail(), nullptr); + + auto child_1 = create<::Child>(); + + ASSERT_EQ(child_1->parent(), nullptr); + ASSERT_EQ(child_1->prev(), nullptr); + ASSERT_EQ(child_1->next(), nullptr); + + parent->children()->append(child_1); + + ASSERT_EQ(child_1->parent(), parent); + ASSERT_EQ(child_1->prev(), nullptr); + ASSERT_EQ(child_1->next(), nullptr); + + ASSERT_EQ(parent->children()->head(), child_1); + ASSERT_EQ(parent->children()->tail(), child_1); + + auto child_2 = create<::Child>(); + + ASSERT_EQ(child_2->parent(), nullptr); + ASSERT_EQ(child_2->prev(), nullptr); + ASSERT_EQ(child_2->next(), nullptr); + + child_2->insertAfter(child_1); + + ASSERT_EQ(child_2->parent(), parent); + ASSERT_EQ(child_2->prev(), child_1); + ASSERT_EQ(child_2->next(), nullptr); + + ASSERT_EQ(child_1->parent(), parent); + ASSERT_EQ(child_1->prev(), nullptr); + ASSERT_EQ(child_1->next(), child_2); + + ASSERT_EQ(parent->children()->head(), child_1); + ASSERT_EQ(parent->children()->tail(), child_2); +} + +TEST_F(DLinkedListTest, insertBefore) +{ + auto parent = create<::Parent>(); + + auto child_1 = create<::Child>(); + auto child_2 = create<::Child>(); + + parent->children()->append(child_1); + child_2->insertBefore(child_1); + + ASSERT_EQ(child_2->parent(), parent); + ASSERT_EQ(child_2->prev(), nullptr); + ASSERT_EQ(child_2->next(), child_1); + + ASSERT_EQ(child_1->parent(), parent); + ASSERT_EQ(child_1->prev(), child_2); + ASSERT_EQ(child_1->next(), nullptr); + + ASSERT_EQ(parent->children()->head(), child_2); + ASSERT_EQ(parent->children()->tail(), child_1); +} + +TEST_F(DLinkedListTest, prepend_after_append) +{ + auto parent = create<::Parent>(); + + auto child_1 = create<::Child>(); + auto child_2 = create<::Child>(); + + parent->children()->append(child_1); + parent->children()->prepend(child_2); + + ASSERT_EQ(child_2->next(), child_1); + + ASSERT_EQ(child_1->parent(), parent); + ASSERT_EQ(child_1->prev(), child_2); + ASSERT_EQ(child_1->next(), nullptr); + + ASSERT_EQ(parent->children()->head(), child_2); + ASSERT_EQ(parent->children()->tail(), child_1); +} + +TEST_F(DLinkedListTest, detach) +{ + auto parent = create<::Parent>(); + + auto child_1 = create<::Child>(); + auto child_2 = create<::Child>(); + + parent->children()->append(child_1); + parent->children()->append(child_2); + + child_1->detach(); + + ASSERT_EQ(child_1->parent(), nullptr); + ASSERT_EQ(child_1->prev(), nullptr); + ASSERT_EQ(child_1->next(), nullptr); + + ASSERT_EQ(child_2->parent(), parent); + ASSERT_EQ(child_2->prev(), nullptr); + + ASSERT_EQ(parent->children()->head(), child_2); + ASSERT_EQ(parent->children()->tail(), child_2); + + child_2->detach(); + + ASSERT_EQ(child_2->parent(), nullptr); + ASSERT_EQ(child_2->prev(), nullptr); + ASSERT_EQ(child_2->next(), nullptr); + + ASSERT_TRUE(parent->children()->empty()); + ASSERT_EQ(parent->children()->head(), nullptr); + ASSERT_EQ(parent->children()->tail(), nullptr); +} + +TEST_F(DLinkedListTest, node_destructor) +{ + auto parent = create<::Parent>(); + + auto child_1 = create<::Child>(); + auto child_2 = create<::Child>(); + + parent->children()->append(child_1); + parent->children()->append(child_2); + + destroy(child_2); + + ASSERT_EQ(parent->children()->head(), child_1); + ASSERT_EQ(parent->children()->tail(), child_1); + ASSERT_EQ(child_1->next(), nullptr); + ASSERT_EQ(child_1->prev(), nullptr); + + destroy(child_1); + + ASSERT_EQ(parent->children()->head(), nullptr); + ASSERT_EQ(parent->children()->tail(), nullptr); +} diff --git a/compiler/coco/core/src/ADT/PtrList.cpp b/compiler/coco/core/src/ADT/PtrList.cpp new file mode 100644 index 000000000..ea2beb06b --- /dev/null +++ b/compiler/coco/core/src/ADT/PtrList.cpp @@ -0,0 +1,19 @@ +/* + * 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 "coco/ADT/PtrList.h" + +// NOTE Do NOT delete this file; this file checks the completeness of 'PtrList.h' diff --git a/compiler/coco/core/src/ADT/PtrList.test.cpp b/compiler/coco/core/src/ADT/PtrList.test.cpp new file mode 100644 index 000000000..dcbad8b90 --- /dev/null +++ b/compiler/coco/core/src/ADT/PtrList.test.cpp @@ -0,0 +1,47 @@ +/* + * 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 "coco/ADT/PtrList.h" + +#include <memory> + +#include <gtest/gtest.h> + +namespace +{ +struct Object +{ +}; +} + +TEST(ADT_PTR_LIST, ctor) +{ + coco::PtrList<Object> l; + + ASSERT_EQ(l.size(), 0); +} + +TEST(ADT_PTR_LIST, insert) +{ + coco::PtrList<Object> l; + + std::unique_ptr<Object> ptr{new Object}; + + l.insert(ptr.get()); + + ASSERT_EQ(l.size(), 1); + ASSERT_EQ(l.at(0), ptr.get()); +} diff --git a/compiler/coco/core/src/ADT/PtrManager.test.cpp b/compiler/coco/core/src/ADT/PtrManager.test.cpp new file mode 100644 index 000000000..bb9056f29 --- /dev/null +++ b/compiler/coco/core/src/ADT/PtrManager.test.cpp @@ -0,0 +1,99 @@ +/* + * 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 "coco/ADT/PtrManager.h" + +#include <memory> + +#include <gtest/gtest.h> + +namespace +{ +struct Count +{ + uint32_t allocated; + uint32_t freed; + + Count() : allocated{0}, freed{0} + { + // DO NOTHING + } +}; + +class Object +{ +public: + Object(Count *count, uint32_t value) : _count{count}, _value{value} { _count->allocated += 1; } + +public: + ~Object() { _count->freed += 1; } + +public: + uint32_t value(void) const { return _value; } + +private: + Count *const _count; + +private: + uint32_t _value; +}; + +struct ObjectManager final : public coco::PtrManager<Object> +{ + Object *alloc(Count *count, uint32_t value) + { + std::unique_ptr<Object> o{new Object{count, value}}; + return take(std::move(o)); + } + + void free(Object *o) { release(o); } +}; +} + +TEST(ADT_PTR_MANAGER, usecase) +{ + Count c; + + ASSERT_EQ(c.allocated, 0); + ASSERT_EQ(c.freed, 0); + + { + ::ObjectManager mgr; + + auto obj_1 = mgr.alloc(&c, 3); + auto obj_2 = mgr.alloc(&c, 4); + + EXPECT_EQ(c.allocated, 2); + ASSERT_EQ(c.freed, 0); + + EXPECT_EQ(mgr.size(), 2); + EXPECT_EQ(mgr.at(0), obj_1); + EXPECT_EQ(mgr.at(1), obj_2); + + // Let's delete obj_1 + mgr.free(obj_1); + + EXPECT_EQ(c.allocated, 2); + ASSERT_EQ(c.freed, 1); + + EXPECT_EQ(mgr.size(), 1); + EXPECT_EQ(mgr.at(0), obj_2); + } + + // PtrManger SHOULD destruct all of the allocated object when it is destructed. + ASSERT_EQ(c.allocated, 2); + ASSERT_EQ(c.freed, 2); +} diff --git a/compiler/coco/core/src/IR.test.cpp b/compiler/coco/core/src/IR.test.cpp new file mode 100644 index 000000000..3f8c0ad34 --- /dev/null +++ b/compiler/coco/core/src/IR.test.cpp @@ -0,0 +1,303 @@ +/* + * 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 "coco/IR.h" + +#include <nncc/core/ADT/tensor/Shape.h> +#include <nncc/core/ADT/tensor/IndexEnumerator.h> +#include <nncc/core/ADT/tensor/LexicalLayout.h> + +#include <nncc/core/ADT/feature/CHWLayout.h> + +#include <nncc/core/ADT/kernel/NCHWLayout.h> + +#include <gtest/gtest.h> + +#include <set> +#include <map> +#include <string> + +using nncc::core::ADT::feature::num_elements; + +using nncc::core::ADT::kernel::num_elements; + +using nncc::core::ADT::tensor::LexicalLayout; +using nncc::core::ADT::tensor::IndexEnumerator; +using nncc::core::ADT::tensor::num_elements; + +// +// 'caffe_conv' test demonstrates how to translate the following Caffe network into coco IR: +// +// layer { +// name: "data" +// type: "Input" +// top: "data" +// input_param: { shape: { dim: 1 dim: 1 dim: 3 dim: 3 } } +// } +// +// layer { +// name: "conv" +// type: "Convolution" +// bottom: "data" +// top: "conv" +// blobs { +// ... +// shape { dim: 1 dim: 1 dim: 3 dim: 3 } +// } +// convolution_param { +// bias_term: false +// num_output: 1 +// kernel_size: 3 +// } +// } +// +TEST(IR, caffe_conv) +{ + // For inter-layer communication + std::map<std::string, coco::Bag *> bags; + std::map<std::string, nncc::core::ADT::tensor::Shape> shapes; + + std::set<std::string> top_blobs; + + // Create a module and block + auto m = coco::Module::create(); + auto blk = m->entity()->block()->create(); + + // Next, append the block to the module + m->block()->append(blk); + + // Now, the block belongs to the module (and has no sibling) + ASSERT_EQ(blk->parent(), m.get()); + ASSERT_EQ(blk->next(), nullptr); + ASSERT_EQ(blk->prev(), nullptr); + + // The head and tail points to the appended block + ASSERT_EQ(m->block()->head(), blk); + ASSERT_EQ(m->block()->tail(), blk); + + // Let's translate the first 'Input' layer + { + using nncc::core::ADT::tensor::Shape; + + const Shape shape{1, 1, 3, 3}; + + auto bag = m->entity()->bag()->create(num_elements(shape)); + auto input = m->entity()->input()->create(shape); + + input->bag(bag); + input->name("data"); + + // Caffe uses lexical layout for tensors + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + const static LexicalLayout l{}; + const auto offset = static_cast<uint32_t>(l.offset(shape, e.current())); + + input->at(e.current()) = coco::ElemID{offset}; + } + + m->input()->insert(input); + + bags["data"] = bag; + shapes["data"] = shape; + + top_blobs = {"data"}; + } + + // Next, translate 'Convolution' layer + { + using nncc::core::ADT::feature::CHWLayout; + using nncc::core::ADT::kernel::NCHWLayout; + + const nncc::core::ADT::feature::Shape ifm_shape{1, 3, 3}; + auto ifm_bag = bags["data"]; + auto ifm_obj = m->entity()->object()->create<coco::FeatureObject>(); + auto ifm_layout = coco::FeatureLayouts::BCHW::create(ifm_shape); + + ifm_obj->bag(ifm_bag); + ifm_obj->layout(std::move(ifm_layout)); + + const nncc::core::ADT::kernel::Shape ker_shape{1, 1, 3, 3}; + auto ker_bag = m->entity()->bag()->create(num_elements(ker_shape)); + auto ker_layout = coco::KernelLayouts::Generic::create(ker_shape); + + ker_layout->reorder<NCHWLayout>(); + + auto ker_obj = m->entity()->object()->create<coco::KernelObject>(); + + ker_obj->bag(ker_bag); + ker_obj->layout(std::move(ker_layout)); + + const nncc::core::ADT::feature::Shape ofm_shape{1, 1, 1}; + auto ofm_bag = m->entity()->bag()->create(1 * 1 * 1); + auto ofm_obj = m->entity()->object()->create<coco::FeatureObject>(); + auto ofm_layout = coco::FeatureLayouts::BCHW::create(ifm_shape); + + ofm_obj->bag(ofm_bag); + ofm_obj->layout(std::move(ofm_layout)); + + // Create Load operation + auto load = m->entity()->op()->create<coco::Load>(); + + load->object(ifm_obj); + + // Create Conv2D operation + // + // NOTE Conv2D op in coco IR does not perform BiasAdd + auto op = m->entity()->op()->create<coco::Conv2D>(); + + op->ker(ker_obj); + + // Create UnitF instruction with Conv2D operation + auto ins = m->entity()->instr()->create<coco::Eval>(); + + ins->out(ofm_obj); + ins->op(op); + + // Append the instruction (to the block) + blk->instr()->append(ins); + + bags["conv"] = ofm_bag; + shapes["conv"] = nncc::core::ADT::tensor::Shape{1, 1, 1, 1}; + + top_blobs = {"conv"}; + } + + // Finalize + for (const auto &top_blob : top_blobs) + { + const auto &shape = shapes[top_blob]; + + auto output = m->entity()->output()->create(shape); + + output->bag(bags[top_blob]); + output->name(top_blob); + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + const static LexicalLayout l{}; + const auto offset = static_cast<uint32_t>(l.offset(shape, e.current())); + + output->at(e.current()) = coco::ElemID{offset}; + } + + m->output()->insert(output); + } + + // Let's validate the constructed IR + { + // There is one input whose name is 'data' + ASSERT_EQ(m->input()->size(), 1); + ASSERT_EQ(m->input()->at(0)->name(), "data"); + + // There is one output whose name is 'conv' + ASSERT_EQ(m->output()->size(), 1); + ASSERT_EQ(m->output()->at(0)->name(), "conv"); + + ASSERT_FALSE(m->block()->empty()); + + // There is one block in the module + auto blk = m->block()->head(); + + ASSERT_EQ(blk->next(), nullptr); + ASSERT_FALSE(blk->instr()->empty()); + + // There is one instruction in the block + auto ins = blk->instr()->head(); + + ASSERT_EQ(ins->next(), nullptr); + + // That instruction is 'Eval' + // TODO Rename 'unit' + auto unit = ins->asEval(); + + ASSERT_NE(unit, nullptr); + +// TODO Rewrite below test +#if 0 + // Input #0 points to IFM + ASSERT_NE(unit->ifm(), nullptr); + ASSERT_EQ(unit->ifm()->bag(), m->input()->at(0)->bag()); +#endif + + // Output #0 points to OFM + ASSERT_NE(unit->out(), nullptr); + ASSERT_EQ(unit->out()->bag(), m->output()->at(0)->bag()); + + // The actual operation is Conv2D + auto conv = unit->op()->asConv2D(); + + ASSERT_NE(conv, nullptr); + + // Let's check Kernel Object + ASSERT_NE(conv->ker(), nullptr); +// TODO Rewrite below test +#if 0 + ASSERT_NE(conv->ker()->bag(), unit->ifm()->bag()); + ASSERT_NE(conv->ker()->bag(), unit->ofm()->bag()); +#endif + +// One may find the correspondence among Input, Output, and Objects through ElemID +// TODO Rewrite below test +#if 0 + { + auto input_0 = m->input()->at(0); + auto ifm = unit->ifm(); + + nncc::core::ADT::tensor::Index input_index{0, 0, 2, 2}; + + // Here we can check that Input(0, 0, 2, 2) corresponds to IFM(0, 2, 2) + ASSERT_EQ(input_0->at(input_index).value(), ifm->at(0, 2, 2).value()); + } +#endif + } +} + +// +// This test demonstrates how to use 'replaceWith' method +// +TEST(IR, bag_replaceWith) +{ + auto m = coco::Module::create(); + + auto bag_1 = m->entity()->bag()->create(1); + auto bag_2 = m->entity()->bag()->create(1); + + auto obj = m->entity()->object()->create<coco::FeatureObject>(); + obj->bag(bag_1); + + auto shuffle_1 = m->entity()->instr()->create<coco::Shuffle>(); + shuffle_1->into(bag_1); + + auto shuffle_2 = m->entity()->instr()->create<coco::Shuffle>(); + shuffle_2->from(bag_1); + + ASSERT_EQ(obj->bag(), bag_1); + ASSERT_EQ(shuffle_1->into(), bag_1); + ASSERT_EQ(shuffle_2->from(), bag_1); + + bag_1->replaceAllDepsWith(bag_2); + + ASSERT_EQ(obj->bag(), bag_2); + ASSERT_EQ(shuffle_1->into(), bag_1); + ASSERT_EQ(shuffle_2->from(), bag_1); + + bag_1->replaceWith(bag_2); + + ASSERT_EQ(obj->bag(), bag_2); + ASSERT_EQ(shuffle_1->into(), bag_2); + ASSERT_EQ(shuffle_2->from(), bag_2); +} diff --git a/compiler/coco/core/src/IR/Arg.cpp b/compiler/coco/core/src/IR/Arg.cpp new file mode 100644 index 000000000..b6f9c4777 --- /dev/null +++ b/compiler/coco/core/src/IR/Arg.cpp @@ -0,0 +1,78 @@ +/* + * 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 "coco/IR/Arg.h" + +#include <nncc/core/ADT/tensor/LexicalLayout.h> +#include <nncc/core/ADT/tensor/IndexEnumerator.h> + +#include <cassert> + +namespace +{ + +const nncc::core::ADT::tensor::LexicalLayout l; + +} // namespace + +namespace coco +{ + +Arg::Arg(const nncc::core::ADT::tensor::Shape &shape) : _shape{shape}, _bag{nullptr} +{ + _map.resize(nncc::core::ADT::tensor::num_elements(shape)); +} + +void Arg::bag(Bag *bag) +{ + if (_bag != nullptr) + { + onRelease(_bag); + _bag = nullptr; + } + + assert(_bag == nullptr); + + if (bag != nullptr) + { + _bag = bag; + onTake(_bag); + } +} + +ElemID &Arg::at(const nncc::core::ADT::tensor::Index &index) +{ + return _map.at(l.offset(_shape, index)); +} + +const ElemID &Arg::at(const nncc::core::ADT::tensor::Index &index) const +{ + return _map.at(l.offset(_shape, index)); +} + +void Arg::reorder(const nncc::core::ADT::tensor::Layout &l) +{ + using nncc::core::ADT::tensor::IndexEnumerator; + + for (IndexEnumerator e{shape()}; e.valid(); e.advance()) + { + const auto offset = static_cast<uint32_t>(l.offset(shape(), e.current())); + + at(e.current()) = coco::ElemID{offset}; + } +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Arg.test.cpp b/compiler/coco/core/src/IR/Arg.test.cpp new file mode 100644 index 000000000..391e05901 --- /dev/null +++ b/compiler/coco/core/src/IR/Arg.test.cpp @@ -0,0 +1,100 @@ +/* + * 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 "coco/IR/Arg.h" + +#include <nncc/core/ADT/tensor/IndexEnumerator.h> +#include <nncc/core/ADT/tensor/LexicalLayout.h> + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::Index; +using nncc::core::ADT::tensor::IndexEnumerator; +using nncc::core::ADT::tensor::LexicalLayout; + +namespace +{ +class ArgTest : public ::testing::Test +{ +protected: + coco::Arg *allocate(const Shape &shape) + { + auto arg = new coco::Arg{shape}; + _allocated.emplace_back(arg); + return arg; + } + +private: + std::vector<std::unique_ptr<coco::Arg>> _allocated; +}; +} // namespace + +TEST_F(ArgTest, constructor) +{ + const Shape shape{1, 3, 3, 1}; + + auto arg = allocate(shape); + + ASSERT_EQ(arg->shape(), shape); + ASSERT_TRUE(arg->name().empty()); + ASSERT_EQ(arg->bag(), nullptr); +} + +TEST_F(ArgTest, name_update) +{ + const Shape shape{1, 3, 3, 1}; + + auto arg = allocate(shape); + + arg->name("data"); + ASSERT_EQ(arg->name(), "data"); +} + +TEST_F(ArgTest, at) +{ + const Shape shape{1, 3, 3, 1}; + + auto arg = allocate(shape); + + coco::Arg *mutable_ptr = arg; + const coco::Arg *immutable_ptr = arg; + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + mutable_ptr->at(e.current()) = coco::ElemID{16}; + } + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + ASSERT_EQ(immutable_ptr->at(e.current()).value(), 16); + } +} + +TEST_F(ArgTest, reorder) +{ + const Shape shape{2, 2, 2, 2}; + + auto arg = allocate(shape); + + arg->reorder<LexicalLayout>(); + + ASSERT_EQ(arg->at(Index{0, 0, 0, 0}).value(), 0); + ASSERT_EQ(arg->at(Index{0, 0, 0, 1}).value(), 1); +} diff --git a/compiler/coco/core/src/IR/AvgPool2D.test.cpp b/compiler/coco/core/src/IR/AvgPool2D.test.cpp new file mode 100644 index 000000000..d62bc9b7d --- /dev/null +++ b/compiler/coco/core/src/IR/AvgPool2D.test.cpp @@ -0,0 +1,113 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +struct IsAvgPool2D : public coco::Op::Visitor<bool> +{ + bool visit(const coco::AvgPool2D *) override { return true; } +}; + +class AvgPool2DTest : public ::testing::Test +{ +public: + AvgPool2DTest() + { + // DO NOTHING + } + +protected: + coco::AvgPool2D *allocate(void) + { + auto op = new coco::AvgPool2D; + _allocated.emplace_back(op); + return op; + } + +private: + std::vector<std::unique_ptr<coco::AvgPool2D>> _allocated; +}; +} // namespace + +TEST_F(AvgPool2DTest, initialization) +{ + auto op = allocate(); + + coco::AvgPool2D *mutable_ptr = op; + const coco::AvgPool2D *immutable_ptr = op; + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); + + // arg() should be nullptr on construction + ASSERT_EQ(immutable_ptr->arg(), nullptr); + + // divisor() SHOULD be unknow on construction + ASSERT_EQ(immutable_ptr->divisor(), coco::AvgPool2D::Divisor::Unknown); + + // window() SHOULD return a valid pointer + ASSERT_NE(mutable_ptr->window(), nullptr); + ASSERT_EQ(mutable_ptr->window(), immutable_ptr->window()); + + // pad() SHOULD return a valid pointer + ASSERT_NE(mutable_ptr->pad(), nullptr); + ASSERT_EQ(mutable_ptr->pad(), immutable_ptr->pad()); + + // stride() SHOULD return a valid pointer + ASSERT_NE(mutable_ptr->stride(), nullptr); + ASSERT_EQ(mutable_ptr->stride(), immutable_ptr->stride()); +} + +TEST_F(AvgPool2DTest, asAvgPool2D) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asAvgPool2D(), op); + ASSERT_EQ(mutable_base->asAvgPool2D(), immutable_base->asAvgPool2D()); +} + +TEST_F(AvgPool2DTest, accept) +{ + // Test 'AvgPool2D' class + auto op = allocate(); + + coco::AvgPool2D *mutable_ptr = op; + const coco::AvgPool2D *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsAvgPool2D{})); + ASSERT_TRUE(immutable_ptr->accept(IsAvgPool2D{})); +} + +TEST_F(AvgPool2DTest, disivor) +{ + auto op = allocate(); + + op->divisor(coco::AvgPool2D::Divisor::Static); + + ASSERT_EQ(op->divisor(), coco::AvgPool2D::Divisor::Static); +} diff --git a/compiler/coco/core/src/IR/Bag.cpp b/compiler/coco/core/src/IR/Bag.cpp new file mode 100644 index 000000000..7dce48587 --- /dev/null +++ b/compiler/coco/core/src/IR/Bag.cpp @@ -0,0 +1,147 @@ +/* + * 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 "coco/IR/Bag.h" + +#include "coco/IR/Object.h" +#include "coco/IR/Read.h" +#include "coco/IR/Update.h" + +#include <cassert> + +namespace coco +{ + +Bag::Bag(uint32_t size) : _size{size} +{ + // DO NOTHING +} + +Bag::~Bag() +{ + // All the references over a bag SHOULD be dropped before its destruction + assert(deps()->size() == 0); + assert(reads()->size() == 0); + assert(updates()->size() == 0); +} + +uint32_t Bag::size(void) const { return _size; } + +bool Bag::isInput(void) const { return _input != nullptr; } +bool Bag::isOutput(void) const { return _output != nullptr; } + +const DepSet *Bag::deps(void) const { return &_deps; } +const ReadSet *Bag::reads(void) const { return &_reads; } +const UpdateSet *Bag::updates(void) const { return &_updates; } + +void Bag::replaceWith(Bag *b) +{ + assert(!isInput() && !isOutput()); + + replaceAllDepsWith(b); + // Replace all the occurence inside Read + while (!(reads()->empty())) + { + auto read = *(reads()->begin()); + assert(read->bag() == this); + read->bag(b); + } + + // Replace all the occurence insider Update + while (!(updates()->empty())) + { + auto update = *(updates()->begin()); + assert(update->bag() == this); + update->bag(b); + } + + assert(deps()->empty()); + assert(reads()->empty()); + assert(updates()->empty()); +} + +void Bag::replaceAllDepsWith(Bag *b) +{ + // Replace all the occurence inside Dep + while (!(deps()->empty())) + { + auto dep = *(deps()->begin()); + assert(dep->bag() == this); + dep->bag(b); + } +} + +ObjectSet dependent_objects(const Bag *b) +{ + ObjectSet res; + + for (const auto &dep : *(b->deps())) + { + if (auto obj = dep->object()) + { + res.insert(obj); + } + } + + return res; +} + +Bag::ReaderSet readers(const Bag *b) +{ + Bag::ReaderSet res; + + for (auto obj : dependent_objects(b)) + { + for (auto consumer : consumers(obj)) + { + // NOTE Object::Consumer inherits Bag::Reader + res.insert(consumer); + } + } + + for (auto read : *b->reads()) + { + auto reader = read->reader(); + assert(reader != nullptr); + res.insert(reader); + } + + return res; +} + +Bag::UpdaterSet updaters(const Bag *b) +{ + Bag::UpdaterSet res; + + for (auto obj : dependent_objects(b)) + { + if (auto p = producer(obj)) + { + res.insert(p); + } + } + + for (auto update : *b->updates()) + { + auto updater = update->updater(); + assert(updater != nullptr); + res.insert(updater); + } + + return res; +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Bag.test.cpp b/compiler/coco/core/src/IR/Bag.test.cpp new file mode 100644 index 000000000..9995e81ef --- /dev/null +++ b/compiler/coco/core/src/IR/Bag.test.cpp @@ -0,0 +1,30 @@ +/* + * 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 "coco/IR/Bag.h" + +#include <gtest/gtest.h> + +TEST(IR_BAG, ctor_should_set_size) +{ + coco::Bag b{3}; + + ASSERT_EQ(b.size(), 3); + + // Bag has no read/updates at the beginning + EXPECT_EQ(b.reads()->size(), 0); + EXPECT_EQ(b.updates()->size(), 0); +} diff --git a/compiler/coco/core/src/IR/BagManager.cpp b/compiler/coco/core/src/IR/BagManager.cpp new file mode 100644 index 000000000..10fe69d57 --- /dev/null +++ b/compiler/coco/core/src/IR/BagManager.cpp @@ -0,0 +1,33 @@ +/* + * 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 "coco/IR/BagManager.h" + +#include <stdex/Memory.h> + +namespace coco +{ + +Bag *BagManager::create(uint32_t size) +{ + auto bag = stdex::make_unique<Bag>(size); + modulize(bag.get()); + return take(std::move(bag)); +} + +void BagManager::destroy(Bag *b) { release(b); } + +} // namespace coco diff --git a/compiler/coco/core/src/IR/BagManager.test.cpp b/compiler/coco/core/src/IR/BagManager.test.cpp new file mode 100644 index 000000000..bf135a951 --- /dev/null +++ b/compiler/coco/core/src/IR/BagManager.test.cpp @@ -0,0 +1,38 @@ +/* + * 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 "coco/IR/BagManager.h" + +#include <gtest/gtest.h> + +TEST(IR_BAG_MANAGER, create) +{ + coco::BagManager mgr; + + auto bag = mgr.create(3); + + ASSERT_EQ(bag->size(), 3); +} + +TEST(IR_BAG_MANAGER, destruct) +{ + coco::BagManager mgr; + + auto b = mgr.create(3); + mgr.destroy(b); + + ASSERT_EQ(mgr.size(), 0); +} diff --git a/compiler/coco/core/src/IR/Block.cpp b/compiler/coco/core/src/IR/Block.cpp new file mode 100644 index 000000000..14c026039 --- /dev/null +++ b/compiler/coco/core/src/IR/Block.cpp @@ -0,0 +1,56 @@ +/* + * 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 "coco/IR/Block.h" +#include "coco/IR/Module.h" + +#include <cassert> + +namespace coco +{ + +template <> void DLinkedList<Block, Module>::joined(Module *, Block *curr_blk) +{ + assert(!curr_blk->index().valid()); + uint32_t value = 0; + + if (auto prev_blk = curr_blk->prev()) + { + value = prev_blk->index().value() + 1; + } + + for (auto blk = curr_blk; blk; blk = blk->next()) + { + blk->_index.set(value++); + } +} + +template <> void DLinkedList<Block, Module>::leaving(Module *, Block *curr_blk) +{ + assert(curr_blk->index().valid()); + uint32_t value = curr_blk->index().value(); + + for (auto blk = curr_blk->next(); blk; blk = blk->next()) + { + blk->_index.set(value++); + } + + curr_blk->_index.reset(); +} + +template <> BlockList *DLinkedList<Block, Module>::head(Module *m) { return m->block(); } + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Block.test.cpp b/compiler/coco/core/src/IR/Block.test.cpp new file mode 100644 index 000000000..c2acc89f7 --- /dev/null +++ b/compiler/coco/core/src/IR/Block.test.cpp @@ -0,0 +1,28 @@ +/* + * 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 "coco/IR/Block.h" + +#include <gtest/gtest.h> + +TEST(IR_BLOCK, default_block_has_empty_instr_list) +{ + coco::Block blk; + + ASSERT_TRUE(blk.instr()->empty()); + ASSERT_EQ(blk.instr()->head(), nullptr); + ASSERT_EQ(blk.instr()->tail(), nullptr); +} diff --git a/compiler/coco/core/src/IR/BlockIndex.cpp b/compiler/coco/core/src/IR/BlockIndex.cpp new file mode 100644 index 000000000..8cb56724c --- /dev/null +++ b/compiler/coco/core/src/IR/BlockIndex.cpp @@ -0,0 +1,30 @@ +/* + * 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 "coco/IR/BlockIndex.h" + +#include <cassert> + +namespace coco +{ + +void BlockIndex::set(uint32_t value) +{ + assert(value != undefined); + _value = value; +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/BlockIndex.test.cpp b/compiler/coco/core/src/IR/BlockIndex.test.cpp new file mode 100644 index 000000000..68afb889e --- /dev/null +++ b/compiler/coco/core/src/IR/BlockIndex.test.cpp @@ -0,0 +1,50 @@ +/* + * 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 "coco/IR/BlockIndex.h" + +#include <gtest/gtest.h> + +namespace +{ + +class BlockIndexTest : public ::testing::Test +{ +}; + +} // namespace + +TEST_F(BlockIndexTest, default_constructor) +{ + coco::BlockIndex blk_ind; + + ASSERT_FALSE(blk_ind.valid()); +} + +TEST_F(BlockIndexTest, explicit_constructor) +{ + coco::BlockIndex blk_ind{3}; + + ASSERT_TRUE(blk_ind.valid()); + ASSERT_EQ(blk_ind.value(), 3); +} + +TEST_F(BlockIndexTest, operator_lt) +{ + // Valid index is always less than undefined one. + ASSERT_TRUE(coco::BlockIndex(3) < coco::BlockIndex()); + ASSERT_TRUE(coco::BlockIndex(3) < coco::BlockIndex(4)); +} diff --git a/compiler/coco/core/src/IR/BlockManager.cpp b/compiler/coco/core/src/IR/BlockManager.cpp new file mode 100644 index 000000000..5e3b88173 --- /dev/null +++ b/compiler/coco/core/src/IR/BlockManager.cpp @@ -0,0 +1,41 @@ +/* + * 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 "coco/IR/BlockManager.h" + +#include <stdex/Memory.h> + +#include <cassert> + +namespace coco +{ + +Block *BlockManager::create(void) +{ + auto blk = stdex::make_unique<Block>(); + modulize(blk.get()); + return take(std::move(blk)); +} + +void BlockManager::destroy(Block *blk) +{ + assert(blk->parent() == nullptr); + assert(blk->prev() == nullptr); + assert(blk->next() == nullptr); + release(blk); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/BlockManager.test.cpp b/compiler/coco/core/src/IR/BlockManager.test.cpp new file mode 100644 index 000000000..94f69b773 --- /dev/null +++ b/compiler/coco/core/src/IR/BlockManager.test.cpp @@ -0,0 +1,60 @@ +/* + * 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 "coco/IR/BlockManager.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +class BlockManagerTest : public ::testing::Test +{ +public: + // Create a coco::BlockManager for testing + coco::BlockManager *allocate(void) + { + auto p = new coco::BlockManager; + _allocated.emplace_back(p); + return p; + } + +private: + std::vector<std::unique_ptr<coco::BlockManager>> _allocated; +}; +} // namespace + +TEST_F(BlockManagerTest, create) +{ + auto mgr = allocate(); + auto blk = mgr->create(); + + ASSERT_NE(blk, nullptr); +} + +TEST_F(BlockManagerTest, destroy) +{ + auto mgr = allocate(); + auto blk_1 = mgr->create(); + auto blk_2 = mgr->create(); + + mgr->destroy(blk_1); + + ASSERT_EQ(mgr->size(), 1); + ASSERT_EQ(mgr->at(0), blk_2); +} diff --git a/compiler/coco/core/src/IR/Consumer.mock.h b/compiler/coco/core/src/IR/Consumer.mock.h new file mode 100644 index 000000000..7d7cc492a --- /dev/null +++ b/compiler/coco/core/src/IR/Consumer.mock.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_CONSUMER_MOCK_H__ +#define __COCO_IR_CONSUMER_MOCK_H__ + +#include "coco/IR/Object.h" + +namespace +{ +namespace mock +{ +struct Consumer final : public coco::Object::Consumer +{ + coco::Instr *loc(void) override { return nullptr; } +}; +} // namespace mock +} // namespace + +#endif // __COCO_IR_CONSUMER_MOCK_H__ diff --git a/compiler/coco/core/src/IR/Conv2D.cpp b/compiler/coco/core/src/IR/Conv2D.cpp new file mode 100644 index 000000000..19395a158 --- /dev/null +++ b/compiler/coco/core/src/IR/Conv2D.cpp @@ -0,0 +1,75 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <pepper/assert.h> + +namespace coco +{ + +Conv2D::Conv2D() : _ker{this}, _arg{this} +{ + // DO NOTHING +} + +uint32_t Conv2D::arity(void) const +{ + // Conv2D has one argument (IFM) + // NOTE This design is subject to change + return 1; +} + +Op *Conv2D::arg(DBGARG(uint32_t, n)) const +{ + assert(n < arity()); + return arg(); +} + +std::set<Object *> Conv2D::uses(void) const +{ + std::set<Object *> res; + + if (ker()) + { + res.insert(ker()); + } + + if (auto ifm = arg()) + { + for (auto obj : ifm->uses()) + { + res.insert(obj); + } + } + + return res; +} + +void Conv2D::ker(KernelObject *ker) { _ker.value(ker); } + +KernelObject *Conv2D::ker(void) const +{ + if (auto obj = _ker.value()) + { + assert(obj->asKernel() != nullptr); + return obj->asKernel(); + } + + return nullptr; +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Conv2D.test.cpp b/compiler/coco/core/src/IR/Conv2D.test.cpp new file mode 100644 index 000000000..df0a2470b --- /dev/null +++ b/compiler/coco/core/src/IR/Conv2D.test.cpp @@ -0,0 +1,154 @@ +/* + * 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 "coco/IR/Ops.h" +#include "coco/IR/ObjectManager.h" + +#include <vector> +#include <memory> + +#include <stdex/Memory.h> + +#include <gtest/gtest.h> + +using stdex::make_unique; + +namespace +{ +class Conv2DTest : public ::testing::Test +{ +public: + Conv2DTest() + { + // DO NOTHING + } + +protected: + coco::Conv2D *allocate(void) + { + auto op = new coco::Conv2D; + _allocated.emplace_back(op); + return op; + } + +protected: + coco::ObjectManager obj_mgr; + +private: + std::vector<std::unique_ptr<coco::Conv2D>> _allocated; +}; +} // namespace + +TEST_F(Conv2DTest, ctor) +{ + auto op = allocate(); + + // arg() should be initialized as nullptr on construction + ASSERT_EQ(op->arg(), nullptr); + // ker() should be initialized as nullptr on construction + ASSERT_EQ(op->ker(), nullptr); + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); + + ASSERT_EQ(op->group(), 1); + + ASSERT_NE(op->pad(), nullptr); + ASSERT_EQ(op->pad()->top(), 0); + ASSERT_EQ(op->pad()->bottom(), 0); + ASSERT_EQ(op->pad()->left(), 0); + ASSERT_EQ(op->pad()->right(), 0); + + ASSERT_NE(op->stride(), nullptr); + ASSERT_EQ(op->stride()->vertical(), 1); + ASSERT_EQ(op->stride()->horizontal(), 1); +} + +TEST_F(Conv2DTest, asConv2D) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asConv2D(), op); + ASSERT_EQ(mutable_base->asConv2D(), immutable_base->asConv2D()); +} + +namespace +{ +struct IsConv2D : public coco::Op::Visitor<bool> +{ + bool visit(const coco::Conv2D *) override { return true; } +}; +} // namespace + +TEST_F(Conv2DTest, ker_update) +{ + // Prepare a kernel object for testing + auto obj = obj_mgr.create<coco::KernelObject>(); + + // Test 'Conv2D' class + auto op = allocate(); + + op->ker(obj); + ASSERT_EQ(op->ker(), obj); + + // Op now uses 'obj' + { + auto uses = op->uses(); + + ASSERT_NE(uses.find(obj), uses.end()); + } + + // ker method should enlist op itself as a consumer of a given kernel object + { + auto consumers = coco::consumers(obj); + + ASSERT_EQ(consumers.size(), 1); + ASSERT_NE(consumers.find(op), consumers.end()); + } +} + +TEST_F(Conv2DTest, accept) +{ + // Test 'Conv2D' class + auto op = allocate(); + + coco::Conv2D *mutable_ptr = op; + const coco::Conv2D *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsConv2D{})); + ASSERT_TRUE(immutable_ptr->accept(IsConv2D{})); +} + +TEST_F(Conv2DTest, destructor) +{ + // Prepare a kernel object for testing + auto obj = obj_mgr.create<coco::KernelObject>(); + + // Create 'Conv2D' op + auto op = make_unique<coco::Conv2D>(); + + op->ker(obj); + + // Destroy 'Conv2D' op + op.reset(); + + ASSERT_EQ(obj->uses()->size(), 0); +} diff --git a/compiler/coco/core/src/IR/Def.cpp b/compiler/coco/core/src/IR/Def.cpp new file mode 100644 index 000000000..1546b6693 --- /dev/null +++ b/compiler/coco/core/src/IR/Def.cpp @@ -0,0 +1,43 @@ +/* + * 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 "coco/IR/Def.h" + +#include <cassert> + +namespace coco +{ + +void Def::value(Object *value) +{ + if (_value) + { + _value->def(nullptr); + _value = nullptr; + } + + assert(_value == nullptr); + + if (value) + { + _value = value; + _value->def(this); + } + + assert(_value == value); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Def.test.cpp b/compiler/coco/core/src/IR/Def.test.cpp new file mode 100644 index 000000000..98455c09e --- /dev/null +++ b/compiler/coco/core/src/IR/Def.test.cpp @@ -0,0 +1,82 @@ +/* + * 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 "coco/IR/Def.h" +#include "coco/IR/ObjectManager.h" + +#include "coco/IR/FeatureObject.h" + +#include <stdex/Memory.h> + +#include "Producer.mock.h" + +#include <gtest/gtest.h> + +using stdex::make_unique; + +namespace +{ +class DefTest : public ::testing::Test +{ +protected: + coco::ObjectManager obj_mgr; +}; +} // namespace + +TEST_F(DefTest, constructor) +{ + auto o = obj_mgr.create<coco::FeatureObject>(); + + ::mock::Producer producer; + coco::Def def{&producer}; + + ASSERT_EQ(def.value(), nullptr); +} + +TEST_F(DefTest, value) +{ + auto o = obj_mgr.create<coco::FeatureObject>(); + + ::mock::Producer producer; + coco::Def def{&producer}; + + def.value(o); + + ASSERT_EQ(def.value(), o); + + ASSERT_EQ(o->def(), &def); + + def.value(nullptr); + + ASSERT_EQ(o->def(), nullptr); +} + +TEST_F(DefTest, unlink_on_destruction) +{ + auto o = obj_mgr.create<coco::FeatureObject>(); + + ::mock::Producer producer; + auto def = make_unique<coco::Def>(&producer); + + def->value(o); + ASSERT_EQ(o->def(), def.get()); + + // Let's destruct the allocated slot + def.reset(nullptr); + + // The def of Object SHOULD BE updated + ASSERT_EQ(o->def(), nullptr); +} diff --git a/compiler/coco/core/src/IR/Dep.cpp b/compiler/coco/core/src/IR/Dep.cpp new file mode 100644 index 000000000..6a5d3cafb --- /dev/null +++ b/compiler/coco/core/src/IR/Dep.cpp @@ -0,0 +1,53 @@ +/* + * 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 "coco/IR/Dep.h" +#include "coco/IR/Object.h" + +#include <cassert> + +namespace coco +{ + +Dep::~Dep() { bag(nullptr); } + +void Dep::bag(Bag *bag) +{ + if (_bag != nullptr) + { + // Remove bag <-> dep link + assert(_bag->deps()->find(this) != _bag->deps()->end()); + _bag->mutable_deps()->erase(this); + + // Reset _bag + _bag = nullptr; + } + + assert(_bag == nullptr); + + if (bag != nullptr) + { + // Set _bag + _bag = bag; + + // Create bag <-> dep link + _bag->mutable_deps()->insert(this); + } + + assert(_bag == bag); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Dep.test.cpp b/compiler/coco/core/src/IR/Dep.test.cpp new file mode 100644 index 000000000..e2104a8af --- /dev/null +++ b/compiler/coco/core/src/IR/Dep.test.cpp @@ -0,0 +1,73 @@ +/* + * 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 "coco/IR/Dep.h" + +#include "coco/IR/BagManager.h" + +#include "coco/IR/ObjectManager.h" +#include "coco/IR/FeatureObject.h" + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT; + +namespace +{ +class DepTest : public ::testing::Test +{ +protected: + coco::BagManager bag_mgr; + coco::ObjectManager obj_mgr; +}; +} // namespace + +TEST_F(DepTest, default_constructor) +{ + coco::Dep dep; + + ASSERT_EQ(dep.bag(), nullptr); + ASSERT_EQ(dep.object(), nullptr); +} + +TEST_F(DepTest, bag_update) +{ + auto bag = bag_mgr.create(3); + + coco::Dep dep; + + // NOTE b->object() is not updated here + dep.bag(bag); + + ASSERT_EQ(dep.bag(), bag); +} + +TEST_F(DepTest, bag_update_with_link_and_object) +{ + auto bag = bag_mgr.create(3); + auto obj = obj_mgr.create<coco::FeatureObject>(); + + coco::Dep dep; + + dep.object(obj); + + dep.bag(bag); + + auto deps = coco::dependent_objects(bag); + + ASSERT_EQ(deps.size(), 1); + ASSERT_NE(deps.count(obj), 0); +} diff --git a/compiler/coco/core/src/IR/ElemID.cpp b/compiler/coco/core/src/IR/ElemID.cpp new file mode 100644 index 000000000..145bb986a --- /dev/null +++ b/compiler/coco/core/src/IR/ElemID.cpp @@ -0,0 +1,25 @@ +/* + * 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 "coco/IR/ElemID.h" + +namespace coco +{ + +bool operator==(const ElemID &lhs, const ElemID &rhs) { return lhs.value() == rhs.value(); } +bool operator<(const ElemID &lhs, const ElemID &rhs) { return lhs.value() < rhs.value(); } + +} // namespace coco diff --git a/compiler/coco/core/src/IR/ElemID.test.cpp b/compiler/coco/core/src/IR/ElemID.test.cpp new file mode 100644 index 000000000..dff2fa27c --- /dev/null +++ b/compiler/coco/core/src/IR/ElemID.test.cpp @@ -0,0 +1,62 @@ +/* + * 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 "coco/IR/ElemID.h" + +#include <vector> + +#include <gtest/gtest.h> + +TEST(IR_ELEM_ID, constructor) +{ + coco::ElemID id{128}; + + ASSERT_EQ(id.value(), 128); +} + +TEST(IR_ELEM_ID, copy) +{ + coco::ElemID src{16}; + coco::ElemID dst{32}; + + dst = src; + + ASSERT_EQ(dst.value(), 16); +} + +TEST(IR_ELEM_ID, std_vector_compatible) +{ + // ElemID SHOULD be compatible with standard container (including std::vector) + std::vector<coco::ElemID> vec; + + vec.resize(16); + vec.clear(); + vec.emplace_back(coco::ElemID{128}); + + ASSERT_EQ(vec.at(0).value(), 128); +} + +TEST(IR_ELEM_ID, operator_eq) +{ + ASSERT_TRUE(coco::ElemID{16} == coco::ElemID{16}); + ASSERT_FALSE(coco::ElemID{16} == coco::ElemID{17}); +} + +TEST(IR_ELEM_ID, operator_lt) +{ + ASSERT_FALSE(coco::ElemID{16} < coco::ElemID{16}); + ASSERT_TRUE(coco::ElemID{16} < coco::ElemID{17}); +} diff --git a/compiler/coco/core/src/IR/EntityManager.cpp b/compiler/coco/core/src/IR/EntityManager.cpp new file mode 100644 index 000000000..f6f2cb382 --- /dev/null +++ b/compiler/coco/core/src/IR/EntityManager.cpp @@ -0,0 +1,20 @@ +/* + * 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 "coco/IR/EntityManager.h" + +// NOTE Do NOT delete this file; this file enforces compiler to check whether 'EntityManager.h' is +// complete. diff --git a/compiler/coco/core/src/IR/Eval.cpp b/compiler/coco/core/src/IR/Eval.cpp new file mode 100644 index 000000000..dcf579049 --- /dev/null +++ b/compiler/coco/core/src/IR/Eval.cpp @@ -0,0 +1,28 @@ +/* + * 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 "coco/IR/Instrs.h" +#include "coco/IR/Op.h" + +namespace coco +{ + +Eval::Eval() : _out{this}, _step{this} +{ + // DO NOTHING +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Eval.test.cpp b/compiler/coco/core/src/IR/Eval.test.cpp new file mode 100644 index 000000000..6469f6763 --- /dev/null +++ b/compiler/coco/core/src/IR/Eval.test.cpp @@ -0,0 +1,60 @@ +/* + * 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 "coco/IR/Instrs.h" +#include "coco/IR/ObjectManager.h" +#include "coco/IR/OpManager.h" + +#include <gtest/gtest.h> + +namespace +{ +class EvalTest : public ::testing::Test +{ +public: + virtual ~EvalTest() = default; + +protected: + coco::Eval *allocate(void) + { + auto ins = new coco::Eval{}; + _allocated.emplace_back(ins); + return ins; + } + +private: + std::vector<std::unique_ptr<coco::Instr>> _allocated; +}; +} // namespace + +TEST_F(EvalTest, constructor) +{ + auto ins = allocate(); + + ASSERT_EQ(ins->out(), nullptr); + ASSERT_EQ(ins->op(), nullptr); +} + +TEST_F(EvalTest, asEval) +{ + auto ins = allocate(); + + coco::Instr *mutable_ptr = ins; + const coco::Instr *immutable_ptr = ins; + + ASSERT_NE(mutable_ptr->asEval(), nullptr); + ASSERT_EQ(mutable_ptr->asEval(), immutable_ptr->asEval()); +} diff --git a/compiler/coco/core/src/IR/FeatureLayouts.cpp b/compiler/coco/core/src/IR/FeatureLayouts.cpp new file mode 100644 index 000000000..98423e01f --- /dev/null +++ b/compiler/coco/core/src/IR/FeatureLayouts.cpp @@ -0,0 +1,211 @@ +/* + * 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 "coco/IR/FeatureLayouts.h" + +#include <nncc/core/ADT/feature/CHWLayout.h> +#include <nncc/core/ADT/feature/HWCLayout.h> + +#include <cassert> + +using namespace nncc::core::ADT::feature; + +// +// BCHW Layout +// +namespace coco +{ +namespace FeatureLayouts +{ + +const FeatureLayout::ID *BCHW::uid(void) +{ + struct LayoutID final : public FeatureLayout::ID + { + }; + static LayoutID id; + return &id; +} + +ElemID BCHW::at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const +{ + static CHWLayout l; + + uint32_t offset = 0; + offset += b * num_elements(_shape); + offset += l.offset(_shape, ch, row, col); + return ElemID{offset}; +} + +std::unique_ptr<BCHW> BCHW::create(const nncc::core::ADT::feature::Shape &shape) +{ + // NOTE It is impossible to use make_unique here as the constructor is private + return std::unique_ptr<BCHW>{new BCHW{FeatureShape{shape}}}; +} + +} // namespace FeatureLayouts +} // namespace coco + +// +// BHWC Layout +// +namespace coco +{ +namespace FeatureLayouts +{ + +const FeatureLayout::ID *BHWC::uid(void) +{ + struct LayoutID final : public FeatureLayout::ID + { + }; + static LayoutID id; + return &id; +} + +ElemID BHWC::at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const +{ + static HWCLayout l; + + uint32_t offset = 0; + offset += b * num_elements(_shape); + offset += l.offset(_shape, ch, row, col); + + return ElemID{offset}; +} + +std::unique_ptr<BHWC> BHWC::create(const nncc::core::ADT::feature::Shape &shape) +{ + // NOTE It is impossible to use make_unique here as the constructor is private + return std::unique_ptr<BHWC>{new BHWC{FeatureShape{shape}}}; +} + +std::unique_ptr<BHWC> BHWC::create(const FeatureShape &shape) +{ + // NOTE It is impossible to use make_unique here as the constructor is private + return std::unique_ptr<BHWC>{new BHWC{shape}}; +} + +} // namespace FeatureLayouts +} // namespace coco + +// +// BC: Channel-major Channel-wise Layout +// +namespace coco +{ +namespace FeatureLayouts +{ + +const FeatureLayout::ID *BC::uid(void) +{ + struct LayoutID final : public FeatureLayout::ID + { + }; + static LayoutID id; + return &id; +} + +// NOTE BC layout ignores row/col as its name suggests +ElemID BC::at(uint32_t b, uint32_t ch, uint32_t /*row*/, uint32_t /*col*/) const +{ + assert(b < shape().batch()); + + uint32_t offset = 0; + + offset += b * _shape.depth(); + offset += ch; + + return ElemID{offset}; +} + +std::unique_ptr<BC> BC::create(const nncc::core::ADT::feature::Shape &shape) +{ + // NOTE It is impossible to use make_unique here as the constructor is private + return std::unique_ptr<BC>{new BC{FeatureShape{shape}}}; +} + +} // namespace FeatureLayouts +} // namespace coco + +// +// Generic Layout +// +namespace coco +{ +namespace FeatureLayouts +{ + +Generic::Generic(const FeatureShape &shape) : _shape{shape} +{ + _content.resize(_shape.batch() * num_elements(_shape)); +} + +const FeatureLayout::ID *Generic::uid(void) +{ + struct LayoutID final : public FeatureLayout::ID + { + }; + static LayoutID id; + return &id; +} + +uint32_t Generic::offset(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const +{ + static nncc::core::ADT::feature::CHWLayout l{}; + + uint32_t res = 0; + + res += b * num_elements(_shape); + res += l.offset(shape(), ch, row, col); + + return res; +} + +ElemID &Generic::at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) +{ + return _content.at(offset(b, ch, row, col)); +} + +ElemID Generic::at(uint32_t b, uint32_t ch, uint32_t row, uint32_t col) const +{ + return _content.at(offset(b, ch, row, col)); +} + +void Generic::reorder(const nncc::core::ADT::feature::Layout &l) +{ + assert(shape().batch() == 1); + + for (uint32_t ch = 0; ch < shape().depth(); ++ch) + { + for (uint32_t row = 0; row < shape().height(); ++row) + { + for (uint32_t col = 0; col < shape().width(); ++col) + { + at(0, ch, row, col) = ElemID{l.offset(shape(), ch, row, col)}; + } + } + } +} + +std::unique_ptr<Generic> Generic::create(const nncc::core::ADT::feature::Shape &shape) +{ + // NOTE It is impossible to use make_unique here as the constructor is private + return std::unique_ptr<Generic>{new Generic{shape}}; +} + +} // namespace FeatureLayouts +} // namespace coco diff --git a/compiler/coco/core/src/IR/FeatureLayouts.test.cpp b/compiler/coco/core/src/IR/FeatureLayouts.test.cpp new file mode 100644 index 000000000..9f9772dd8 --- /dev/null +++ b/compiler/coco/core/src/IR/FeatureLayouts.test.cpp @@ -0,0 +1,66 @@ +/* + * 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 "coco/IR/FeatureLayouts.h" + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT; + +TEST(FeatureLayoutsTest, BC) +{ + // NOTE The current implementation uses a hard-coded "batch" value + const uint32_t B = 1; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 5; + + auto l = coco::FeatureLayouts::BC::create(feature::Shape{C, H, W}); + + ASSERT_EQ(l->batch(), B); + ASSERT_EQ(l->depth(), C); + ASSERT_EQ(l->height(), H); + ASSERT_EQ(l->width(), W); + + // Check whether BC layout is actually channel-wise + for (uint32_t b = 0; b < B; ++b) + { + for (uint32_t ch = 0; ch < C; ++ch) + { + for (uint32_t row = 0; row < H; ++row) + { + for (uint32_t col = 0; col < W; ++col) + { + ASSERT_EQ(l->at(b, ch, 0, 0), l->at(b, ch, row, col)); + } + } + } + } + + // Check whether BC layout is actually channel-major + for (uint32_t b = 0; b < B; ++b) + { + for (uint32_t ch = 1; ch < C; ++ch) + { + ASSERT_EQ(l->at(b, ch - 1, 0, 0).value() + 1, l->at(b, ch, 0, 0).value()); + } + } + + for (uint32_t b = 1; b < B; ++b) + { + ASSERT_EQ(l->at(b - 1, C - 1, 0, 0).value() + 1, l->at(b, 0, 0, 0).value()); + } +} diff --git a/compiler/coco/core/src/IR/FeatureObject.cpp b/compiler/coco/core/src/IR/FeatureObject.cpp new file mode 100644 index 000000000..46de98874 --- /dev/null +++ b/compiler/coco/core/src/IR/FeatureObject.cpp @@ -0,0 +1,31 @@ +/* + * 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 "coco/IR/FeatureObject.h" + +#include <cassert> + +namespace coco +{ + +FeatureObject::~FeatureObject() +{ + // DO NOTHING +} + +const FeatureShape &FeatureObject::shape(void) const { return _layout->shape(); } + +} // namespace coco diff --git a/compiler/coco/core/src/IR/FeatureObject.test.cpp b/compiler/coco/core/src/IR/FeatureObject.test.cpp new file mode 100644 index 000000000..23188f866 --- /dev/null +++ b/compiler/coco/core/src/IR/FeatureObject.test.cpp @@ -0,0 +1,122 @@ +/* + * 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 "coco/IR/FeatureObject.h" +#include "coco/IR/FeatureLayouts.h" + +#include <vector> +#include <memory> + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT; + +namespace +{ +class FeatureObjectTest : public ::testing::Test +{ +protected: + coco::FeatureObject *allocate() + { + auto o = new coco::FeatureObject{}; + _allocated.emplace_back(o); + return o; + } + + // TODO Deprecate this method + coco::FeatureObject *allocate(const coco::FeatureShape &shape) + { + auto o = new coco::FeatureObject{}; + o->layout(coco::FeatureLayouts::Generic::create(shape)); + _allocated.emplace_back(o); + return o; + } + +private: + std::vector<std::unique_ptr<coco::FeatureObject>> _allocated; +}; +} // namespace + +TEST_F(FeatureObjectTest, ctor) +{ + const coco::FeatureShape shape{1, 3, 3}; + + auto o = allocate(shape); + + ASSERT_EQ(o->shape(), shape); + ASSERT_EQ(o->kind(), coco::Object::Kind::Feature); +} + +// TODO Reimplement this test as a test for GenericFeatureLayout +#if 0 +TEST_F(FeatureObjectTest, at) +{ + const uint32_t C = 1; + const uint32_t H = 3; + const uint32_t W = 3; + + const coco::FeatureShape shape{C, H, W}; + + auto o = allocate(shape); + + coco::FeatureObject *mutable_ptr = o; + const coco::FeatureObject *immutable_ptr = o; + + for (uint32_t ch = 0; ch < C; ++ch) + { + for (uint32_t row = 0; row < H; ++row) + { + for (uint32_t col = 0; col < W; ++col) + { + mutable_ptr->at(ch, row, col) = coco::ElemID{16}; + } + } + } + + for (uint32_t ch = 0; ch < C; ++ch) + { + for (uint32_t row = 0; row < H; ++row) + { + for (uint32_t col = 0; col < W; ++col) + { + ASSERT_EQ(immutable_ptr->at(ch, row, col).value(), 16); + } + } + } +} +#endif + +TEST_F(FeatureObjectTest, asFeature) +{ + const coco::FeatureShape shape{1, 3, 3}; + + auto o = allocate(shape); + + coco::Object *mutable_object = o; + const coco::Object *immutable_object = o; + + ASSERT_NE(mutable_object->asFeature(), nullptr); + ASSERT_EQ(mutable_object->asFeature(), immutable_object->asFeature()); +} + +TEST_F(FeatureObjectTest, casting_helpers) +{ + auto obj = allocate(); + + ASSERT_TRUE(coco::isa<coco::FeatureObject>(obj)); + ASSERT_EQ(coco::cast<coco::FeatureObject>(obj), obj); + ASSERT_EQ(coco::safe_cast<coco::FeatureObject>(obj), obj); +} diff --git a/compiler/coco/core/src/IR/FeatureShape.test.cpp b/compiler/coco/core/src/IR/FeatureShape.test.cpp new file mode 100644 index 000000000..ceeab02b7 --- /dev/null +++ b/compiler/coco/core/src/IR/FeatureShape.test.cpp @@ -0,0 +1,29 @@ +/* + * 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 "coco/IR/FeatureShape.h" + +#include <gtest/gtest.h> + +TEST(FeatureShapeTest, constructor_with_4_arguments) +{ + const coco::FeatureShape shape{1, 2, 3, 4}; + + ASSERT_EQ(shape.batch(), 1); + ASSERT_EQ(shape.depth(), 2); + ASSERT_EQ(shape.height(), 3); + ASSERT_EQ(shape.width(), 4); +} diff --git a/compiler/coco/core/src/IR/Input.cpp b/compiler/coco/core/src/IR/Input.cpp new file mode 100644 index 000000000..4385ac26c --- /dev/null +++ b/compiler/coco/core/src/IR/Input.cpp @@ -0,0 +1,41 @@ +/* + * 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 "coco/IR/Input.h" + +#include <cassert> + +namespace coco +{ + +Input::Input(const nncc::core::ADT::tensor::Shape &shape) : Arg{shape} +{ + // DO NOT?HING +} + +void Input::onTake(Bag *bag) +{ + assert(bag->input() == nullptr); + bag->input(this); +} + +void Input::onRelease(Bag *bag) +{ + assert(bag->input() == this); + bag->input(nullptr); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Input.test.cpp b/compiler/coco/core/src/IR/Input.test.cpp new file mode 100644 index 000000000..7cc1731cc --- /dev/null +++ b/compiler/coco/core/src/IR/Input.test.cpp @@ -0,0 +1,79 @@ +/* + * 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 "coco/IR/Input.h" +#include "coco/IR/BagManager.h" + +#include <nncc/core/ADT/tensor/IndexEnumerator.h> + +#include <gtest/gtest.h> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::IndexEnumerator; + +TEST(IR_INPUT, ctor_should_set_shape) +{ + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + coco::Input input{shape}; + + ASSERT_EQ(input.shape(), shape); + ASSERT_TRUE(input.name().empty()); +} + +TEST(IR_INPUT, bag_update) +{ + // Create a bag + coco::BagManager bag_mgr; + + auto bag = bag_mgr.create(9); + + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + coco::Input input{shape}; + + input.bag(bag); + ASSERT_EQ(input.bag(), bag); + + // bag(...) method SHOULD update 'bag' type + ASSERT_TRUE(bag->isInput()); +} + +TEST(IR_INPUT, name_update) +{ + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + coco::Input input{shape}; + + input.name("data"); + ASSERT_EQ(input.name(), "data"); +} + +TEST(IR_INPUT, at) +{ + const Shape shape{1, 3, 3, 1}; + coco::Input input{shape}; + + coco::Input *mutable_ptr = &input; + const coco::Input *immutable_ptr = &input; + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + mutable_ptr->at(e.current()) = coco::ElemID{16}; + } + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + ASSERT_EQ(immutable_ptr->at(e.current()).value(), 16); + } +} diff --git a/compiler/coco/core/src/IR/InputManager.cpp b/compiler/coco/core/src/IR/InputManager.cpp new file mode 100644 index 000000000..6d5b9470b --- /dev/null +++ b/compiler/coco/core/src/IR/InputManager.cpp @@ -0,0 +1,31 @@ +/* + * 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 "coco/IR/InputManager.h" + +#include <stdex/Memory.h> + +namespace coco +{ + +Input *InputManager::create(const nncc::core::ADT::tensor::Shape &shape) +{ + auto input = stdex::make_unique<Input>(shape); + modulize(input.get()); + return take(std::move(input)); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/InputManager.test.cpp b/compiler/coco/core/src/IR/InputManager.test.cpp new file mode 100644 index 000000000..be43113b4 --- /dev/null +++ b/compiler/coco/core/src/IR/InputManager.test.cpp @@ -0,0 +1,29 @@ +/* + * 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 "coco/IR/InputManager.h" + +#include <gtest/gtest.h> + +TEST(IR_INPUT_MANAGER, make) +{ + coco::InputManager mgr; + + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + auto input = mgr.create(shape); + + ASSERT_EQ(input->shape(), shape); +} diff --git a/compiler/coco/core/src/IR/Instr.cpp b/compiler/coco/core/src/IR/Instr.cpp new file mode 100644 index 000000000..9f000ba1c --- /dev/null +++ b/compiler/coco/core/src/IR/Instr.cpp @@ -0,0 +1,56 @@ +/* + * 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 "coco/IR/Instr.h" +#include "coco/IR/Block.h" + +#include <cassert> + +namespace coco +{ + +template <> void DLinkedList<Instr, Block>::joined(Block *, Instr *curr_ins) +{ + assert(!curr_ins->index().valid()); + uint32_t value = 0; + + if (auto prev_ins = curr_ins->prev()) + { + value = prev_ins->index().value() + 1; + } + + for (auto ins = curr_ins; ins; ins = ins->next()) + { + ins->_index.set(value++); + } +} + +template <> void DLinkedList<Instr, Block>::leaving(Block *, Instr *curr_ins) +{ + assert(curr_ins->index().valid()); + uint32_t value = curr_ins->index().value(); + + for (auto ins = curr_ins->next(); ins; ins = ins->next()) + { + ins->_index.set(value++); + } + + curr_ins->_index.reset(); +} + +template <> InstrList *DLinkedList<Instr, Block>::head(Block *b) { return b->instr(); } + +} // namespace coco diff --git a/compiler/coco/core/src/IR/InstrIndex.cpp b/compiler/coco/core/src/IR/InstrIndex.cpp new file mode 100644 index 000000000..c447cfc42 --- /dev/null +++ b/compiler/coco/core/src/IR/InstrIndex.cpp @@ -0,0 +1,30 @@ +/* + * 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 "coco/IR/InstrIndex.h" + +#include <cassert> + +namespace coco +{ + +void InstrIndex::set(uint32_t value) +{ + assert(value != undefined); + _value = value; +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/InstrIndex.test.cpp b/compiler/coco/core/src/IR/InstrIndex.test.cpp new file mode 100644 index 000000000..40f5d49de --- /dev/null +++ b/compiler/coco/core/src/IR/InstrIndex.test.cpp @@ -0,0 +1,50 @@ +/* + * 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 "coco/IR/InstrIndex.h" + +#include <gtest/gtest.h> + +namespace +{ + +class InstrIndexTest : public ::testing::Test +{ +}; + +} // namespace + +TEST_F(InstrIndexTest, default_constructor) +{ + coco::InstrIndex ins_ind; + + ASSERT_FALSE(ins_ind.valid()); +} + +TEST_F(InstrIndexTest, explicit_constructor) +{ + coco::InstrIndex ins_ind{3}; + + ASSERT_TRUE(ins_ind.valid()); + ASSERT_EQ(ins_ind.value(), 3); +} + +TEST_F(InstrIndexTest, operator_lt) +{ + // Valid index is always less than undefined one. + ASSERT_TRUE(coco::InstrIndex(3) < coco::InstrIndex()); + ASSERT_TRUE(coco::InstrIndex(3) < coco::InstrIndex(4)); +} diff --git a/compiler/coco/core/src/IR/InstrManager.cpp b/compiler/coco/core/src/IR/InstrManager.cpp new file mode 100644 index 000000000..32f1cbf28 --- /dev/null +++ b/compiler/coco/core/src/IR/InstrManager.cpp @@ -0,0 +1,33 @@ +/* + * 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 "coco/IR/InstrManager.h" + +#include "coco/IR/Op.h" + +#include <cassert> + +namespace coco +{ + +void InstrManager::destroy(Instr *ins) +{ + // ins SHOULD BE detached from any block before destroy call + assert(ins->parent() == nullptr); + release(ins); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/InstrManager.test.cpp b/compiler/coco/core/src/IR/InstrManager.test.cpp new file mode 100644 index 000000000..23d9f8e86 --- /dev/null +++ b/compiler/coco/core/src/IR/InstrManager.test.cpp @@ -0,0 +1,52 @@ +/* + * 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 "coco/IR/InstrManager.h" +#include "coco/IR/Op.h" + +#include <gtest/gtest.h> + +namespace +{ + +// Dummy custom instruction for testing +struct CustomInstr final : public coco::Instr +{ +}; + +class InstrManagerTest : public ::testing::Test +{ +public: + virtual ~InstrManagerTest() = default; + +protected: + coco::InstrManager mgr; +}; +} // namespace + +TEST_F(InstrManagerTest, create_Shuffle) +{ + auto ins = mgr.create<coco::Shuffle>(); + ASSERT_NE(ins, nullptr); + mgr.destroy(ins); +} + +TEST_F(InstrManagerTest, create_Custom) +{ + auto ins = mgr.create<CustomInstr>(); + ASSERT_NE(ins, nullptr); + mgr.destroy(ins); +} diff --git a/compiler/coco/core/src/IR/KernelLayouts.cpp b/compiler/coco/core/src/IR/KernelLayouts.cpp new file mode 100644 index 000000000..6e9a1575a --- /dev/null +++ b/compiler/coco/core/src/IR/KernelLayouts.cpp @@ -0,0 +1,155 @@ +/* + * 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 "coco/IR/KernelLayouts.h" + +#include <nncc/core/ADT/kernel/NCHWLayout.h> +#include <nncc/core/ADT/kernel/NHWCLayout.h> + +#include <cassert> + +using namespace nncc::core::ADT::kernel; + +using nncc::core::ADT::kernel::num_elements; +using nncc::core::ADT::kernel::Shape; + +// +// NCHW Layout +// +namespace coco +{ +namespace KernelLayouts +{ + +const KernelLayout::ID *NCHW::uid(void) +{ + struct LayoutID final : public KernelLayout::ID + { + }; + static LayoutID id; + return &id; +} + +ElemID NCHW::at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const +{ + static NCHWLayout l; + return ElemID{l.offset(_shape, n, ch, row, col)}; +} + +std::unique_ptr<NCHW> NCHW::create(const nncc::core::ADT::kernel::Shape &shape) +{ + // NOTE It is impossible to use make_unique here as the constructor is private + return std::unique_ptr<NCHW>{new NCHW{shape}}; +} + +} // namespace KernelLayouts +} // namespace coco + +// +// NHWC Layout +// +namespace coco +{ +namespace KernelLayouts +{ + +const KernelLayout::ID *NHWC::uid(void) +{ + struct LayoutID final : public KernelLayout::ID + { + }; + static LayoutID id; + return &id; +} + +ElemID NHWC::at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const +{ + static NHWCLayout l; + return ElemID{l.offset(_shape, n, ch, row, col)}; +} + +std::unique_ptr<NHWC> NHWC::create(const nncc::core::ADT::kernel::Shape &shape) +{ + // NOTE It is impossible to use make_unique here as the constructor is private + return std::unique_ptr<NHWC>{new NHWC{shape}}; +} + +} // namespace KernelLayouts +} // namespace coco + +// +// Generic Layout +// +namespace +{ + +nncc::core::ADT::kernel::NCHWLayout l; + +} // namespace + +namespace coco +{ +namespace KernelLayouts +{ + +Generic::Generic(const nncc::core::ADT::kernel::Shape &shape) : _shape{shape} +{ + _content.resize(num_elements(_shape)); +} + +const KernelLayout::ID *Generic::uid(void) +{ + struct LayoutID final : public KernelLayout::ID + { + }; + static LayoutID id; + return &id; +} + +ElemID &Generic::at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) +{ + return _content.at(l.offset(_shape, n, ch, row, col)); +} + +ElemID Generic::at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const +{ + return _content.at(l.offset(_shape, n, ch, row, col)); +} + +void Generic::reorder(const nncc::core::ADT::kernel::Layout &l) +{ + for (uint32_t n = 0; n < shape().count(); ++n) + { + for (uint32_t ch = 0; ch < shape().depth(); ++ch) + { + for (uint32_t row = 0; row < shape().height(); ++row) + { + for (uint32_t col = 0; col < shape().width(); ++col) + { + at(n, ch, row, col) = ElemID{l.offset(shape(), n, ch, row, col)}; + } + } + } + } +} + +std::unique_ptr<Generic> Generic::create(const Shape &shape) +{ + return std::unique_ptr<Generic>{new Generic{shape}}; +} + +} // namespace KernelLayouts +} // namespace coco diff --git a/compiler/coco/core/src/IR/KernelLayouts.test.cpp b/compiler/coco/core/src/IR/KernelLayouts.test.cpp new file mode 100644 index 000000000..df13cb051 --- /dev/null +++ b/compiler/coco/core/src/IR/KernelLayouts.test.cpp @@ -0,0 +1,126 @@ +/* + * 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. + */ + +#include "coco/IR/KernelLayouts.h" + +#include <nncc/core/ADT/kernel/NCHWLayout.h> +#include <nncc/core/ADT/kernel/NHWCLayout.h> + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT; + +TEST(KernelLayoutsTest, NCHW_increment) +{ + const uint32_t N = 2; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 4; + + auto l = coco::KernelLayouts::NCHW::create(kernel::Shape{N, C, H, W}); + + // check NCHW order + ASSERT_EQ(l->at(0, 0, 0, 1).value(), l->at(0, 0, 0, 0).value() + 1); + ASSERT_EQ(l->at(0, 0, 1, 0).value(), l->at(0, 0, 0, 0).value() + W); + ASSERT_EQ(l->at(0, 1, 0, 0).value(), l->at(0, 0, 0, 0).value() + H * W); + ASSERT_EQ(l->at(1, 0, 0, 0).value(), l->at(0, 0, 0, 0).value() + C * H * W); +} + +TEST(KernelLayoutsTest, NHWC_increment) +{ + const uint32_t N = 2; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 4; + + auto l = coco::KernelLayouts::NHWC::create(kernel::Shape{N, C, H, W}); + + // check NHWC order + ASSERT_EQ(l->at(0, 1, 0, 0).value(), l->at(0, 0, 0, 0).value() + 1); + ASSERT_EQ(l->at(0, 0, 0, 1).value(), l->at(0, 0, 0, 0).value() + C); + ASSERT_EQ(l->at(0, 0, 1, 0).value(), l->at(0, 0, 0, 0).value() + W * C); + ASSERT_EQ(l->at(1, 0, 0, 0).value(), l->at(0, 0, 0, 0).value() + H * W * C); +} + +TEST(KernelLayoutsTest, Generic_increment) +{ + const uint32_t N = 2; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 4; + + auto nchw = coco::KernelLayouts::Generic::create(kernel::Shape{N, C, H, W}); + auto nhwc = coco::KernelLayouts::Generic::create(kernel::Shape{N, C, H, W}); + + // reorder + nchw->reorder(kernel::NCHWLayout()); + nhwc->reorder(kernel::NHWCLayout()); + + // check NCHW order + ASSERT_EQ(nchw->at(0, 0, 0, 1).value(), nchw->at(0, 0, 0, 0).value() + 1); + ASSERT_EQ(nchw->at(0, 0, 1, 0).value(), nchw->at(0, 0, 0, 0).value() + W); + ASSERT_EQ(nchw->at(0, 1, 0, 0).value(), nchw->at(0, 0, 0, 0).value() + H * W); + ASSERT_EQ(nchw->at(1, 0, 0, 0).value(), nchw->at(0, 0, 0, 0).value() + C * H * W); + + // check NHWC order + ASSERT_EQ(nhwc->at(0, 1, 0, 0).value(), nhwc->at(0, 0, 0, 0).value() + 1); + ASSERT_EQ(nhwc->at(0, 0, 0, 1).value(), nhwc->at(0, 0, 0, 0).value() + C); + ASSERT_EQ(nhwc->at(0, 0, 1, 0).value(), nhwc->at(0, 0, 0, 0).value() + W * C); + ASSERT_EQ(nhwc->at(1, 0, 0, 0).value(), nhwc->at(0, 0, 0, 0).value() + H * W * C); +} + +TEST(KernelLayoutsTest, Generic_at) +{ + const uint32_t N = 2; + const uint32_t C = 3; + const uint32_t H = 4; + const uint32_t W = 4; + + auto l = coco::KernelLayouts::Generic::create(kernel::Shape{N, C, H, W}); + + ASSERT_NE(l.get(), nullptr); + + coco::KernelLayouts::Generic *mutable_ptr = l.get(); + const coco::KernelLayouts::Generic *immutable_ptr = l.get(); + + for (uint32_t n = 0; n < N; ++n) + { + for (uint32_t ch = 0; ch < C; ++ch) + { + for (uint32_t row = 0; row < H; ++row) + { + for (uint32_t col = 0; col < W; ++col) + { + mutable_ptr->at(n, ch, row, col) = coco::ElemID{16}; + } + } + } + } + + for (uint32_t n = 0; n < N; ++n) + { + for (uint32_t ch = 0; ch < C; ++ch) + { + for (uint32_t row = 0; row < H; ++row) + { + for (uint32_t col = 0; col < W; ++col) + { + ASSERT_EQ(immutable_ptr->at(n, ch, row, col).value(), 16); + } + } + } + } +} diff --git a/compiler/coco/core/src/IR/KernelObject.cpp b/compiler/coco/core/src/IR/KernelObject.cpp new file mode 100644 index 000000000..79c298b43 --- /dev/null +++ b/compiler/coco/core/src/IR/KernelObject.cpp @@ -0,0 +1,42 @@ +/* + * 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 "coco/IR/KernelObject.h" +#include "coco/IR/KernelLayouts.h" + +#include <nncc/core/ADT/kernel/NCHWLayout.h> + +namespace coco +{ + +KernelObject::KernelObject(const nncc::core::ADT::kernel::Shape &shape) +{ + _layout = KernelLayouts::Generic::create(shape); +} + +KernelObject::~KernelObject() +{ + // DO NOTHING +} + +const nncc::core::ADT::kernel::Shape &KernelObject::shape(void) const { return _layout->shape(); } + +ElemID KernelObject::at(uint32_t n, uint32_t ch, uint32_t row, uint32_t col) const +{ + return _layout->at(n, ch, row, col); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/KernelObject.test.cpp b/compiler/coco/core/src/IR/KernelObject.test.cpp new file mode 100644 index 000000000..f227764ca --- /dev/null +++ b/compiler/coco/core/src/IR/KernelObject.test.cpp @@ -0,0 +1,78 @@ +/* + * 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 "coco/IR/KernelObject.h" + +#include <vector> +#include <memory> + +#include <gtest/gtest.h> + +using namespace nncc::core::ADT; + +namespace +{ +class KernelObjectTest : public ::testing::Test +{ +protected: + coco::KernelObject *allocate() + { + auto o = new coco::KernelObject{}; + _allocated.emplace_back(o); + return o; + } + + coco::KernelObject *allocate(const kernel::Shape &shape) + { + auto o = new coco::KernelObject{shape}; + _allocated.emplace_back(o); + return o; + } + +private: + std::vector<std::unique_ptr<coco::KernelObject>> _allocated; +}; +} // namespace + +TEST_F(KernelObjectTest, constructor) +{ + const nncc::core::ADT::kernel::Shape shape{1, 1, 3, 3}; + auto o = allocate(shape); + + ASSERT_EQ(o->shape(), shape); + ASSERT_EQ(o->kind(), coco::Object::Kind::Kernel); +} + +TEST_F(KernelObjectTest, asKernel) +{ + const nncc::core::ADT::kernel::Shape shape{1, 1, 3, 3}; + auto o = allocate(shape); + + coco::Object *mutable_object = o; + const coco::Object *immutable_object = o; + + ASSERT_NE(mutable_object->asKernel(), nullptr); + ASSERT_EQ(mutable_object->asKernel(), immutable_object->asKernel()); +} + +TEST_F(KernelObjectTest, casting_helpers) +{ + auto obj = allocate(); + + ASSERT_TRUE(coco::isa<coco::KernelObject>(obj)); + ASSERT_EQ(coco::cast<coco::KernelObject>(obj), obj); + ASSERT_EQ(coco::safe_cast<coco::KernelObject>(obj), obj); +} diff --git a/compiler/coco/core/src/IR/Load.cpp b/compiler/coco/core/src/IR/Load.cpp new file mode 100644 index 000000000..4985e9254 --- /dev/null +++ b/compiler/coco/core/src/IR/Load.cpp @@ -0,0 +1,53 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <cassert> + +namespace coco +{ + +Load::Load() : _obj{this} +{ + // DO NOTHING +} + +uint32_t Load::arity(void) const +{ + // Load has no child Op + return 0; +} + +Op *Load::arg(uint32_t) const +{ + assert(!"Load has no argument"); + return nullptr; +} + +std::set<Object *> Load::uses(void) const +{ + std::set<Object *> res; + + if (auto obj = object()) + { + res.insert(obj); + } + + return res; +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/MaxPool2D.test.cpp b/compiler/coco/core/src/IR/MaxPool2D.test.cpp new file mode 100644 index 000000000..864edddb3 --- /dev/null +++ b/compiler/coco/core/src/IR/MaxPool2D.test.cpp @@ -0,0 +1,101 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +struct IsMaxPool2D : public coco::Op::Visitor<bool> +{ + bool visit(const coco::MaxPool2D *) override { return true; } +}; + +class MaxPool2DTest : public ::testing::Test +{ +public: + MaxPool2DTest() + { + // DO NOTHING + } + +protected: + coco::MaxPool2D *allocate(void) + { + auto op = new coco::MaxPool2D; + _allocated.emplace_back(op); + return op; + } + +private: + std::vector<std::unique_ptr<coco::MaxPool2D>> _allocated; +}; +} // namespace + +TEST_F(MaxPool2DTest, initialization) +{ + auto op = allocate(); + + coco::MaxPool2D *mutable_ptr = op; + const coco::MaxPool2D *immutable_ptr = op; + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); + + // arg() should be nullptr on construction + ASSERT_EQ(immutable_ptr->arg(), nullptr); + + // window() SHOULD return a valid pointer + ASSERT_NE(mutable_ptr->window(), nullptr); + ASSERT_EQ(mutable_ptr->window(), immutable_ptr->window()); + + // stride() SHOULD return a valid pointer + ASSERT_NE(mutable_ptr->stride(), nullptr); + ASSERT_EQ(mutable_ptr->stride(), immutable_ptr->stride()); + + // pad() SHOULD return a valid pointer + ASSERT_NE(mutable_ptr->pad(), nullptr); + ASSERT_EQ(mutable_ptr->pad(), immutable_ptr->pad()); +} + +TEST_F(MaxPool2DTest, asMaxPool2D) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asMaxPool2D(), op); + ASSERT_EQ(mutable_base->asMaxPool2D(), immutable_base->asMaxPool2D()); +} + +TEST_F(MaxPool2DTest, accept) +{ + // Test 'MaxPool2D' class + auto op = allocate(); + + coco::MaxPool2D *mutable_ptr = op; + const coco::MaxPool2D *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsMaxPool2D{})); + ASSERT_TRUE(immutable_ptr->accept(IsMaxPool2D{})); +} diff --git a/compiler/coco/core/src/IR/Module.cpp b/compiler/coco/core/src/IR/Module.cpp new file mode 100644 index 000000000..0b65ceedc --- /dev/null +++ b/compiler/coco/core/src/IR/Module.cpp @@ -0,0 +1,150 @@ +/* + * 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 "coco/IR/Module.h" + +#include <stdex/Memory.h> + +using stdex::make_unique; + +namespace +{ + +struct EntityManagerImpl final : public coco::EntityManager +{ +public: + std::unique_ptr<coco::BagManager> _bag; + +public: + coco::BagManager *bag(void) override { return _bag.get(); } + const coco::BagManager *bag(void) const override { return _bag.get(); } + +public: + std::unique_ptr<coco::ObjectManager> _object; + +public: + coco::ObjectManager *object(void) override { return _object.get(); } + const coco::ObjectManager *object(void) const override { return _object.get(); } + +public: + std::unique_ptr<coco::OpManager> _op; + +public: + coco::OpManager *op(void) override { return _op.get(); } + const coco::OpManager *op(void) const override { return _op.get(); } + +public: + coco::InstrManager *instr(void) override { return _instr.get(); } + const coco::InstrManager *instr(void) const override { return _instr.get(); } + +public: + coco::BlockManager *block(void) override { return _block.get(); } + const coco::BlockManager *block(void) const override { return _block.get(); } + +public: + std::unique_ptr<coco::InputManager> _input; + +public: + coco::InputManager *input(void) override { return _input.get(); } + const coco::InputManager *input(void) const override { return _input.get(); } + +public: + std::unique_ptr<coco::OutputManager> _output; + +public: + coco::OutputManager *output(void) override { return _output.get(); } + const coco::OutputManager *output(void) const override { return _output.get(); } + +public: + // WARN Do NOT change the order of these fields: _block -> _instr + // + // Note that each instruction may have a reference to a block, and + // the destructor of Instr accesses this 'block' reference. + // + // Thus, Instr entities SHOULD BE destructed before Block entities are destructed. + std::unique_ptr<coco::BlockManager> _block; + std::unique_ptr<coco::InstrManager> _instr; +}; + +} // namespace + +namespace +{ + +class ModuleImpl final : public coco::Module +{ +public: + coco::EntityManager *entity(void) override { return _entity.get(); } + const coco::EntityManager *entity(void) const override { return _entity.get(); } + +public: + std::unique_ptr<coco::BlockList> _block; + +public: + coco::BlockList *block(void) override { return _block.get(); } + const coco::BlockList *block(void) const override { return _block.get(); } + +public: + std::unique_ptr<coco::InputList> _input; + +public: + coco::InputList *input(void) override { return _input.get(); } + const coco::InputList *input(void) const override { return _input.get(); } + +public: + std::unique_ptr<coco::OutputList> _output; + +public: + coco::OutputList *output(void) override { return _output.get(); } + const coco::OutputList *output(void) const override { return _output.get(); } + +public: + // WARN _entity SHOULD BE declared after _block in order to allow each Block(s) to detach itself. + // + // If not, Block is destructed after its corresponding BlockList is destructed, which results + // in invalid memory access during the update on BlockList (inside Block's destructor). + std::unique_ptr<coco::EntityManager> _entity; +}; + +} // namespace + +namespace coco +{ + +std::unique_ptr<Module> Module::create(void) +{ + auto m = make_unique<::ModuleImpl>(); + + auto mgr = make_unique<::EntityManagerImpl>(); + { + mgr->_bag = make_unique<coco::BagManager>(m.get()); + mgr->_object = make_unique<coco::ObjectManager>(m.get()); + mgr->_op = make_unique<coco::OpManager>(m.get()); + mgr->_instr = make_unique<coco::InstrManager>(m.get()); + mgr->_block = make_unique<coco::BlockManager>(m.get()); + mgr->_input = make_unique<coco::InputManager>(m.get()); + mgr->_output = make_unique<coco::OutputManager>(m.get()); + } + m->_entity = std::move(mgr); + + m->_block = make_unique<coco::BlockList>(m.get()); + m->_input = make_unique<coco::InputList>(); + m->_output = make_unique<coco::OutputList>(); + + return std::move(m); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Module.test.cpp b/compiler/coco/core/src/IR/Module.test.cpp new file mode 100644 index 000000000..b55ceacb8 --- /dev/null +++ b/compiler/coco/core/src/IR/Module.test.cpp @@ -0,0 +1,196 @@ +/* + * 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 "coco/IR/Module.h" + +#include <gtest/gtest.h> + +TEST(IR_MODULE, create) +{ + auto m = coco::Module::create(); + + ASSERT_NE(m.get(), nullptr); + + coco::Module *mutable_m = m.get(); + const coco::Module *immutable_m = m.get(); + + ASSERT_NE(mutable_m->entity(), nullptr); + ASSERT_NE(immutable_m->entity(), nullptr); + + ASSERT_NE(mutable_m->entity()->bag(), nullptr); + ASSERT_EQ(immutable_m->entity()->bag(), mutable_m->entity()->bag()); + + ASSERT_NE(mutable_m->entity()->object(), nullptr); + ASSERT_EQ(immutable_m->entity()->object(), mutable_m->entity()->object()); + + ASSERT_NE(mutable_m->entity()->op(), nullptr); + ASSERT_EQ(immutable_m->entity()->op(), mutable_m->entity()->op()); + + ASSERT_NE(mutable_m->entity()->instr(), nullptr); + ASSERT_EQ(immutable_m->entity()->instr(), mutable_m->entity()->instr()); + + ASSERT_NE(mutable_m->entity()->block(), nullptr); + ASSERT_EQ(immutable_m->entity()->block(), mutable_m->entity()->block()); + + ASSERT_NE(mutable_m->entity()->input(), nullptr); + ASSERT_EQ(immutable_m->entity()->input(), mutable_m->entity()->input()); + + ASSERT_NE(mutable_m->entity()->output(), nullptr); + ASSERT_EQ(immutable_m->entity()->output(), mutable_m->entity()->output()); + + ASSERT_NE(mutable_m->block(), nullptr); + ASSERT_EQ(immutable_m->block(), mutable_m->block()); + + ASSERT_NE(mutable_m->input(), nullptr); + ASSERT_EQ(immutable_m->input(), mutable_m->input()); + + ASSERT_NE(mutable_m->output(), nullptr); + ASSERT_EQ(immutable_m->output(), mutable_m->output()); +} + +TEST(IR_MODULE, append_two_blocks) +{ + auto m = coco::Module::create(); + + auto blk_1 = m->entity()->block()->create(); + m->block()->append(blk_1); + + auto blk_2 = m->entity()->block()->create(); + m->block()->append(blk_2); + + ASSERT_EQ(m->block()->head(), blk_1); + ASSERT_EQ(m->block()->tail(), blk_2); + + ASSERT_EQ(blk_1->prev(), nullptr); + ASSERT_EQ(blk_1->next(), blk_2); + + ASSERT_EQ(blk_2->prev(), blk_1); + ASSERT_EQ(blk_2->next(), nullptr); + + ASSERT_EQ(blk_1->index().value(), 0); + ASSERT_EQ(blk_2->index().value(), 1); +} + +TEST(IR_MODULE, append_two_instrs) +{ + auto m = coco::Module::create(); + + auto blk = m->entity()->block()->create(); + auto ins_1 = m->entity()->instr()->create<coco::Eval>(); + auto ins_2 = m->entity()->instr()->create<coco::Eval>(); + + blk->instr()->append(ins_1); + blk->instr()->append(ins_2); + + ASSERT_EQ(blk->instr()->head(), ins_1); + ASSERT_EQ(blk->instr()->tail(), ins_2); + + ASSERT_EQ(ins_1->parent(), blk); + ASSERT_EQ(ins_1->prev(), nullptr); + ASSERT_EQ(ins_1->next(), ins_2); + + ASSERT_EQ(ins_2->parent(), blk); + ASSERT_EQ(ins_2->prev(), ins_1); + ASSERT_EQ(ins_2->next(), nullptr); + + ASSERT_EQ(ins_1->index().value(), 0); + ASSERT_EQ(ins_2->index().value(), 1); +} + +TEST(IR_MODULE, iterate_constant_block) +{ + auto m = coco::Module::create(); + auto blk = m->entity()->block()->create(); + auto ins_1 = m->entity()->instr()->create<coco::Eval>(); + auto ins_2 = m->entity()->instr()->create<coco::Eval>(); + + blk->instr()->append(ins_1); + blk->instr()->append(ins_2); + + const coco::Block *immutable_blk = blk; + + ASSERT_EQ(immutable_blk->instr()->head(), ins_1); + ASSERT_EQ(immutable_blk->instr()->head()->next(), ins_2); +} + +TEST(IR_MODULE, input_as_output) +{ + // Some NN frameworks allows users to use a network input as its output. + // + // For example, let us consider the following Caffe network + // + // name: "example" + // layer { + // name: "l" + // type: "Input" + // top: "data" + // input_param { shape: { dim: 1 dim: 1 dim: 3 dim: 3 } } + // } + // + // "data" blob is the input of this network, and it is also the output of this network. + const nncc::core::ADT::tensor::Shape shape{1, 1, 3, 3}; + + auto m = coco::Module::create(); + auto bag = m->entity()->bag()->create(9); + + auto input = m->entity()->input()->create(shape); + auto output = m->entity()->output()->create(shape); + + input->name("data"); + input->bag(bag); + + output->name("data"); + output->bag(bag); + + ASSERT_TRUE(bag->isInput()); + ASSERT_TRUE(bag->isOutput()); + + output->bag(nullptr); + + ASSERT_TRUE(bag->isInput()); + ASSERT_FALSE(bag->isOutput()); +} + +/** + * This test ensures that IR entities allocated via EntityManager have a correct module link + */ +TEST(IR_Module, create_entites) +{ + using namespace coco; + using namespace nncc::core::ADT; + + auto m = Module::create(); + auto entity = m->entity(); + + ASSERT_EQ(entity->bag()->create(1)->module(), m.get()); + ASSERT_EQ(entity->object()->create<coco::FeatureObject>()->module(), m.get()); + ASSERT_EQ(entity->object()->create<coco::KernelObject>()->module(), m.get()); +#define OP(Name) ASSERT_EQ(entity->op()->create<Name>()->module(), m.get()); +#include "coco/IR/Op.lst" +#undef OP +#define INSTR(Name) \ + { \ + auto ins = entity->instr()->create<Name>(); \ + ASSERT_EQ(ins->module(), m.get()); \ + ASSERT_TRUE(coco::isa<Name>(ins)); \ + ASSERT_NE(coco::safe_cast<Name>(ins), nullptr); \ + } +#include "coco/IR/Instr.lst" +#undef INSTR + ASSERT_EQ(entity->block()->create()->module(), m.get()); + ASSERT_EQ(entity->input()->create(tensor::Shape{1})->module(), m.get()); + ASSERT_EQ(entity->output()->create(tensor::Shape{1})->module(), m.get()); +} diff --git a/compiler/coco/core/src/IR/Object.cpp b/compiler/coco/core/src/IR/Object.cpp new file mode 100644 index 000000000..6a51a61a3 --- /dev/null +++ b/compiler/coco/core/src/IR/Object.cpp @@ -0,0 +1,116 @@ +/* + * 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 "coco/IR/Object.h" +#include "coco/IR/Def.h" +#include "coco/IR/Use.h" + +#include <cassert> +#include <stdexcept> + +namespace coco +{ + +Object::Object() +{ + // Register self to Dep + _dep.object(this); +} + +Def *Object::def(void) const { return _def; } + +void Object::def(Def *d) +{ + // This assert enforces users to explicitly reset def before update. + // + // Let's consider an object o with def d0. + // + // The following code is allowed: + // o->def(nullptr); + // o->def(d1); + // + // However, the following code is not allowed: + // o->def(d1); + // + assert((_def == nullptr) || (d == nullptr)); + _def = d; +} + +const UseSet *Object::uses(void) const { return &_uses; } +UseSet *Object::mutable_uses(void) { return &_uses; } + +Object::Producer *producer(const Object *obj) +{ + if (auto d = obj->def()) + { + return d->producer(); + } + + return nullptr; +} + +Object::ConsumerSet consumers(const Object *obj) +{ + Object::ConsumerSet res; + + for (const auto &use : *(obj->uses())) + { + if (auto consumer = use->consumer()) + { + res.insert(consumer); + } + } + + return res; +} + +/** + * Casting Helpers + * + * TODO Use Macro to reduce code duplication + */ +template <> bool isa<FeatureObject>(const Object *o) { return o->asFeature() != nullptr; } +template <> bool isa<KernelObject>(const Object *o) { return o->asKernel() != nullptr; } + +template <> FeatureObject *cast(Object *o) +{ + assert(o != nullptr); + auto res = o->asFeature(); + assert(res != nullptr); + return res; +} + +template <> KernelObject *cast(Object *o) +{ + assert(o != nullptr); + auto res = o->asKernel(); + assert(res != nullptr); + return res; +} + +template <> FeatureObject *safe_cast(Object *o) +{ + // NOTE o may be nullptr + return (o == nullptr) ? nullptr : o->asFeature(); +} + +template <> KernelObject *safe_cast(Object *o) +{ + // NOTE o may be nullptr + return (o == nullptr) ? nullptr : o->asKernel(); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Object.test.cpp b/compiler/coco/core/src/IR/Object.test.cpp new file mode 100644 index 000000000..2a2e4db23 --- /dev/null +++ b/compiler/coco/core/src/IR/Object.test.cpp @@ -0,0 +1,110 @@ +/* + * 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 "coco/IR/Object.h" +#include "coco/IR/BagManager.h" + +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +class ObjectTest : public ::testing::Test +{ +protected: + coco::BagManager bag_mgr; +}; +} // namespace + +namespace +{ +namespace mock +{ +struct Object : public coco::Object +{ +public: + virtual ~Object() = default; +}; +} // namespace mock +} // namespace + +TEST_F(ObjectTest, ctor) +{ + ::mock::Object obj; + + // Newly created object should not have a backing bag + ASSERT_EQ(obj.bag(), nullptr); + + // Newly created object should not have def and uses + ASSERT_EQ(obj.def(), nullptr); + ASSERT_TRUE(obj.uses()->empty()); +} + +TEST_F(ObjectTest, bag_update) +{ + // Prepare bag + auto bag = bag_mgr.create(1); + + // Test 'Object' class through a mock-up object + ::mock::Object obj; + + obj.bag(bag); + + // 'bag(Bag *)' should affect the return of 'bag(void)' + ASSERT_EQ(obj.bag(), bag); + + // User SHOULD be able to access dependent objects through 'bag' + { + auto deps = coco::dependent_objects(bag); + ASSERT_EQ(deps.size(), 1); + ASSERT_EQ(deps.count(&obj), 1); + } + + // Unlink Object-Bag relation + obj.bag(nullptr); + + ASSERT_EQ(obj.bag(), nullptr); + + { + auto deps = coco::dependent_objects(bag); + ASSERT_EQ(deps.size(), 0); + } +} + +TEST_F(ObjectTest, destructor) +{ + auto bag = bag_mgr.create(1); + + // Destruct Object after proper initialization + { + ::mock::Object obj; + + obj.bag(bag); + } + + // Object SHOULD be unlinked from Bag on destruction + { + auto deps = coco::dependent_objects(bag); + ASSERT_EQ(deps.size(), 0); + } +} + +TEST_F(ObjectTest, safe_cast) +{ + ASSERT_EQ(coco::safe_cast<coco::FeatureObject>(nullptr), nullptr); + ASSERT_EQ(coco::safe_cast<coco::KernelObject>(nullptr), nullptr); +} diff --git a/compiler/coco/core/src/IR/ObjectManager.cpp b/compiler/coco/core/src/IR/ObjectManager.cpp new file mode 100644 index 000000000..1b7215a04 --- /dev/null +++ b/compiler/coco/core/src/IR/ObjectManager.cpp @@ -0,0 +1,52 @@ +/* + * 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 "coco/IR/ObjectManager.h" + +#include "coco/IR/FeatureObject.h" +#include "coco/IR/KernelObject.h" + +#include <stdex/Memory.h> + +#include <cassert> + +using stdex::make_unique; + +namespace coco +{ + +template <> FeatureObject *ObjectManager::create(void) +{ + auto feature = make_unique<FeatureObject>(); + modulize(feature.get()); + return take(std::move(feature)); +} + +template <> KernelObject *ObjectManager::create(void) +{ + auto kernel = make_unique<KernelObject>(); + modulize(kernel.get()); + return take(std::move(kernel)); +} + +void ObjectManager::destroy(Object *o) +{ + assert(o->def() == nullptr); + assert(o->uses()->size() == 0); + release(o); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/ObjectManager.test.cpp b/compiler/coco/core/src/IR/ObjectManager.test.cpp new file mode 100644 index 000000000..781775f25 --- /dev/null +++ b/compiler/coco/core/src/IR/ObjectManager.test.cpp @@ -0,0 +1,57 @@ +/* + * 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 "coco/IR/ObjectManager.h" +#include "coco/IR/BagManager.h" + +#include "coco/IR/FeatureObject.h" +#include "coco/IR/KernelObject.h" + +#include <gtest/gtest.h> + +TEST(IR_OBJECT_MANAGER, create_feature_with_template) +{ + coco::ObjectManager mgr; + + auto feature = mgr.create<coco::FeatureObject>(); + + ASSERT_EQ(feature->layout(), nullptr); +} + +TEST(IR_OBJECT_MANAGER, create_kernel_with_template) +{ + coco::ObjectManager mgr; + + auto kernel = mgr.create<coco::KernelObject>(); + + ASSERT_EQ(kernel->layout(), nullptr); +} + +TEST(IR_OBJECT_MANAGER, destroy) +{ + coco::BagManager bag_mgr; + coco::ObjectManager obj_mgr; + + auto bag = bag_mgr.create(3); + auto feature = obj_mgr.create<coco::FeatureObject>(); + + feature->bag(bag); + + obj_mgr.destroy(feature); + + // Object SHOULD BE unlinked from its dependent bag on destruction + ASSERT_EQ(bag->deps()->size(), 0); +} diff --git a/compiler/coco/core/src/IR/Op.cpp b/compiler/coco/core/src/IR/Op.cpp new file mode 100644 index 000000000..d3808a9d6 --- /dev/null +++ b/compiler/coco/core/src/IR/Op.cpp @@ -0,0 +1,153 @@ +/* + * 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 "coco/IR/Op.h" +#include "coco/IR/Step.h" +#include "coco/IR/Part.h" + +#include <pepper/assert.h> + +namespace coco +{ +Op::~Op() +{ + // NOTE Op SHOULD NOT be referred by an instruction to be destructed + assert(_step == nullptr); +} + +Instr *Op::parent(void) const +{ + // Get the parent instruction specified by _step for root nodes + if (_step) + { + // Op SHOULD BE a root node + assert(_part == nullptr); + assert(_step->instr() != nullptr); + return _step->instr(); + } + + // Get the parent instruction of its parent Op for non-root nodes + if (_part) + { + assert(_part->parent() != nullptr); + return _part->parent()->parent(); + } + + return nullptr; +} + +Op *Op::up(void) const +{ + if (_part) + { + assert(_part->parent() != nullptr); + return _part->parent(); + } + return nullptr; +} + +// +// UnaryOP trait +// +UnaryOp::UnaryOp() : _arg{this} +{ + // DO NOTHING +} + +uint32_t UnaryOp::arity(void) const +{ + // There is only one argument + return 1; +} + +Op *UnaryOp::arg(DBGARG(uint32_t, n)) const +{ + assert(n < 1); + return arg(); +} + +std::set<Object *> UnaryOp::uses(void) const +{ + std::set<Object *> res; + + if (auto ifm = arg()) + { + for (auto obj : ifm->uses()) + { + res.insert(obj); + } + } + + return res; +} + +// +// BinaryOp trait +// +BinaryOp::BinaryOp() : _left{this}, _right{this} +{ + // DO NOTHING +} + +uint32_t BinaryOp::arity(void) const +{ + // There are two arguments + return 2; +} + +Op *BinaryOp::arg(uint32_t n) const +{ + assert(n < arity()); + + return (n == 0) ? left() : right(); +} + +std::set<Object *> BinaryOp::uses(void) const +{ + std::set<Object *> res; + + if (auto l = left()) + { + for (auto obj : l->uses()) + { + res.insert(obj); + } + } + + if (auto r = right()) + { + for (auto obj : r->uses()) + { + res.insert(obj); + } + } + + return res; +} + +// +// Additional Helpers +// +Op *root(Op *cur) +{ + while (cur->up()) + { + cur = cur->up(); + } + return cur; +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/OpManager.cpp b/compiler/coco/core/src/IR/OpManager.cpp new file mode 100644 index 000000000..c87b704fe --- /dev/null +++ b/compiler/coco/core/src/IR/OpManager.cpp @@ -0,0 +1,99 @@ +/* + * 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 "coco/IR/OpManager.h" + +#include <stdex/Memory.h> + +#include <cassert> +#include <queue> +#include <set> + +using stdex::make_unique; + +namespace coco +{ + +OpManager::~OpManager() +{ + std::set<coco::Op *> roots; + + for (uint32_t n = 0; n < size(); ++n) + { + auto op = at(n); + + if (op->up() != nullptr) + { + continue; + } + + roots.insert(op); + } + + for (const auto &op : roots) + { + destroy_all(op); + } +} + +// +// Each Op class SHOULD be default constructible +// +#define OP(Name) \ + template <> Name *OpManager::create<Name>(void) \ + { \ + auto op = make_unique<Name>(); \ + modulize(op.get()); \ + return take(std::move(op)); \ + } +#include "coco/IR/Op.lst" +#undef OP + +void OpManager::destroy(Op *op) +{ + assert(op->parent() == nullptr); + release(op); +} + +void OpManager::destroy_all(Op *op) +{ + assert(op->parent() == nullptr); + assert(op->up() == nullptr); + + std::queue<coco::Op *> q; + + q.emplace(op); + + while (q.size() > 0) + { + auto cur = q.front(); + q.pop(); + + // Insert child op nodes + for (uint32_t n = 0; n < cur->arity(); ++n) + { + if (auto child = cur->arg(n)) + { + q.emplace(child); + } + } + + // Destroy the current op node + destroy(cur); + } +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/OpManager.test.cpp b/compiler/coco/core/src/IR/OpManager.test.cpp new file mode 100644 index 000000000..9d463b3e4 --- /dev/null +++ b/compiler/coco/core/src/IR/OpManager.test.cpp @@ -0,0 +1,120 @@ +/* + * 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 "coco/IR/OpManager.h" + +#include <gtest/gtest.h> + +namespace +{ + +class OpManagerTest : public ::testing::Test +{ +protected: + coco::OpManager mgr; +}; + +} // namespace + +TEST(IR_OP_MANAGER, create_Conv2D) +{ + coco::OpManager mgr; + + auto obj = mgr.create<coco::Conv2D>(); + + ASSERT_NE(obj, nullptr); +} + +TEST(IR_OP_MANAGER, create_AvgPool2D) +{ + coco::OpManager mgr; + + auto obj = mgr.create<coco::AvgPool2D>(); + + ASSERT_NE(obj, nullptr); +} + +TEST_F(OpManagerTest, ReLU) +{ + auto obj = mgr.create<coco::ReLU>(); + + ASSERT_NE(obj, nullptr); +} + +TEST_F(OpManagerTest, ReLU6) +{ + auto obj = mgr.create<coco::ReLU6>(); + + ASSERT_NE(obj, nullptr); +} + +TEST_F(OpManagerTest, Sqrt) +{ + auto obj = mgr.create<coco::Sqrt>(); + + ASSERT_NE(obj, nullptr); +} + +TEST_F(OpManagerTest, Sub) +{ + auto obj = mgr.create<coco::Sub>(); + + ASSERT_NE(obj, nullptr); +} + +TEST_F(OpManagerTest, Div) +{ + auto obj = mgr.create<coco::Div>(); + + ASSERT_NE(obj, nullptr); +} + +TEST_F(OpManagerTest, PadF) +{ + auto op = mgr.create<coco::PadF>(); + ASSERT_NE(op, nullptr); + mgr.destroy(op); +} + +TEST_F(OpManagerTest, destroy) +{ + auto op = mgr.create<coco::Conv2D>(); + mgr.destroy(op); + ASSERT_EQ(mgr.size(), 0); +} + +TEST_F(OpManagerTest, destroy_all) +{ + // Create a Op tree + auto load_op = mgr.create<coco::Load>(); + auto conv_op = mgr.create<coco::Conv2D>(); + + conv_op->arg(load_op); + + mgr.destroy_all(conv_op); + + ASSERT_EQ(mgr.size(), 0); +} + +TEST_F(OpManagerTest, destroy_all_partial_tree) +{ + // Create a (partial) Op tree + auto conv_op = mgr.create<coco::Conv2D>(); + + mgr.destroy_all(conv_op); + + ASSERT_EQ(mgr.size(), 0); +} diff --git a/compiler/coco/core/src/IR/Ops.cpp b/compiler/coco/core/src/IR/Ops.cpp new file mode 100644 index 000000000..1c1ef5d28 --- /dev/null +++ b/compiler/coco/core/src/IR/Ops.cpp @@ -0,0 +1,22 @@ +/* + * 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 "coco/IR/Ops.h" + +namespace coco +{ + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Ops.test.cpp b/compiler/coco/core/src/IR/Ops.test.cpp new file mode 100644 index 000000000..ae979b2bf --- /dev/null +++ b/compiler/coco/core/src/IR/Ops.test.cpp @@ -0,0 +1,129 @@ +/* + * 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 "coco/IR/Ops.h" +#include "coco/IR/ObjectManager.h" +#include "coco/IR/OpManager.h" + +#include <vector> +#include <memory> + +#include <stdex/Memory.h> + +#include <gtest/gtest.h> + +using stdex::make_unique; + +/** + * Section: Add Op + */ +namespace +{ + +class AddTest : public ::testing::Test +{ +public: + AddTest() + { + // DO NOTHING + } + +protected: + coco::Add *allocate(void) + { + auto op = new coco::Add; + _allocated.emplace_back(op); + return op; + } + +protected: + coco::ObjectManager obj_mgr; + +private: + std::vector<std::unique_ptr<coco::Op>> _allocated; +}; + +} // namespace + +TEST_F(AddTest, constructor) +{ + auto op = allocate(); + + ASSERT_EQ(op->left(), nullptr); + ASSERT_EQ(op->right(), nullptr); +} + +/** + * Section: Mul Op + */ +TEST(MulTest, constructor) +{ + auto op = make_unique<coco::Mul>(); + + ASSERT_EQ(op->left(), nullptr); + ASSERT_EQ(op->right(), nullptr); +} + +/** + * Section: Div Op + */ +TEST(DivTest, constructor) +{ + auto op = make_unique<coco::Div>(); + + ASSERT_EQ(op->left(), nullptr); + ASSERT_EQ(op->right(), nullptr); +} + +/** + * Section: Op Helpers + */ +namespace +{ + +class OpHelperTest : public ::testing::Test +{ +public: + OpHelperTest() + { + // DO NOTHING + } + +protected: + template <typename Op> Op *allocate(void) { return op_mgr.create<Op>(); } + +protected: + coco::ObjectManager obj_mgr; + +private: + coco::OpManager op_mgr; +}; + +} // namespace + +TEST_F(OpHelperTest, root) +{ + auto load = allocate<coco::Load>(); + + ASSERT_EQ(root(load), load); + + auto avgpool = allocate<coco::AvgPool2D>(); + + avgpool->arg(load); + + ASSERT_EQ(root(load), avgpool); + ASSERT_EQ(root(avgpool), avgpool); +} diff --git a/compiler/coco/core/src/IR/Output.cpp b/compiler/coco/core/src/IR/Output.cpp new file mode 100644 index 000000000..7b6d1870b --- /dev/null +++ b/compiler/coco/core/src/IR/Output.cpp @@ -0,0 +1,41 @@ +/* + * 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 "coco/IR/Output.h" + +#include <cassert> + +namespace coco +{ + +Output::Output(const nncc::core::ADT::tensor::Shape &shape) : Arg{shape} +{ + // DO NOTHING +} + +void Output::onTake(Bag *bag) +{ + assert(bag->output() == nullptr); + bag->output(this); +} + +void Output::onRelease(Bag *bag) +{ + assert(bag->output() == this); + bag->output(nullptr); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Output.test.cpp b/compiler/coco/core/src/IR/Output.test.cpp new file mode 100644 index 000000000..715a83875 --- /dev/null +++ b/compiler/coco/core/src/IR/Output.test.cpp @@ -0,0 +1,83 @@ +/* + * 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 "coco/IR/Output.h" +#include "coco/IR/BagManager.h" + +#include <nncc/core/ADT/tensor/IndexEnumerator.h> + +#include <gtest/gtest.h> + +using nncc::core::ADT::tensor::Shape; +using nncc::core::ADT::tensor::IndexEnumerator; + +TEST(IR_OUTPUT, ctor_should_set_shape) +{ + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + coco::Output output{shape}; + + ASSERT_EQ(output.shape(), shape); +} + +TEST(IR_OUTPUT, bag_update) +{ + // Create a bag for test + coco::BagManager bag_mgr; + + auto bag = bag_mgr.create(9); + + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + coco::Output output{shape}; + + output.bag(bag); + ASSERT_EQ(output.bag(), bag); + + // bag(...) method SHOULD update 'bag' type + ASSERT_TRUE(bag->isOutput()); + + output.bag(nullptr); + + // bag(nullptr) SHOULD revert 'bag' type + ASSERT_FALSE(bag->isOutput()); +} + +TEST(IR_OUTPUT, name_update) +{ + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + coco::Output output{shape}; + + output.name("softmax"); + ASSERT_EQ(output.name(), "softmax"); +} + +TEST(IR_OUTPUT, at) +{ + const Shape shape{1, 3, 3, 1}; + coco::Output input{shape}; + + coco::Output *mutable_ptr = &input; + const coco::Output *immutable_ptr = &input; + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + mutable_ptr->at(e.current()) = coco::ElemID{16}; + } + + for (IndexEnumerator e{shape}; e.valid(); e.advance()) + { + ASSERT_EQ(immutable_ptr->at(e.current()).value(), 16); + } +} diff --git a/compiler/coco/core/src/IR/OutputManager.cpp b/compiler/coco/core/src/IR/OutputManager.cpp new file mode 100644 index 000000000..86b9580ac --- /dev/null +++ b/compiler/coco/core/src/IR/OutputManager.cpp @@ -0,0 +1,31 @@ +/* + * 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 "coco/IR/OutputManager.h" + +#include <stdex/Memory.h> + +namespace coco +{ + +Output *OutputManager::create(const nncc::core::ADT::tensor::Shape &shape) +{ + auto output = stdex::make_unique<Output>(shape); + modulize(output.get()); + return take(std::move(output)); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/OutputManager.test.cpp b/compiler/coco/core/src/IR/OutputManager.test.cpp new file mode 100644 index 000000000..80b38b42c --- /dev/null +++ b/compiler/coco/core/src/IR/OutputManager.test.cpp @@ -0,0 +1,29 @@ +/* + * 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 "coco/IR/OutputManager.h" + +#include <gtest/gtest.h> + +TEST(IR_OUTPUT_MANAGER, make) +{ + coco::OutputManager mgr; + + const nncc::core::ADT::tensor::Shape shape{1, 3, 3, 1}; + auto output = mgr.create(shape); + + ASSERT_EQ(output->shape(), shape); +} diff --git a/compiler/coco/core/src/IR/PadF.test.cpp b/compiler/coco/core/src/IR/PadF.test.cpp new file mode 100644 index 000000000..b443d86fb --- /dev/null +++ b/compiler/coco/core/src/IR/PadF.test.cpp @@ -0,0 +1,89 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +struct IsPadF : public coco::Op::Visitor<bool> +{ + bool visit(const coco::PadF *) override { return true; } +}; + +class PadFTest : public ::testing::Test +{ +public: + PadFTest() + { + // DO NOTHING + } + +protected: + coco::PadF *allocate(void) + { + auto op = new coco::PadF; + _allocated.emplace_back(op); + return op; + } + +private: + std::vector<std::unique_ptr<coco::PadF>> _allocated; +}; +} // namespace + +TEST_F(PadFTest, initialization) +{ + auto op = allocate(); + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); + + // arg() should be nullptr on construction + ASSERT_EQ(op->arg(), nullptr); + + // pad() should be a valid + ASSERT_NE(op->pad(), nullptr); +} + +TEST_F(PadFTest, asPadF) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asPadF(), op); + ASSERT_EQ(mutable_base->asPadF(), immutable_base->asPadF()); +} + +TEST_F(PadFTest, accept) +{ + // Test 'PadF' class + auto op = allocate(); + + coco::PadF *mutable_ptr = op; + const coco::PadF *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsPadF{})); + ASSERT_TRUE(immutable_ptr->accept(IsPadF{})); +} diff --git a/compiler/coco/core/src/IR/Padding2D.cpp b/compiler/coco/core/src/IR/Padding2D.cpp new file mode 100644 index 000000000..8cdc42638 --- /dev/null +++ b/compiler/coco/core/src/IR/Padding2D.cpp @@ -0,0 +1,46 @@ +/* + * 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 "coco/IR/Padding2D.h" + +namespace coco +{ + +Padding2D &Padding2D::top(uint32_t value) +{ + _top = value; + return (*this); +} + +Padding2D &Padding2D::bottom(uint32_t value) +{ + _bottom = value; + return (*this); +} + +Padding2D &Padding2D::left(uint32_t value) +{ + _left = value; + return (*this); +} + +Padding2D &Padding2D::right(uint32_t value) +{ + _right = value; + return (*this); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Padding2D.test.cpp b/compiler/coco/core/src/IR/Padding2D.test.cpp new file mode 100644 index 000000000..292ce7d17 --- /dev/null +++ b/compiler/coco/core/src/IR/Padding2D.test.cpp @@ -0,0 +1,51 @@ +/* + * 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 "coco/IR/Padding2D.h" + +#include <gtest/gtest.h> + +TEST(IR_PADDING, default_constructor) +{ + coco::Padding2D pad; + + ASSERT_EQ(pad.top(), 0); + ASSERT_EQ(pad.bottom(), 0); + ASSERT_EQ(pad.left(), 0); + ASSERT_EQ(pad.right(), 0); +} + +TEST(IR_PADDING, explicit_constructor_4) +{ + coco::Padding2D pad{1, 2, 3, 4}; + + ASSERT_EQ(pad.top(), 1); + ASSERT_EQ(pad.bottom(), 2); + ASSERT_EQ(pad.left(), 3); + ASSERT_EQ(pad.right(), 4); +} + +TEST(IR_PADDING, update) +{ + coco::Padding2D pad; + + pad.top(1).bottom(2).left(3).right(4); + + ASSERT_EQ(pad.top(), 1); + ASSERT_EQ(pad.bottom(), 2); + ASSERT_EQ(pad.left(), 3); + ASSERT_EQ(pad.right(), 4); +} diff --git a/compiler/coco/core/src/IR/Part.cpp b/compiler/coco/core/src/IR/Part.cpp new file mode 100644 index 000000000..bf68c1feb --- /dev/null +++ b/compiler/coco/core/src/IR/Part.cpp @@ -0,0 +1,45 @@ +/* + * 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 "coco/IR/Part.h" +#include "coco/IR/Op.h" + +#include <cassert> + +namespace coco +{ + +void Part::child(Op *c) +{ + if (_child != nullptr) + { + assert(_child->_part == this); + _child->_part = nullptr; + _child = nullptr; + } + + assert(_child == nullptr); + + if (c != nullptr) + { + assert(c->_part == nullptr); + assert(c->_step == nullptr); + _child = c; + _child->_part = this; + } +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Part.test.cpp b/compiler/coco/core/src/IR/Part.test.cpp new file mode 100644 index 000000000..87e0e1516 --- /dev/null +++ b/compiler/coco/core/src/IR/Part.test.cpp @@ -0,0 +1,70 @@ +/* + * 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 "coco/IR/Part.h" +#include "coco/IR/Op.h" + +#include <stdex/Memory.h> + +#include <gtest/gtest.h> + +using stdex::make_unique; + +namespace +{ +namespace mock +{ + +// TODO Inherit UnaryOp instead of Op +struct Op final : public coco::Op +{ +public: + Op() : _arg{this} + { + // DO NOTHING + } + +public: + uint32_t arity(void) const final { return 1; } + coco::Op *arg(uint32_t n) const final { return arg(); } + + std::set<coco::Object *> uses() const override { throw std::runtime_error{"Not supported"}; } + +public: + ::coco::Op *arg(void) const { return _arg.child(); } + void arg(::coco::Op *child) { _arg.child(child); } + +private: + coco::Part _arg; +}; + +} // namespace mock +} // namespace + +TEST(PartTest, destructor) +{ + auto parent = make_unique<::mock::Op>(); + auto child = make_unique<::mock::Op>(); + + parent->arg(child.get()); + ASSERT_EQ(parent->arg(), child.get()); + ASSERT_EQ(child->up(), parent.get()); + + parent.reset(); + + // NOTE parent SHOULD unlink itself from child on destruction + ASSERT_EQ(child->up(), nullptr); +} diff --git a/compiler/coco/core/src/IR/Producer.mock.h b/compiler/coco/core/src/IR/Producer.mock.h new file mode 100644 index 000000000..ffc343ee8 --- /dev/null +++ b/compiler/coco/core/src/IR/Producer.mock.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_PRODUCER_MOCK_H__ +#define __COCO_IR_PRODUCER_MOCK_H__ + +#include "coco/IR/Object.h" + +namespace +{ +namespace mock +{ +struct Producer final : public coco::Object::Producer +{ + coco::Instr *loc(void) override { return nullptr; } +}; +} // namespace mock +} // namespace + +#endif // __COCO_IR_PRODUCER_MOCK_H__ diff --git a/compiler/coco/core/src/IR/ReLU.test.cpp b/compiler/coco/core/src/IR/ReLU.test.cpp new file mode 100644 index 000000000..22ef1730e --- /dev/null +++ b/compiler/coco/core/src/IR/ReLU.test.cpp @@ -0,0 +1,85 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +struct IsReLU : public coco::Op::Visitor<bool> +{ + bool visit(const coco::ReLU *) override { return true; } +}; + +class ReLUTest : public ::testing::Test +{ +public: + ReLUTest() + { + // DO NOTHING + } + +protected: + coco::ReLU *allocate(void) + { + auto op = new coco::ReLU; + _allocated.emplace_back(op); + return op; + } + +private: + std::vector<std::unique_ptr<coco::ReLU>> _allocated; +}; +} // namespace + +TEST_F(ReLUTest, initialization) +{ + auto op = allocate(); + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); + + ASSERT_EQ(op->arg(), nullptr); +} + +TEST_F(ReLUTest, asReLU) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asReLU(), op); + ASSERT_EQ(mutable_base->asReLU(), immutable_base->asReLU()); +} + +TEST_F(ReLUTest, accept) +{ + // Test 'ReLU' class + auto op = allocate(); + + coco::ReLU *mutable_ptr = op; + const coco::ReLU *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsReLU{})); + ASSERT_TRUE(immutable_ptr->accept(IsReLU{})); +} diff --git a/compiler/coco/core/src/IR/ReLU6.test.cpp b/compiler/coco/core/src/IR/ReLU6.test.cpp new file mode 100644 index 000000000..dd148254f --- /dev/null +++ b/compiler/coco/core/src/IR/ReLU6.test.cpp @@ -0,0 +1,85 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +struct IsReLU6 : public coco::Op::Visitor<bool> +{ + bool visit(const coco::ReLU6 *) override { return true; } +}; + +class ReLU6Test : public ::testing::Test +{ +public: + ReLU6Test() + { + // DO NOTHING + } + +protected: + coco::ReLU6 *allocate(void) + { + auto op = new coco::ReLU6; + _allocated.emplace_back(op); + return op; + } + +private: + std::vector<std::unique_ptr<coco::ReLU6>> _allocated; +}; +} // namespace + +TEST_F(ReLU6Test, initialization) +{ + auto op = allocate(); + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); + + ASSERT_EQ(op->arg(), nullptr); +} + +TEST_F(ReLU6Test, asReLU6) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asReLU6(), op); + ASSERT_EQ(mutable_base->asReLU6(), immutable_base->asReLU6()); +} + +TEST_F(ReLU6Test, accept) +{ + // Test 'ReLU6' class + auto op = allocate(); + + coco::ReLU6 *mutable_ptr = op; + const coco::ReLU6 *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsReLU6{})); + ASSERT_TRUE(immutable_ptr->accept(IsReLU6{})); +} diff --git a/compiler/coco/core/src/IR/Read.cpp b/compiler/coco/core/src/IR/Read.cpp new file mode 100644 index 000000000..ea01cce1d --- /dev/null +++ b/compiler/coco/core/src/IR/Read.cpp @@ -0,0 +1,49 @@ +/* + * 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 "coco/IR/Read.h" + +#include <cassert> + +namespace coco +{ + +Read::~Read() +{ + // Unlink self from Bag if there is a linked bag + bag(nullptr); +} + +void Read::bag(Bag *bag) +{ + if (_bag) + { + _bag->mutable_reads()->erase(this); + _bag = nullptr; + } + + assert(_bag == nullptr); + + if (bag) + { + _bag = bag; + _bag->mutable_reads()->insert(this); + } + + assert(_bag == bag); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Read.test.cpp b/compiler/coco/core/src/IR/Read.test.cpp new file mode 100644 index 000000000..7c36820a6 --- /dev/null +++ b/compiler/coco/core/src/IR/Read.test.cpp @@ -0,0 +1,81 @@ +/* + * 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 "coco/IR/Read.h" +#include "coco/IR/BagManager.h" + +#include "Reader.mock.h" + +#include <gtest/gtest.h> + +namespace +{ +class ReadTest : public ::testing::Test +{ +protected: + coco::BagManager bag_mgr; +}; +} // namespace + +TEST_F(ReadTest, constructor) +{ + // TODO Rename 'read' as 'reader' + ::mock::Reader read; + + // TODO Rename 'slot' + coco::Read slot{&read}; + + ASSERT_EQ(slot.bag(), nullptr); +} + +TEST_F(ReadTest, value) +{ + // TODO Rename 'read' as 'reader' + ::mock::Reader read; + + // TODO Rename 'slot' + coco::Read slot{&read}; + + auto bag = bag_mgr.create(16); + + slot.bag(bag); + + ASSERT_EQ(slot.bag(), bag); + + ASSERT_EQ(bag->reads()->size(), 1); + ASSERT_NE(bag->reads()->find(&slot), bag->reads()->end()); + + slot.bag(nullptr); + + ASSERT_EQ(slot.bag(), nullptr); + + ASSERT_EQ(bag->reads()->size(), 0); +} + +TEST_F(ReadTest, unlink_on_destruction) +{ + // TODO Rename 'read' as 'reader' + ::mock::Reader reader; + + auto bag = bag_mgr.create(1); + + { + coco::Read read{&reader}; + read.bag(bag); + } + + ASSERT_EQ(bag->reads()->size(), 0); +} diff --git a/compiler/coco/core/src/IR/Reader.mock.h b/compiler/coco/core/src/IR/Reader.mock.h new file mode 100644 index 000000000..0965abfeb --- /dev/null +++ b/compiler/coco/core/src/IR/Reader.mock.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_READER_MOCK_H__ +#define __COCO_IR_READER_MOCK_H__ + +#include "coco/IR/Bag.h" + +namespace +{ +namespace mock +{ +struct Reader final : public coco::Bag::Reader +{ + coco::Instr *loc(void) override { return nullptr; } +}; +} // namespace mock +} // namespace + +#endif // __COCO_IR_READER_MOCK_H__ diff --git a/compiler/coco/core/src/IR/Shuffle.cpp b/compiler/coco/core/src/IR/Shuffle.cpp new file mode 100644 index 000000000..f8007dd1b --- /dev/null +++ b/compiler/coco/core/src/IR/Shuffle.cpp @@ -0,0 +1,41 @@ +/* + * 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 "coco/IR/Instrs.h" + +namespace coco +{ + +uint32_t Shuffle::size(void) const { return _content.size(); } + +std::set<ElemID> Shuffle::range(void) const +{ + std::set<ElemID> res; + + for (auto it = _content.begin(); it != _content.end(); ++it) + { + res.insert(it->first); + } + + return res; +} + +void Shuffle::insert(const ElemID &from, const ElemID &into) { _content[into] = from; } + +void Shuffle::from(Bag *b) { _from.bag(b); } +void Shuffle::into(Bag *b) { _into.bag(b); } + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Shuffle.test.cpp b/compiler/coco/core/src/IR/Shuffle.test.cpp new file mode 100644 index 000000000..f564c08c3 --- /dev/null +++ b/compiler/coco/core/src/IR/Shuffle.test.cpp @@ -0,0 +1,95 @@ +/* + * 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 "coco/IR/Instrs.h" +#include "coco/IR/ObjectManager.h" +#include "coco/IR/OpManager.h" + +#include <gtest/gtest.h> + +namespace +{ +class ShuffleTest : public ::testing::Test +{ +public: + virtual ~ShuffleTest() = default; + +protected: + coco::Shuffle *allocate(void) + { + auto ins = new coco::Shuffle; + _allocated.emplace_back(ins); + return ins; + } + +private: + std::vector<std::unique_ptr<coco::Instr>> _allocated; +}; +} // namespace + +TEST_F(ShuffleTest, constructor) +{ + auto ins = allocate(); + + ASSERT_EQ(ins->from(), nullptr); + ASSERT_EQ(ins->into(), nullptr); +} + +TEST_F(ShuffleTest, asShuffle) +{ + auto ins = allocate(); + + coco::Instr *mutable_ptr = ins; + const coco::Instr *immutable_ptr = ins; + + ASSERT_NE(mutable_ptr->asShuffle(), nullptr); + ASSERT_EQ(mutable_ptr->asShuffle(), immutable_ptr->asShuffle()); +} + +TEST_F(ShuffleTest, size) +{ + auto shuffle = allocate(); + + shuffle->insert(coco::ElemID{3}, coco::ElemID{2}); + shuffle->insert(coco::ElemID{3}, coco::ElemID{5}); + + ASSERT_EQ(shuffle->size(), 2); + ASSERT_EQ(shuffle->range().size(), shuffle->size()); +} + +TEST_F(ShuffleTest, range) +{ + auto shuffle = allocate(); + + shuffle->insert(coco::ElemID{3}, coco::ElemID{2}); + shuffle->insert(coco::ElemID{3}, coco::ElemID{5}); + + auto range = shuffle->range(); + + EXPECT_EQ(range.size(), 2); + EXPECT_NE(range.count(coco::ElemID{2}), 0); + EXPECT_NE(range.count(coco::ElemID{5}), 0); +} + +TEST_F(ShuffleTest, defined) +{ + auto shuffle = allocate(); + + shuffle->insert(coco::ElemID{3}, coco::ElemID{2}); + + EXPECT_TRUE(shuffle->defined(coco::ElemID{2})); + EXPECT_FALSE(shuffle->defined(coco::ElemID{3})); +} diff --git a/compiler/coco/core/src/IR/Sqrt.test.cpp b/compiler/coco/core/src/IR/Sqrt.test.cpp new file mode 100644 index 000000000..cf9b232ea --- /dev/null +++ b/compiler/coco/core/src/IR/Sqrt.test.cpp @@ -0,0 +1,85 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +struct IsSqrt : public coco::Op::Visitor<bool> +{ + bool visit(const coco::Sqrt *) override { return true; } +}; + +class SqrtTest : public ::testing::Test +{ +public: + SqrtTest() + { + // DO NOTHING + } + +protected: + coco::Sqrt *allocate(void) + { + auto op = new coco::Sqrt; + _allocated.emplace_back(op); + return op; + } + +private: + std::vector<std::unique_ptr<coco::Sqrt>> _allocated; +}; +} // namespace + +TEST_F(SqrtTest, initialization) +{ + auto op = allocate(); + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); + + ASSERT_EQ(op->arg(), nullptr); +} + +TEST_F(SqrtTest, asSqrt) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asSqrt(), op); + ASSERT_EQ(mutable_base->asSqrt(), immutable_base->asSqrt()); +} + +TEST_F(SqrtTest, accept) +{ + // Test 'Sqrt' class + auto op = allocate(); + + coco::Sqrt *mutable_ptr = op; + const coco::Sqrt *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsSqrt{})); + ASSERT_TRUE(immutable_ptr->accept(IsSqrt{})); +} diff --git a/compiler/coco/core/src/IR/Step.cpp b/compiler/coco/core/src/IR/Step.cpp new file mode 100644 index 000000000..04400d46b --- /dev/null +++ b/compiler/coco/core/src/IR/Step.cpp @@ -0,0 +1,52 @@ +/* + * 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 "coco/IR/Step.h" +#include "coco/IR/Op.h" + +#include <cassert> + +namespace coco +{ + +void Step::op(Op *o) +{ + if (_op != nullptr) + { + // Unlink step from _op + assert(_op->_step == this); + _op->_step = nullptr; + + // Reset _op + _op = nullptr; + } + + assert(_op == nullptr); + + if (o) + { + // Update _op + _op = o; + + // Link step to _op + assert(_op->_step == nullptr); + _op->_step = this; + } + + assert(_op == o); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Stride2D.cpp b/compiler/coco/core/src/IR/Stride2D.cpp new file mode 100644 index 000000000..a034876ef --- /dev/null +++ b/compiler/coco/core/src/IR/Stride2D.cpp @@ -0,0 +1,34 @@ +/* + * 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 "coco/IR/Stride2D.h" + +namespace coco +{ + +Stride2D &Stride2D::vertical(uint32_t value) +{ + _vertical = value; + return (*this); +} + +Stride2D &Stride2D::horizontal(uint32_t value) +{ + _horizontal = value; + return (*this); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Stride2D.test.cpp b/compiler/coco/core/src/IR/Stride2D.test.cpp new file mode 100644 index 000000000..43d159ee0 --- /dev/null +++ b/compiler/coco/core/src/IR/Stride2D.test.cpp @@ -0,0 +1,45 @@ +/* + * 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 "coco/IR/Stride2D.h" + +#include <gtest/gtest.h> + +TEST(IR_STRIDE_2D, default_constructor) +{ + coco::Stride2D stride; + + ASSERT_EQ(stride.vertical(), 1); + ASSERT_EQ(stride.horizontal(), 1); +} + +TEST(IR_STRIDE_2D, explicit_constructor_4) +{ + coco::Stride2D stride{2, 3}; + + ASSERT_EQ(stride.vertical(), 2); + ASSERT_EQ(stride.horizontal(), 3); +} + +TEST(IR_STRIDE_2D, update) +{ + coco::Stride2D stride; + + stride.vertical(2).horizontal(3); + + ASSERT_EQ(stride.vertical(), 2); + ASSERT_EQ(stride.horizontal(), 3); +} diff --git a/compiler/coco/core/src/IR/Sub.test.cpp b/compiler/coco/core/src/IR/Sub.test.cpp new file mode 100644 index 000000000..6c8b9ba54 --- /dev/null +++ b/compiler/coco/core/src/IR/Sub.test.cpp @@ -0,0 +1,87 @@ +/* + * 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 "coco/IR/Ops.h" + +#include <memory> +#include <vector> + +#include <gtest/gtest.h> + +namespace +{ +struct IsSub : public coco::Op::Visitor<bool> +{ + bool visit(const coco::Sub *) override { return true; } +}; + +class SubTest : public ::testing::Test +{ +public: + SubTest() + { + // DO NOTHING + } + +protected: + coco::Sub *allocate(void) + { + auto op = new coco::Sub; + _allocated.emplace_back(op); + return op; + } + +private: + std::vector<std::unique_ptr<coco::Sub>> _allocated; +}; +} // namespace + +TEST_F(SubTest, initialization) +{ + auto op = allocate(); + + // arguments should be empty on construction + ASSERT_EQ(op->left(), nullptr); + ASSERT_EQ(op->right(), nullptr); + + // uses() should be empty on construction + ASSERT_EQ(op->uses().size(), 0); + // parent() should be nullptr on construction + ASSERT_EQ(op->parent(), nullptr); +} + +TEST_F(SubTest, asSub) +{ + auto op = allocate(); + + coco::Op *mutable_base = op; + const coco::Op *immutable_base = op; + + ASSERT_EQ(mutable_base->asSub(), op); + ASSERT_EQ(mutable_base->asSub(), immutable_base->asSub()); +} + +TEST_F(SubTest, accept) +{ + // Test 'Sub' class + auto op = allocate(); + + coco::Sub *mutable_ptr = op; + const coco::Sub *immutable_ptr = op; + + ASSERT_TRUE(mutable_ptr->accept(IsSub{})); + ASSERT_TRUE(immutable_ptr->accept(IsSub{})); +} diff --git a/compiler/coco/core/src/IR/Update.cpp b/compiler/coco/core/src/IR/Update.cpp new file mode 100644 index 000000000..8e81c85cf --- /dev/null +++ b/compiler/coco/core/src/IR/Update.cpp @@ -0,0 +1,49 @@ +/* + * 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 "coco/IR/Update.h" + +#include <cassert> + +namespace coco +{ + +Update::~Update() +{ + // Unlink self from a linked bag if it exists + bag(nullptr); +} + +void Update::bag(Bag *bag) +{ + if (_bag) + { + _bag->mutable_updates()->erase(this); + _bag = nullptr; + } + + assert(_bag == nullptr); + + if (bag) + { + _bag = bag; + _bag->mutable_updates()->insert(this); + } + + assert(_bag == bag); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Update.test.cpp b/compiler/coco/core/src/IR/Update.test.cpp new file mode 100644 index 000000000..0bd355998 --- /dev/null +++ b/compiler/coco/core/src/IR/Update.test.cpp @@ -0,0 +1,81 @@ +/* + * 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 "coco/IR/Update.h" +#include "coco/IR/BagManager.h" + +#include "Updater.mock.h" + +#include <gtest/gtest.h> + +namespace +{ +class UpdateTest : public ::testing::Test +{ +protected: + coco::BagManager bag_mgr; +}; +} // namespace + +TEST_F(UpdateTest, constructor) +{ + // TODO Rename 'update' + ::mock::Updater update; + + // TODO Rename 'slot' + coco::Update slot{&update}; + + ASSERT_EQ(slot.bag(), nullptr); +} + +TEST_F(UpdateTest, value) +{ + // TODO Rename 'update' + ::mock::Updater update; + + // TODO Rename 'slot' + coco::Update slot{&update}; + + auto bag = bag_mgr.create(16); + + slot.bag(bag); + + ASSERT_EQ(slot.bag(), bag); + + ASSERT_EQ(bag->updates()->size(), 1); + ASSERT_NE(bag->updates()->find(&slot), bag->updates()->end()); + + slot.bag(nullptr); + + ASSERT_EQ(slot.bag(), nullptr); + + ASSERT_EQ(bag->updates()->size(), 0); +} + +TEST_F(UpdateTest, unlink_on_destruction) +{ + ::mock::Updater updater; + + auto bag = bag_mgr.create(1); + + { + coco::Update update{&updater}; + update.bag(bag); + ASSERT_EQ(bag->updates()->size(), 1); + } + + ASSERT_EQ(bag->updates()->size(), 0); +} diff --git a/compiler/coco/core/src/IR/Updater.mock.h b/compiler/coco/core/src/IR/Updater.mock.h new file mode 100644 index 000000000..6441cdd02 --- /dev/null +++ b/compiler/coco/core/src/IR/Updater.mock.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef __COCO_IR_UPDATER_MOCK_H__ +#define __COCO_IR_UPDATER_MOCK_H__ + +#include "coco/IR/Bag.h" + +namespace +{ +namespace mock +{ +struct Updater final : public coco::Bag::Updater +{ + coco::Instr *loc(void) override { return nullptr; } +}; +} // namespace mock +} // namespace + +#endif // __COCO_IR_UPDATER_MOCK_H__ diff --git a/compiler/coco/core/src/IR/Use.cpp b/compiler/coco/core/src/IR/Use.cpp new file mode 100644 index 000000000..cd9b68105 --- /dev/null +++ b/compiler/coco/core/src/IR/Use.cpp @@ -0,0 +1,43 @@ +/* + * 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 "coco/IR/Use.h" + +#include <cassert> + +namespace coco +{ + +void Use::value(Object *value) +{ + if (_value) + { + _value->mutable_uses()->erase(this); + _value = nullptr; + } + + assert(_value == nullptr); + + if (value) + { + _value = value; + _value->mutable_uses()->insert(this); + } + + assert(_value == value); +} + +} // namespace coco diff --git a/compiler/coco/core/src/IR/Use.test.cpp b/compiler/coco/core/src/IR/Use.test.cpp new file mode 100644 index 000000000..3191e9852 --- /dev/null +++ b/compiler/coco/core/src/IR/Use.test.cpp @@ -0,0 +1,86 @@ +/* + * 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 "coco/IR/Use.h" +#include "coco/IR/ObjectManager.h" + +#include "coco/IR/FeatureObject.h" + +#include "Consumer.mock.h" + +#include <stdex/Memory.h> + +#include <gtest/gtest.h> + +using stdex::make_unique; + +namespace +{ +class UseTest : public ::testing::Test +{ +protected: + coco::ObjectManager obj_mgr; +}; +} // namespace + +TEST_F(UseTest, constructor) +{ + auto o = obj_mgr.create<coco::FeatureObject>(); + + // TODO Rename 'use' + ::mock::Consumer use; + + coco::Use slot{&use}; + + ASSERT_EQ(slot.value(), nullptr); +} + +TEST_F(UseTest, value) +{ + auto o = obj_mgr.create<coco::FeatureObject>(); + + // TODO Rename 'use' + ::mock::Consumer use; + + coco::Use slot{&use}; + + slot.value(o); + + ASSERT_EQ(slot.value(), o); + + ASSERT_EQ(o->uses()->size(), 1); + ASSERT_NE(o->uses()->find(&slot), o->uses()->end()); + + slot.value(nullptr); + + ASSERT_EQ(slot.value(), nullptr); + + ASSERT_EQ(o->uses()->size(), 0); +} + +TEST_F(UseTest, destructor) +{ + ::mock::Consumer consumer; + + auto o = obj_mgr.create<coco::FeatureObject>(); + auto use = make_unique<coco::Use>(&consumer); + + use->value(o); + use.reset(); + + // ~Use SHOULD unlink itself from linked Object (if exists) + ASSERT_EQ(o->uses()->size(), 0); +} diff --git a/compiler/coco/core/src/IR/Window2D.test.cpp b/compiler/coco/core/src/IR/Window2D.test.cpp new file mode 100644 index 000000000..c0e919237 --- /dev/null +++ b/compiler/coco/core/src/IR/Window2D.test.cpp @@ -0,0 +1,46 @@ +/* + * 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 "coco/IR/Window2D.h" + +#include <gtest/gtest.h> + +TEST(IR_WINDOW_2D, default_constructor) +{ + coco::Window2D window; + + ASSERT_EQ(window.height(), 1); + ASSERT_EQ(window.width(), 1); +} + +TEST(IR_WINDOW_2D, explicit_constructor_4) +{ + coco::Window2D window{2, 3}; + + ASSERT_EQ(window.height(), 2); + ASSERT_EQ(window.width(), 3); +} + +TEST(IR_WINDOW_2D, update) +{ + coco::Window2D window; + + window.height(2); + window.width(3); + + ASSERT_EQ(window.height(), 2); + ASSERT_EQ(window.width(), 3); +} |