4758d237222808da1dd8399dd3cf019f5d31a04f
[tidl/tidl-api.git] / examples / layer_output / main.cpp
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 <iomanip>
32 #include <fstream>
33 #include <cassert>
34 #include <string>
35 #include <functional>
36 #include <algorithm>
37 #include <time.h>
39 #include "executor.h"
40 #include "execution_object.h"
41 #include "configuration.h"
43 bool __TI_show_debug_ = false;
45 using namespace tidl;
47 bool RunConfiguration(const std::string& config_file, int num_devices,
48                       DeviceType device_type);
50 bool ReadFrame(ExecutionObject&     eo,
51                int                  frame_idx,
52                const Configuration& configuration,
53                std::istream&        input_file);
55 bool WriteFrame(const ExecutionObject &eo,
56                 std::ostream& output_file);
58 static void ProcessTrace(const ExecutionObject* eo, const Configuration& c);
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     std::cout << "API Version: " << Executor::GetAPIVersion() << std::endl;
68     // If there are no devices capable of offloading TIDL on the SoC, exit
69     uint32_t num_eve = Executor::GetNumDevices(DeviceType::EVE);
70     uint32_t num_dsp = Executor::GetNumDevices(DeviceType::DSP);
71     if (num_eve == 0 && num_dsp == 0)
72     {
73         std::cout << "TI DL not supported on this SoC." << std::endl;
74         return EXIT_SUCCESS;
75     }
77     // Configuration file with tracing enabled
78     std::string config_file = "j11_v2_trace.txt";
79     int         num_devices = 1;
80     DeviceType  device_type = num_eve > 0 ? DeviceType::EVE :
81                                             DeviceType::DSP;
83     bool status = RunConfiguration(config_file, num_devices, device_type);
85     if (!status)
86     {
87         std::cout << "tidl FAILED" << std::endl;
88         return EXIT_FAILURE;
89     }
91     std::cout << "tidl PASSED" << std::endl;
92     return EXIT_SUCCESS;
93 }
95 bool RunConfiguration(const std::string& config_file, int num_devices,
96                       DeviceType device_type)
97 {
98     DeviceIds ids;
99     for (int i = 0; i < num_devices; i++)
100         ids.insert(static_cast<DeviceId>(i));
102     // Read the TI DL configuration file
103     Configuration configuration;
104     bool status = configuration.ReadFromFile(config_file);
105     if (!status)
106     {
107         std::cerr << "Error in configuration file: " << config_file
108                   << std::endl;
109         return false;
110     }
112     // Open input files
113     std::ifstream input_data_file(configuration.inData, std::ios::binary);
114     assert (input_data_file.good());
116     try
117     {
118         // Create a executor with the approriate core type, number of cores
119         // and configuration specified
120         Executor executor(device_type, ids, configuration);
122         // Query Executor for set of ExecutionObjects created
123         const ExecutionObjects& execution_objects =
124                                                 executor.GetExecutionObjects();
125         int num_eos = execution_objects.size();
127         // Allocate input and output buffers for each execution object
128         std::vector<void *> buffers;
129         for (auto &eo : execution_objects)
130         {
131             size_t in_size  = eo->GetInputBufferSizeInBytes();
132             size_t out_size = eo->GetOutputBufferSizeInBytes();
133             ArgInfo in  = { ArgInfo(malloc(in_size),  in_size)};
134             ArgInfo out = { ArgInfo(malloc(out_size), out_size)};
135             eo->SetInputOutputBuffer(in, out);
137             buffers.push_back(in.ptr());
138             buffers.push_back(out.ptr());
139         }
141         // Process frames across execution objects in a pipelined manner
142         // additional num_eos iterations to flush the pipeline (epilogue)
143         for (int frame_idx = 0;
144              frame_idx < configuration.numFrames + num_eos; frame_idx++)
145         {
146             ExecutionObject* eo = execution_objects[frame_idx % num_eos].get();
148             // Wait for previous frame on the same eo to finish processing
149             if (eo->ProcessFrameWait())
150                 ProcessTrace(eo, configuration);
152             // Read a frame and start processing it with current eo
153             if (ReadFrame(*eo, frame_idx, configuration, input_data_file))
154                 eo->ProcessFrameStartAsync();
155         }
157         for (auto b : buffers)
158             free(b);
160     }
161     catch (tidl::Exception &e)
162     {
163         std::cerr << e.what() << std::endl;
164         status = false;
165     }
167     input_data_file.close();
169     return status;
173 // APIs for accessing output buffers from individual layers
174 // 1. ExecutionObject::WriteLayerOutputsToFile
175 // 2. ExecutionObject::GetOutputsFromAllLayers
176 // 3. ExecutionObject::GetOutputFromLayer
177 void ProcessTrace(const ExecutionObject* eo, const Configuration& c)
179     if (!c.enableOutputTrace)
180         return;
182     // 1. Write the outputs from each layer to files
183     // filename: trace_data_<layer_index>_<channels>_<width>_<height>.bin
184     eo->WriteLayerOutputsToFile();
186     // 2. Get all outputs from all layers and iterate through them
187     const LayerOutputs* los = eo->GetOutputsFromAllLayers();
189     for (const std::unique_ptr<const LayerOutput> &lo : *los)
190     {
191         std::cout << "Layer index: " << lo->LayerIndex()
192               << " Shape: " << lo->NumberOfChannels() << " x "
193               << lo->Width() << " x " << lo->Height()
194               << " Data ptr: " << static_cast<const void*>(lo->Data())
195               << " Size in bytes: " << lo->Size()
196               << std::endl;
197     }
199     // Call delete to free the memory used to store layer outputs
200     delete los;
202     // 3. Get the output from a single layer
203     const LayerOutput* lo = eo->GetOutputFromLayer(1);
205     if (lo)
206     {
207         std::cout << "Layer index: " << lo->LayerIndex()
208               << " Shape: " << lo->NumberOfChannels() << " x "
209               << lo->Width() << " x " << lo->Height()
210               << " Data ptr: " << static_cast<const void*>(lo->Data())
211               << " Size in bytes: " << lo->Size()
212               << std::endl;
214         delete lo;
215     }
219 bool ReadFrame(ExecutionObject &eo, int frame_idx,
220                const Configuration& configuration,
221                std::istream& input_file)
223     if (frame_idx >= configuration.numFrames)
224         return false;
226     char*  frame_buffer = eo.GetInputBufferPtr();
227     assert (frame_buffer != nullptr);
229     input_file.read(eo.GetInputBufferPtr(),
230                     eo.GetInputBufferSizeInBytes());
232     if (input_file.eof())
233         return false;
235     assert (input_file.good());
237     eo.SetFrameIndex(frame_idx);
239     if (input_file.good())
240         return true;
242     return false;