43310c034f1596b0c028c1889c9e7c1cfb800e9f
[tidl/tidl-api.git] / examples / two_eo_per_frame_opt / 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  *****************************************************************************/
29 //
30 // This example illustrates using multiple EOs to process a single frame
31 // For details, refer http://downloads.ti.com/mctools/esd/docs/tidl-api/
32 //
33 #include <signal.h>
34 #include <iostream>
35 #include <fstream>
36 #include <cassert>
37 #include <string>
39 #include "executor.h"
40 #include "execution_object.h"
41 #include "execution_object_pipeline.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 using EOP = tidl::ExecutionObjectPipeline;
52 bool Run(int num_eve,int num_dsp, const char* ref_output);
54 int main(int argc, char *argv[])
55 {
56     // Catch ctrl-c to ensure a clean exit
57     signal(SIGABRT, exit);
58     signal(SIGTERM, exit);
60     // This example requires both EVE and C66x
61     uint32_t num_eve = Executor::GetNumDevices(DeviceType::EVE);
62     uint32_t num_dsp = Executor::GetNumDevices(DeviceType::DSP);
63     if (num_eve == 0 || num_dsp == 0)
64     {
65         std::cout << "TI DL not supported on this SoC." << std::endl;
66         return EXIT_SUCCESS;
67     }
69     string ref_file ="../test/testvecs/reference/j11_v2_ref.bin";
70     unique_ptr<const char> reference_output(ReadReferenceOutput(ref_file));
72     // Enable time stamp generation. The timestamp file is post processed
73     // by execution_graph.py to generate graphical view of frame execution.
74     // Refer to the User's Guide for details.
75     EnableTimeStamps("2eo_opt.log");
77     bool status = Run(num_eve, num_dsp, reference_output.get());
79     if (!status)
80     {
81         std::cout << "FAILED" << std::endl;
82         return EXIT_FAILURE;
83     }
85     std::cout << "PASSED" << std::endl;
86     return EXIT_SUCCESS;
87 }
89 bool Run(int num_eve, int num_dsp, const char* ref_output)
90 {
91     string config_file ="../test/testvecs/config/infer/tidl_config_j11_v2.txt";
93     Configuration c;
94     if (!c.ReadFromFile(config_file))
95         return false;
97     // Heap sizes for this network determined using Configuration::showHeapStats
98     c.PARAM_HEAP_SIZE   = (3 << 20); // 3MB
99     c.NETWORK_HEAP_SIZE = (20 << 20); // 20MB
101     // Run this example for 16 input frames
102     c.numFrames = 16;
104     // Assign layers 12, 13 and 14 to the DSP layer group
105     const int EVE_LG = 1;
106     const int DSP_LG = 2;
107     c.layerIndex2LayerGroupId = { {12, DSP_LG}, {13, DSP_LG}, {14, DSP_LG} };
109     // Open input file for reading
110     std::ifstream input(c.inData, std::ios::binary);
112     bool status = true;
113     try
114     {
115         // Create Executors - use all the DSP and EVE cores available
116         // Specify layer group id for each Executor
117         unique_ptr<Executor> eve(CreateExecutor(DeviceType::EVE,
118                                                 num_eve, c, EVE_LG));
119         unique_ptr<Executor> dsp(CreateExecutor(DeviceType::DSP,
120                                                 num_dsp, c, DSP_LG));
122         // On AM5749, create a total of 4 pipelines (EOPs):
123         // EOPs[0] : { EVE1, DSP1 }
124         // EOPs[1] : { EVE1, DSP1 } for double buffering
125         // EOPs[2] : { EVE2, DSP2 }
126         // EOPs[3] : { EVE2, DSP2 } for double buffering
128         const uint32_t pipeline_depth = 2;  // 2 EOs in EOP => depth 2
129         std::vector<EOP *> EOPs;
130         uint32_t num_pipe = std::max(num_eve, num_dsp);
131         for (uint32_t i = 0; i < num_pipe; i++)
132             for (uint32_t j = 0; j < pipeline_depth; j++)
133                 EOPs.push_back(new EOP( { (*eve)[i % num_eve],
134                                           (*dsp)[i % num_dsp] } ));
136         AllocateMemory(EOPs);
138         // Process frames with EOs in a pipelined manner
139         // additional num_eos iterations to flush the pipeline (epilogue)
140         int num_eops = EOPs.size();
141         for (int frame_idx = 0; frame_idx < c.numFrames + num_eops; frame_idx++)
142         {
143             EOP* eop = EOPs[frame_idx % num_eops];
145             // Wait for previous frame on the same EOP to finish processing
146             if (eop->ProcessFrameWait())
147             {
148                 // The reference output is valid only for the first frame
149                 // processed on each EOP
150                 if (frame_idx < num_eops && !CheckFrame(eop, ref_output))
151                     status = false;
152             }
154             // Read a frame and start processing it with current eo
155             if (ReadFrame(eop, frame_idx, c, input))
156                 eop->ProcessFrameStartAsync();
157         }
159         FreeMemory(EOPs);
161     }
162     catch (tidl::Exception &e)
163     {
164         std::cerr << e.what() << std::endl;
165         status = false;
166     }
168     input.close();
170     return status;