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 *****************************************************************************/
28 #include <signal.h>
29 #include <getopt.h>
30 #include <iostream>
31 #include <fstream>
32 #include <cassert>
33 #include <string>
35 #include "executor.h"
36 #include "execution_object.h"
37 #include "configuration.h"
38 #include "utils.h"
40 using namespace tidl;
42 bool RunConfiguration(const std::string& config_file, int num_devices,
43 DeviceType device_type);
45 static void ProcessTrace(const ExecutionObject* eo, const Configuration& c);
47 int main(int argc, char *argv[])
48 {
49 // Catch ctrl-c to ensure a clean exit
50 signal(SIGABRT, exit);
51 signal(SIGTERM, exit);
53 std::cout << "API Version: " << Executor::GetAPIVersion() << std::endl;
55 // If there are no devices capable of offloading TIDL on the SoC, exit
56 uint32_t num_eve = Executor::GetNumDevices(DeviceType::EVE);
57 uint32_t num_dsp = Executor::GetNumDevices(DeviceType::DSP);
58 if (num_eve == 0 && num_dsp == 0)
59 {
60 std::cout << "TI DL not supported on this SoC." << std::endl;
61 return EXIT_SUCCESS;
62 }
64 // Configuration file with tracing enabled
65 std::string config_file = "j11_v2_trace.txt";
66 int num_devices = 1;
67 DeviceType device_type = num_eve > 0 ? DeviceType::EVE :
68 DeviceType::DSP;
70 bool status = RunConfiguration(config_file, num_devices, device_type);
72 if (!status)
73 {
74 std::cout << "tidl FAILED" << std::endl;
75 return EXIT_FAILURE;
76 }
78 std::cout << "tidl PASSED" << std::endl;
79 return EXIT_SUCCESS;
80 }
82 bool RunConfiguration(const std::string& config_file, int num_devices,
83 DeviceType device_type)
84 {
85 DeviceIds ids;
86 for (int i = 0; i < num_devices; i++)
87 ids.insert(static_cast<DeviceId>(i));
89 // Read the TI DL configuration file
90 Configuration c;
91 if (!c.ReadFromFile(config_file))
92 return false;
94 // Open input files
95 std::ifstream input(c.inData, std::ios::binary);
96 assert (input.good());
98 bool status = true;
100 try
101 {
102 // Create a executor with the specified core type, number of cores
103 // and configuration
104 Executor E(device_type, ids, c);
106 std::vector<ExecutionObject *> EOs;
107 for (unsigned int i = 0; i < E.GetNumExecutionObjects(); i++)
108 EOs.push_back(E[i]);
110 int num_eos = EOs.size();
112 // Allocate input and output buffers for each execution object
113 for (auto eo : EOs)
114 {
115 size_t in_size = eo->GetInputBufferSizeInBytes();
116 size_t out_size = eo->GetOutputBufferSizeInBytes();
117 ArgInfo in = { ArgInfo(malloc(in_size), in_size)};
118 ArgInfo out = { ArgInfo(malloc(out_size), out_size)};
119 eo->SetInputOutputBuffer(in, out);
120 }
122 // Process frames with available EOs in a pipelined manner
123 // additional num_eos iterations to flush the pipeline (epilogue)
124 for (int frame_idx = 0; frame_idx < c.numFrames + num_eos; frame_idx++)
125 {
126 ExecutionObject* eo = EOs[frame_idx % num_eos];
128 // Wait for previous frame on the same eo to finish processing
129 if (eo->ProcessFrameWait())
130 ProcessTrace(eo, c);
132 // Read a frame and start processing it with current eo
133 if (ReadFrame(eo, frame_idx, c, input))
134 eo->ProcessFrameStartAsync();
135 }
137 for (auto eo : EOs)
138 {
139 free(eo->GetInputBufferPtr());
140 free(eo->GetOutputBufferPtr());
141 }
142 }
143 catch (tidl::Exception &e)
144 {
145 std::cerr << e.what() << std::endl;
146 status = false;
147 }
149 input.close();
151 return status;
152 }
155 // APIs for accessing output buffers from individual layers
156 // 1. ExecutionObject::WriteLayerOutputsToFile
157 // 2. ExecutionObject::GetOutputsFromAllLayers
158 // 3. ExecutionObject::GetOutputFromLayer
159 void ProcessTrace(const ExecutionObject* eo, const Configuration& c)
160 {
161 if (!c.enableOutputTrace)
162 {
163 std::cout << "Trace is not enabled. Set"
164 " Configuration::enableOutputTrace to true"
165 << std::endl;
166 return;
167 }
169 // 1. Write the outputs from each layer to files
170 // filename: trace_data_<layer_index>_<channels>_<width>_<height>.bin
171 eo->WriteLayerOutputsToFile();
173 // 2. Get all outputs from all layers and iterate through them
174 const LayerOutputs* los = eo->GetOutputsFromAllLayers();
175 if (!los) return;
177 for (const std::unique_ptr<const LayerOutput> &lo : *los)
178 {
179 std::cout << "Layer index: " << lo->LayerIndex()
180 << " Shape: " << lo->NumberOfChannels() << " x "
181 << lo->Width() << " x " << lo->Height()
182 << " Data ptr: " << static_cast<const void*>(lo->Data())
183 << " Size in bytes: " << lo->Size()
184 << std::endl;
185 }
187 // Call delete to free the memory used to store layer outputs
188 delete los;
190 // 3. Get the output from a single layer
191 const LayerOutput* lo = eo->GetOutputFromLayer(1);
192 if (!lo) return;
194 std::cout << "Layer index: " << lo->LayerIndex()
195 << " Shape: " << lo->NumberOfChannels() << " x "
196 << lo->Width() << " x " << lo->Height()
197 << " Data ptr: " << static_cast<const void*>(lo->Data())
198 << " Size in bytes: " << lo->Size()
199 << std::endl;
201 delete lo;
202 }