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>
37 #include "executor.h"
39 using namespace tidl;
41 using namespace std::chrono;
43 std::unique_ptr<TimeStamp> tidl_api_timestamps(nullptr);
45 bool tidl::EnableTimeStamps(const std::string& file, size_t num_frames)
46 {
47 std::mutex m;
48 std::lock_guard<std::mutex> guard(m);
50 if (tidl_api_timestamps.get() != nullptr)
51 return true;
53 tidl_api_timestamps.reset(new TimeStamp(file, num_frames));
54 if (tidl_api_timestamps.get() == nullptr)
55 return false;
57 return true;
58 }
60 TimeStamp::TimeStamp(const std::string& file, int num_entries):
61 num_entries_m(num_entries), file_m(file)
62 {
63 entries_m = new Entry[num_entries_m];
64 std::memset(entries_m, 0, sizeof(Entry)*num_entries_m);
65 }
67 void TimeStamp::Update(int frame_idx, EventKind k, int type, int id)
68 {
69 int idx = frame_idx % num_entries_m;
71 entries_m[idx].frame_idx = frame_idx;
72 entries_m[idx].timestamp[k] = duration_cast<microseconds>
73 (high_resolution_clock::now().time_since_epoch()).count();
75 if (k == EO1_PFSA_START)
76 {
77 entries_m[idx].eo1_id = id;
78 entries_m[idx].eo1_type = type;
79 }
80 else if (k == EO2_PFSA_START)
81 {
82 entries_m[idx].eo2_id = id;
83 entries_m[idx].eo2_type = type;
84 }
86 }
88 void TimeStamp::Zero(int frame_idx, EventKind k)
89 {
90 int idx = frame_idx % num_entries_m;
92 entries_m[idx].frame_idx = frame_idx;
93 entries_m[idx].timestamp[k] = 0;
94 }
97 TimeStamp::~TimeStamp()
98 {
99 std::ofstream ofs;
100 ofs.open(file_m, std::ofstream::out);
102 for (int i=0; i < num_entries_m; i++)
103 for (int j=0; j < EventKind::NUM_EVENTS; j++)
104 if (entries_m[i].timestamp[j] != 0)
105 {
106 ofs << entries_m[i].frame_idx << ",";
107 switch (j)
108 {
109 case EOP_PFSA_START: ofs << "EOP:PFSA:Start"; break;
110 case EOP_PFSA_END: ofs << "EOP:PFSA:End"; break;
111 case EOP_PFW_START: ofs << "EOP:PFW:Start"; break;
112 case EOP_PFW_END: ofs << "EOP:PFW:End"; break;
113 case EOP_RAN_START: ofs << "EOP:RAN:Start"; break;
114 case EOP_RAN_END: ofs << "EOP:RAN:End"; break;
116 case EO1_PFSA_START: ofs << "EO1:PFSA:Start"; break;
117 case EO1_PFSA_END: ofs << "EO1:PFSA:End"; break;
118 case EO1_PFW_START: ofs << "EO1:PFW:Start"; break;
119 case EO1_PFW_END: ofs << "EO1:PFW:End"; break;
121 case EO2_PFSA_START: ofs << "EO2:PFSA:Start"; break;
122 case EO2_PFSA_END: ofs << "EO2:PFSA:End"; break;
123 case EO2_PFW_START: ofs << "EO2:PFW:Start"; break;
124 case EO2_PFW_END: ofs << "EO2:PFW:End"; break;
126 default: ofs << "UNKNOWN"; break;
127 }
128 ofs << "," << entries_m[i].timestamp[j];
130 if (j == EO1_PFSA_START)
131 {
132 ofs << "," << entries_m[i].eo1_type
133 << "," << entries_m[i].eo1_id;
134 }
135 else if (j == EO2_PFSA_START)
136 {
137 ofs << "," << entries_m[i].eo2_type
138 << "," << entries_m[i].eo2_id;
139 }
142 ofs << std::endl;
143 }
145 ofs.close();
147 delete [] entries_m;
148 }
151 void tidl::RecordEvent(int frame_idx, TimeStamp::EventKind k,
152 int eo_type, int eo_id)
153 {
154 TimeStamp* t = tidl_api_timestamps.get();
155 if (t)
156 t->Update(frame_idx, k, eo_type, eo_id);
157 }
159 void tidl::ResetEvent(int frame_idx, TimeStamp::EventKind k)
160 {
161 TimeStamp* t = tidl_api_timestamps.get();
162 if (t)
163 t->Zero(frame_idx, k);
164 }
166 std::size_t tidl::GetBinaryFileSize(const std::string &F)
167 {
168 std::ifstream is;
169 is.open (F, std::ios::binary );
171 if (!is.good())
172 {
173 std::cout << "ERROR: File read failed for " << F << std::endl;
174 return 0;
175 }
177 is.seekg (0, std::ios::end);
178 size_t length = is.tellg();
179 is.close();
181 return length;
182 }
185 bool tidl::ReadBinary(const std::string &F, char* buffer, int size)
186 {
187 std::ifstream is;
188 is.open (F, std::ios::binary );
190 if (!is.good())
191 {
192 std::cout << "ERROR: File read failed for " << F << std::endl;
193 return false;
194 }
196 is.seekg (0, std::ios::end);
197 int length = is.tellg();
199 if (length != size)
200 {
201 std::cout << length << " != " << size << std::endl;
202 is.close();
203 return false;
204 }
206 is.seekg (0, std::ios::beg);
207 is.read (buffer, length);
208 is.close();
210 return true;
211 }
213 bool tidl::CompareFiles(const std::string &F1, const std::string &F2)
214 {
215 std::size_t s1 = GetBinaryFileSize(F1);
216 std::size_t s2 = GetBinaryFileSize(F2);
218 if (s1 != s2)
219 return false;
221 char *b1 = new char[s1];
222 char *b2 = new char[s2];
224 ReadBinary(F1, b1, s1);
225 ReadBinary(F2, b2, s2);
227 int errors = 0;
228 for (size_t i=0; i < s1; i++)
229 if (b1[i] != b2[i])
230 {
231 std::cout << "Error at " << i << " " <<
232 (int)b1[i] << " != " << (int)b2[i];
233 std::cout << std::endl;
234 errors++;
236 if (errors > 10)
237 break;
238 }
240 delete[] b1;
241 delete[] b2;
243 if (errors == 0) return true;
245 return false;
246 }
248 bool tidl::CompareFrames(const std::string &F1, const std::string &F2,
249 int numFrames, int width, int height)
250 {
251 bool status = true;
253 std::size_t s1 = GetBinaryFileSize(F1);
254 std::size_t s2 = GetBinaryFileSize(F2);
256 char *b1 = new char[s1];
257 char *b2 = new char[s2];
259 ReadBinary(F1, b1, s1);
260 ReadBinary(F2, b2, s2);
262 for (int f=0; f < numFrames; f++)
263 {
264 int errors = 0;
265 int frame_offset = f*width*height;
266 std::cout << "Comparing frame: " << f << std::endl;
267 for (int h=0; h < height; h++)
268 {
269 for (int w=0; w < width; w++)
270 {
271 size_t index = frame_offset+(h*width)+w;
272 assert (index < s1 && index < s2);
273 if (b1[index] != b2[index])
274 {
275 status = false;
276 std::cout << "Error at " << index << " " <<
277 (int)b1[index] << " != " << (int)b2[index];
278 std::cout << std::endl;
279 errors++;
281 }
282 if (errors > 10) break;
283 }
284 if (errors > 10) break;
285 }
286 }
288 delete[] b1;
289 delete[] b2;
291 return status;
292 }