Update TIDL network data structure
[tidl/tidl-api.git] / tidl_api / src / util.cpp
1 /******************************************************************************
2  * Copyright (c) 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 #include "util.h"
30 #include <iostream>
31 #include <fstream>
32 #include <assert.h>
33 #include <chrono>
34 #include <mutex>
35 #include <cstring>
36 #include <memory>
38 namespace tidl {
39 bool EnableTimeStamps(const std::string& file, size_t num_frames);
40 }
42 using namespace tidl;
44 using namespace std::chrono;
46 std::unique_ptr<TimeStamp> tidl_api_timestamps(nullptr);
48 bool tidl::EnableTimeStamps(const std::string& file, size_t num_frames)
49 {
50     std::mutex m;
51     std::lock_guard<std::mutex> guard(m);
53     if (tidl_api_timestamps.get() != nullptr)
54         return true;
56     tidl_api_timestamps.reset(new TimeStamp(file, num_frames));
57     if (tidl_api_timestamps.get() == nullptr)
58         return false;
60     return true;
61 }
63 TimeStamp::TimeStamp(const std::string& file, int num_entries):
64                         num_entries_m(num_entries), file_m(file)
65 {
66     entries_m = new Entry[num_entries_m];
67     if (entries_m)
68         std::memset(entries_m, 0, sizeof(Entry)*num_entries_m);
69 }
71 void TimeStamp::Update(int frame_idx, EventKind k, int type, int id)
72 {
73     if (!entries_m)
74         return;
76     int idx = frame_idx % num_entries_m;
78     entries_m[idx].frame_idx = frame_idx;
79     entries_m[idx].timestamp[k] = duration_cast<microseconds>
80                  (high_resolution_clock::now().time_since_epoch()).count();
82     if (k == EO1_PFSA_START)
83     {
84         entries_m[idx].eo1_id   = id;
85         entries_m[idx].eo1_type = type;
86     }
87     else if (k == EO2_PFSA_START)
88     {
89         entries_m[idx].eo2_id   = id;
90         entries_m[idx].eo2_type = type;
91     }
92 }
94 void TimeStamp::Zero(int frame_idx, EventKind k)
95 {
96     if (!entries_m)
97         return;
99     int idx = frame_idx % num_entries_m;
101     entries_m[idx].frame_idx    = frame_idx;
102     entries_m[idx].timestamp[k] = 0;
106 TimeStamp::~TimeStamp()
108     if (!entries_m)
109         return;
111     std::ofstream ofs;
112     ofs.open(file_m, std::ofstream::out);
114     for (int i=0; i < num_entries_m; i++)
115         for (int j=0; j < EventKind::NUM_EVENTS; j++)
116             if (entries_m[i].timestamp[j] != 0)
117             {
118                 ofs << entries_m[i].frame_idx << ",";
119                 switch (j)
120                 {
121                     case EOP_PFSA_START: ofs << "EOP:PFSA:Start"; break;
122                     case EOP_PFSA_END:   ofs << "EOP:PFSA:End"; break;
123                     case EOP_PFW_START:  ofs << "EOP:PFW:Start"; break;
124                     case EOP_PFW_END:    ofs << "EOP:PFW:End"; break;
125                     case EOP_RAN_START:  ofs << "EOP:RAN:Start"; break;
126                     case EOP_RAN_END:    ofs << "EOP:RAN:End"; break;
128                     case EO1_PFSA_START: ofs << "EO1:PFSA:Start"; break;
129                     case EO1_PFSA_END:   ofs << "EO1:PFSA:End"; break;
130                     case EO1_PFW_START:  ofs << "EO1:PFW:Start"; break;
131                     case EO1_PFW_END:    ofs << "EO1:PFW:End"; break;
133                     case EO2_PFSA_START: ofs << "EO2:PFSA:Start"; break;
134                     case EO2_PFSA_END:   ofs << "EO2:PFSA:End"; break;
135                     case EO2_PFW_START:  ofs << "EO2:PFW:Start"; break;
136                     case EO2_PFW_END:    ofs << "EO2:PFW:End"; break;
138                     default:             ofs << "UNKNOWN"; break;
139                 }
140                 ofs << "," << entries_m[i].timestamp[j];
142                 if (j == EO1_PFSA_START)
143                 {
144                     ofs << "," << entries_m[i].eo1_type
145                         << "," << entries_m[i].eo1_id;
146                 }
147                 else if (j == EO2_PFSA_START)
148                 {
149                     ofs << "," << entries_m[i].eo2_type
150                         << "," << entries_m[i].eo2_id;
151                 }
154                 ofs << std::endl;
155             }
157     ofs.close();
158     delete [] entries_m;
162 void tidl::RecordEvent(int frame_idx, TimeStamp::EventKind k,
163                        int eo_type, int eo_id)
165     TimeStamp* t = tidl_api_timestamps.get();
166     if (t)
167         t->Update(frame_idx, k, eo_type, eo_id);
170 void tidl::ResetEvent(int frame_idx, TimeStamp::EventKind k)
172     TimeStamp* t = tidl_api_timestamps.get();
173     if (t)
174         t->Zero(frame_idx, k);
177 std::size_t tidl::GetBinaryFileSize(const std::string &F)
179     std::ifstream is;
180     is.open (F, std::ios::binary );
182     if (!is.good())
183     {
184         std::cout << "ERROR: File read failed for " << F << std::endl;
185         return 0;
186     }
188     is.seekg (0, std::ios::end);
189     size_t length = is.tellg();
190     is.close();
192     return length;
196 bool tidl::ReadBinary(const std::string &F, char* buffer, int size)
198     std::ifstream is;
199     is.open (F, std::ios::binary );
201     if (!is.good())
202     {
203         std::cout << "ERROR: File read failed for " << F << std::endl;
204         return false;
205     }
207     is.seekg (0, std::ios::end);
208     int length = is.tellg();
210     if (length != size)
211     {
212         std::cout << length << " != " << size << std::endl;
213         is.close();
214         return false;
215     }
217     is.seekg (0, std::ios::beg);
218     is.read (buffer, length);
219     is.close();
221     return true;
224 bool tidl::ReadNetworkBinary(const std::string &F, char *buffer)
226     std::size_t fsize = GetBinaryFileSize(F);
228     /* Read binary network format in the latest TIDL-API (1.3.x or later) */
229     if (fsize == sizeof(sTIDL_Network_t))
230         return ReadBinary(F, buffer, fsize);
232     /* Read binary network format in TIDL-API 1.2.x or earlier */
233     if (fsize == sizeof(sTIDL_1_2_Network_t))
234     {
235        sTIDL_1_2_Network_t *tmp = new sTIDL_1_2_Network_t;
236        if (tmp == nullptr)  return false;
237        if (! ReadBinary(F, (char *) tmp, fsize)) return false;
238        ConvertFromNetwork_1_2((sTIDL_Network_t *) buffer, tmp);
239        delete tmp;
240        return true;
241     }
243     std::cout << "ERROR: Wrong network binary size: " << fsize << std::endl;
244     return false;
247 void tidl::ConvertFromNetwork_1_2(sTIDL_Network_t *new_net,
248                                   sTIDL_1_2_Network_t *old_net)
250     memcpy(new_net, old_net, 7 * sizeof(int32_t));  /* first 7 common fields */
251     int32_t strideOffsetMethod = old_net->strideOffsetMethod;
252     new_net->reserved          = old_net->reserved;
254     for (int i = 0; i < TIDL_NUM_MAX_LAYERS; i++)
255     {
256         memcpy(& new_net->TIDLLayers[i], & old_net->TIDLLayers[i],
257                sizeof(sTIDL_1_2_Layer_t));
258         new_net->TIDLLayers[i].strideOffsetMethod = strideOffsetMethod;
259     }
262 bool tidl::CompareFiles(const std::string &F1, const std::string &F2)
264     std::size_t s1 = GetBinaryFileSize(F1);
265     std::size_t s2 = GetBinaryFileSize(F2);
267     if (s1 != s2)
268         return false;
270     char *b1 = new char[s1];
271     char *b2 = new char[s2];
273     ReadBinary(F1, b1, s1);
274     ReadBinary(F2, b2, s2);
276     int errors = 0;
277     for (size_t i=0; i < s1; i++)
278         if (b1[i] != b2[i])
279         {
280             if (errors++ < 10)
281                 std::cout << "Error at " << i << " " <<
282                              (int)b1[i] << " != " << (int)b2[i] << std::endl;
283         }
285     delete[] b1;
286     delete[] b2;
288     if (errors == 0) return true;
290     std::cout << "Total " << errors << " errors out of " << s1 << std::endl;
291     return false;
294 bool tidl::CompareFrames(const std::string &F1, const std::string &F2,
295                          int numFrames, int width, int height)
297     bool status = true;
299     std::size_t s1 = GetBinaryFileSize(F1);
300     std::size_t s2 = GetBinaryFileSize(F2);
302     char *b1 = new char[s1];
303     char *b2 = new char[s2];
305     ReadBinary(F1, b1, s1);
306     ReadBinary(F2, b2, s2);
308     for (int f=0; f < numFrames; f++)
309     {
310         int errors = 0;
311         int frame_offset = f*width*height;
312         std::cout << "Comparing frame: " << f << std::endl;
313         for (int h=0; h < height; h++)
314         {
315             for (int w=0; w < width; w++)
316             {
317                 size_t index = frame_offset+(h*width)+w;
318                 assert (index < s1 && index < s2);
319                 if (b1[index] != b2[index])
320                 {
321                     status = false;
322                     if (errors++ < 10)
323                         std::cout << "Error at " << index << " " <<
324                                      (int)b1[index] << " != " << (int)b2[index]
325                                   << std::endl;
326                 }
327             }
328         }
329         if (errors > 0)
330             std::cout << "Total " << errors << " errors out of " <<
331                          height * width << std::endl;
332     }
334     delete[] b1;
335     delete[] b2;
337     return status;