009efdd8f0e4231d37780a849fb21030603efbf4
1 /******************************************************************************
2 * Copyright (c) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Texas Instruments Incorporated nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *****************************************************************************/
29 //
30 // This example illustrates using a single EO to process a frame. To increase
31 // throughput, multiple EOs are used.
32 // For details, refer http://downloads.ti.com/mctools/esd/docs/tidl-api/
33 //
34 #include <signal.h>
35 #include <iostream>
36 #include <fstream>
37 #include <cassert>
38 #include <string>
40 #include "executor.h"
41 #include "execution_object.h"
42 #include "configuration.h"
43 #include "utils.h"
45 using namespace tidl;
46 using std::string;
47 using std::unique_ptr;
48 using std::vector;
50 bool Run(const string& config_file, int num_eve,int num_dsp,
51 const char* ref_output);
53 Executor* CreateExecutor(DeviceType dt, int num, const Configuration& c);
54 void CollectEOs(const Executor *e, vector<ExecutionObject *>& EOs);
56 void AllocateMemory(const vector<ExecutionObject *>& EOs);
57 void FreeMemory (const vector<ExecutionObject *>& EOs);
60 int main(int argc, char *argv[])
61 {
62 // Catch ctrl-c to ensure a clean exit
63 signal(SIGABRT, exit);
64 signal(SIGTERM, exit);
66 // If there are no devices capable of offloading TIDL on the SoC, exit
67 uint32_t num_eve = Executor::GetNumDevices(DeviceType::EVE);
68 uint32_t num_dsp = Executor::GetNumDevices(DeviceType::DSP);
69 if (num_eve == 0 && num_dsp == 0)
70 {
71 std::cout << "TI DL not supported on this SoC." << std::endl;
72 return EXIT_SUCCESS;
73 }
75 string config_file ="../test/testvecs/config/infer/tidl_config_j11_v2.txt";
76 string ref_file ="../test/testvecs/reference/j11_v2_ref.bin";
78 unique_ptr<const char> reference_output(ReadReferenceOutput(ref_file));
80 bool status = Run(config_file, num_eve, num_dsp, reference_output.get());
82 if (!status)
83 {
84 std::cout << "FAILED" << std::endl;
85 return EXIT_FAILURE;
86 }
88 std::cout << "PASSED" << std::endl;
89 return EXIT_SUCCESS;
90 }
92 bool Run(const string& config_file, int num_eve, int num_dsp,
93 const char* ref_output)
94 {
95 Configuration c;
96 if (!c.ReadFromFile(config_file))
97 return false;
99 // Heap sizes for this network determined using Configuration::showHeapStats
100 c.PARAM_HEAP_SIZE = (3 << 20); // 3MB
101 c.NETWORK_HEAP_SIZE = (20 << 20); // 20MB
103 c.numFrames = 16;
105 // Open input file for reading
106 std::ifstream input_data_file(c.inData, std::ios::binary);
108 bool status = true;
109 try
110 {
111 // Create Executors - use all the DSP and EVE cores available
112 unique_ptr<Executor> e_dsp(CreateExecutor(DeviceType::DSP, num_dsp, c));
113 unique_ptr<Executor> e_eve(CreateExecutor(DeviceType::EVE, num_eve, c));
115 // Accumulate all the EOs from across the Executors
116 vector<ExecutionObject *> EOs;
117 CollectEOs(e_eve.get(), EOs);
118 CollectEOs(e_dsp.get(), EOs);
120 AllocateMemory(EOs);
122 // Process frames with EOs in a pipelined manner
123 // additional num_eos iterations to flush the pipeline (epilogue)
124 int num_eos = EOs.size();
125 for (int frame_idx = 0; frame_idx < c.numFrames + num_eos; frame_idx++)
126 {
127 ExecutionObject* eo = EOs[frame_idx % num_eos];
129 // Wait for previous frame on the same eo to finish processing
130 if (eo->ProcessFrameWait())
131 {
132 ReportTime(eo);
133 if (frame_idx < num_eos && !CheckFrame(eo, ref_output))
134 status = false;
135 }
137 // Read a frame and start processing it with current eo
138 if (ReadFrame(eo, frame_idx, c, input_data_file))
139 eo->ProcessFrameStartAsync();
140 }
142 FreeMemory(EOs);
144 }
145 catch (tidl::Exception &e)
146 {
147 std::cerr << e.what() << std::endl;
148 status = false;
149 }
151 input_data_file.close();
153 return status;
154 }
156 // Create an Executor with the specified type and number of EOs
157 Executor* CreateExecutor(DeviceType dt, int num, const Configuration& c)
158 {
159 if (num == 0) return nullptr;
161 DeviceIds ids;
162 for (int i = 0; i < num; i++)
163 ids.insert(static_cast<DeviceId>(i));
165 return new Executor(dt, ids, c);
166 }
168 // Accumulate EOs from an Executor into a vector of EOs
169 void CollectEOs(const Executor *e, vector<ExecutionObject *>& EOs)
170 {
171 if (!e) return;
173 for (unsigned int i = 0; i < e->GetNumExecutionObjects(); i++)
174 EOs.push_back((*e)[i]);
175 }
177 // Allocate input and output memory for each EO
178 void AllocateMemory(const vector<ExecutionObject *>& EOs)
179 {
180 // Allocate input and output buffers for each execution object
181 for (auto eo : EOs)
182 {
183 size_t in_size = eo->GetInputBufferSizeInBytes();
184 size_t out_size = eo->GetOutputBufferSizeInBytes();
185 ArgInfo in = { ArgInfo(malloc(in_size), in_size)};
186 ArgInfo out = { ArgInfo(malloc(out_size), out_size)};
187 eo->SetInputOutputBuffer(in, out);
188 }
189 }
191 // Free the input and output memory associated with each EO
192 void FreeMemory(const vector<ExecutionObject *>& EOs)
193 {
194 for (auto eo : EOs)
195 {
196 free(eo->GetInputBufferPtr());
197 free(eo->GetOutputBufferPtr());
198 }
200 }