ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Backend.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "enco/Backend.h"
18
19#include "IRValidator.h"
20
21#include "Session.h"
22#include "Pipeline.h"
23
24#include "Code.h"
25#include "AsmCode.h"
26#include "CppCode.h"
27
44#include "Transforms/Split.h"
46
47#include <memory>
48#include <stdexcept>
49#include <iostream>
50#include <fstream>
51
52using std::make_unique;
53using namespace enco;
54
55namespace
56{
57
58// has_inout_bag(m) returns true if there is a pair of coco::Input and coco::Output that share
59// the same bag as their backing storage
60inline bool has_inout_bag(const coco::Module *m)
61{
62 for (uint32_t n = 0; n < m->entity()->bag()->size(); ++n)
63 {
64 auto bag = m->entity()->bag()->at(n);
65
66 if (bag->isInput() && bag->isOutput())
67 {
68 return true;
69 }
70 }
71 return false;
72}
73
74class BackendImpl final : public enco::Backend
75{
76public:
77 BackendImpl(const std::string &prefix) : _prefix{prefix}
78 {
79 // DO NOTHING
80 }
81
82public:
83 void compile(coco::Module *m, coco::Data *d) override;
84
85private:
86 std::string _prefix;
87};
88
89void BackendImpl::compile(coco::Module *m, coco::Data *d)
90{
91 auto sess = make_session(m, d);
92
93 // validate if IR from frontend is correct
94 assert(validate(code(sess)));
95
96 enco::Pipeline pipeline;
97
98 // Configure pipeline
99
100 // As explained below, the current implementation does not work if there is a pair of input/output
101 // that share the same bag as their underlying bag.
102 //
103 // BagDuplicationPass creates a copy of such bags in order to eliminate such a pair.
104 pipeline.append(make_unique<BagDuplicationPass>());
105 pipeline.append(make_unique<FeatureUnificationPass>());
106 pipeline.append(make_unique<AvgPoolLoweringPass>());
107 pipeline.append(make_unique<IntrinsicSelectionPass>());
108 // Insert data ordering if necessary
109 pipeline.append(make_unique<DataLayoutConversionPass>());
110 pipeline.append(make_unique<IndirectCopyEliminationPass>());
111 pipeline.append(make_unique<IdenticalObjectReductionPass>());
112 pipeline.append(make_unique<DuplicatedObjectReductionPass>());
113 pipeline.append(make_unique<ConstantFoldingPass>());
114 // Eliminate dead object
115 //
116 // NOTE Dead Object Elimination (DOE) is performed before Copy lowering
117 // in order to reduce compilation overhead.
118 pipeline.append(make_unique<DeadObjectEliminationPass>());
119 // Lower Copy as Shuffle
120 pipeline.append(make_unique<CopyLoweringPass>());
121 // Lower ConcatF as Shuffle if it is not delegated to NNAPI yet
122 pipeline.append(make_unique<ConcatLoweringPass>());
123 pipeline.append(make_unique<BypassGenerationPass>());
124 pipeline.append(make_unique<FreeInstrEliminationPass>());
125 // NOTE Free Op Elimination should be applied after Free Instr Elimination
126 // - Free Instr Elimination may generate additional free Op(s)
127 pipeline.append(make_unique<FreeOpEliminationPass>());
128 pipeline.append(make_unique<DeadBagEliminationPass>());
129 // Split instructions into a set of phases (each block serves as a phase)
130 pipeline.append(make_unique<PhaseConstructionPass>());
131
132 // Apply transforms in the pipeline
133 for (uint32_t n = 0; n < pipeline.size(); ++n)
134 {
135 const auto &pass = pipeline.at(n);
136
137 pass.run(sess);
138 }
139
140 // The current implementation will assign memory region for each bag as follows:
141 // Bind input bag to the region provided by Network_input_bind
142 // Bind output bag to the region provided by Network_output_bind
143 // Bind intermediate bag to the region allocated during execution
144 //
145 // Note that this scheme does not work if there is a pair of input/output
146 // that share the same bag as their underlying bag
147 assert(!has_inout_bag(code(sess)->module()));
148
149 const std::string data_var = "data";
150 const std::string data_filename = _prefix + ".bin";
151
152 // Generate 'bin' file
153 {
154 std::ofstream ofs{data_filename, std::ios::binary};
155 generate_global_data(ofs, code(sess));
156 }
157
158 // Generate 'embed.S' file
159 {
160 std::ofstream ofs{_prefix + ".embed.S"};
161 ofs << AsmCode{data_filename, data_var};
162 }
163
164 // TODO Run various transforms over enco::Code
165
166 std::ofstream ofs{_prefix + ".cpp"};
167 ofs << CppCode{data_var, code(sess)} << std::endl;
168}
169
170} // namespace
171
172#include <iostream>
173
174std::unique_ptr<enco::Backend> make_backend(const cmdline::View &cmdline)
175{
176 return make_unique<::BackendImpl>(cmdline.at(0));
177}
Top-level element of coco IR which represents a neural network.
Definition Module.h:34
virtual void run(const SessionID &) const =0
uint32_t size(void) const
Definition Pipeline.h:32
void append(std::unique_ptr< Pass > &&pass)
Definition Pipeline.h:38
const Pass & at(uint32_t n) const
Definition Pipeline.h:35
std::unique_ptr< enco::Backend > make_backend(const cmdline::View &cmdline)
Definition Backend.cpp:174
Definition View.h:23
Definition Bundle.h:26
void generate_global_data(std::ostream &os, enco::Code *code)
Generate 'Global' weight array.
Code * code(const SessionID &sess)
Definition Session.cpp:54
coco::Module * module(const SessionID &sess)
Definition Session.cpp:51
SessionID make_session(coco::Module *m, coco::Data *d)
Definition Session.cpp:36
bool validate(Code *code)
int32_t size[5]
Definition Slice.cpp:35
Core coco entity for constant weights.
Definition Data.h:31
virtual void compile(coco::Module *m, coco::Data *d)=0