examples: Add layers group command line parameter
[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 <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;
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)
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;