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;
103 }
106 TimeStamp::~TimeStamp()
107 {
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;
159 }
162 void tidl::RecordEvent(int frame_idx, TimeStamp::EventKind k,
163 int eo_type, int eo_id)
164 {
165 TimeStamp* t = tidl_api_timestamps.get();
166 if (t)
167 t->Update(frame_idx, k, eo_type, eo_id);
168 }
170 void tidl::ResetEvent(int frame_idx, TimeStamp::EventKind k)
171 {
172 TimeStamp* t = tidl_api_timestamps.get();
173 if (t)
174 t->Zero(frame_idx, k);
175 }
177 std::size_t tidl::GetBinaryFileSize(const std::string &F)
178 {
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;
193 }
196 bool tidl::ReadBinary(const std::string &F, char* buffer, int size)
197 {
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;
222 }
224 bool tidl::CompareFiles(const std::string &F1, const std::string &F2)
225 {
226 std::size_t s1 = GetBinaryFileSize(F1);
227 std::size_t s2 = GetBinaryFileSize(F2);
229 if (s1 != s2)
230 return false;
232 char *b1 = new char[s1];
233 char *b2 = new char[s2];
235 ReadBinary(F1, b1, s1);
236 ReadBinary(F2, b2, s2);
238 int errors = 0;
239 for (size_t i=0; i < s1; i++)
240 if (b1[i] != b2[i])
241 {
242 std::cout << "Error at " << i << " " <<
243 (int)b1[i] << " != " << (int)b2[i];
244 std::cout << std::endl;
245 errors++;
247 if (errors > 10)
248 break;
249 }
251 delete[] b1;
252 delete[] b2;
254 if (errors == 0) return true;
256 return false;
257 }
259 bool tidl::CompareFrames(const std::string &F1, const std::string &F2,
260 int numFrames, int width, int height)
261 {
262 bool status = true;
264 std::size_t s1 = GetBinaryFileSize(F1);
265 std::size_t s2 = GetBinaryFileSize(F2);
267 char *b1 = new char[s1];
268 char *b2 = new char[s2];
270 ReadBinary(F1, b1, s1);
271 ReadBinary(F2, b2, s2);
273 for (int f=0; f < numFrames; f++)
274 {
275 int errors = 0;
276 int frame_offset = f*width*height;
277 std::cout << "Comparing frame: " << f << std::endl;
278 for (int h=0; h < height; h++)
279 {
280 for (int w=0; w < width; w++)
281 {
282 size_t index = frame_offset+(h*width)+w;
283 assert (index < s1 && index < s2);
284 if (b1[index] != b2[index])
285 {
286 status = false;
287 std::cout << "Error at " << index << " " <<
288 (int)b1[index] << " != " << (int)b2[index];
289 std::cout << std::endl;
290 errors++;
292 }
293 if (errors > 10) break;
294 }
295 if (errors > 10) break;
296 }
297 }
299 delete[] b1;
300 delete[] b2;
302 return status;
303 }