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 <boost/format.hpp>
30 #include <cstring>
32 #include "utils.h"
34 using namespace tidl;
36 using boost::format;
37 using std::string;
38 using std::istream;
39 using std::ostream;
40 using std::vector;
42 static bool read_frame_helper(char* ptr, size_t size, istream& input_file);
44 bool ReadFrame(ExecutionObject* eo,
45 int frame_idx,
46 const Configuration& configuration,
47 std::istream& input_file)
48 {
49 if (frame_idx >= configuration.numFrames)
50 return false;
52 // Note: Frame index is used by the EO for debug messages only
53 eo->SetFrameIndex(frame_idx);
55 return read_frame_helper(eo->GetInputBufferPtr(),
56 eo->GetInputBufferSizeInBytes(),
57 input_file);
58 }
60 bool ReadFrame(ExecutionObjectPipeline* eop,
61 int frame_idx,
62 const Configuration& configuration,
63 std::istream& input_file)
64 {
65 if (frame_idx >= configuration.numFrames)
66 return false;
68 // Note: Frame index is used by the EOP for debug messages only
69 eop->SetFrameIndex(frame_idx);
71 return read_frame_helper(eop->GetInputBufferPtr(),
72 eop->GetInputBufferSizeInBytes(),
73 input_file);
74 }
76 bool read_frame_helper(char* ptr, size_t size, istream& input_file)
77 {
78 assert (ptr != nullptr);
79 assert (input_file.good());
81 input_file.read(ptr, size);
82 assert (input_file.good());
84 if (input_file.eof())
85 return false;
87 // Wrap-around : if EOF is reached, start reading from the beginning.
88 if (input_file.peek() == EOF)
89 input_file.seekg(0, input_file.beg);
91 if (input_file.good())
92 return true;
94 return false;
95 }
98 bool WriteFrame(const ExecutionObject* eo, ostream& output_file)
99 {
100 output_file.write(eo->GetOutputBufferPtr(),
101 eo->GetOutputBufferSizeInBytes());
102 assert(output_file.good() == true);
104 if (output_file.good())
105 return true;
107 return false;
108 }
110 void ReportTime(const ExecutionObject* eo)
111 {
112 double elapsed_host = eo->GetHostProcessTimeInMilliSeconds();
113 double elapsed_device = eo->GetProcessTimeInMilliSeconds();
114 double overhead = 100 - (elapsed_device/elapsed_host*100);
116 std::cout << format("frame[%3d]: Time on %s: %4.2f ms, host: %4.2f ms"
117 " API overhead: %2.2f %%\n")
118 % eo->GetFrameIndex() % eo->GetDeviceName()
119 % elapsed_device % elapsed_host % overhead;
120 }
122 void ReportTime(const ExecutionObjectPipeline* eop)
123 {
124 double elapsed_host = eop->GetHostProcessTimeInMilliSeconds();
125 double elapsed_device = eop->GetProcessTimeInMilliSeconds();
126 double overhead = 100 - (elapsed_device/elapsed_host*100);
128 std::cout << format("frame[%3d]: Time on %s: %4.2f ms, host: %4.2f ms"
129 " API overhead: %2.2f %%\n")
130 % eop->GetFrameIndex() % eop->GetDeviceName()
131 % elapsed_device % elapsed_host % overhead;
132 }
134 // Compare output against reference output
135 bool CheckFrame(const ExecutionObject *eo, const char *ref_output)
136 {
137 if (std::memcmp(static_cast<const void*>(ref_output),
138 static_cast<const void*>(eo->GetOutputBufferPtr()),
139 eo->GetOutputBufferSizeInBytes()) == 0)
140 return true;
142 return false;
143 }
145 bool CheckFrame(const ExecutionObjectPipeline *eop, const char *ref_output)
146 {
147 if (std::memcmp(static_cast<const void*>(ref_output),
148 static_cast<const void*>(eop->GetOutputBufferPtr()),
149 eop->GetOutputBufferSizeInBytes()) == 0)
150 return true;
152 return false;
153 }
156 namespace tidl {
157 std::size_t GetBinaryFileSize (const std::string &F);
158 bool ReadBinary (const std::string &F, char* buffer, int size);
159 }
161 // Read file into a buffer.
162 const char* ReadReferenceOutput(const string& name)
163 {
164 size_t size = GetBinaryFileSize(name);
166 if (size == 0)
167 return nullptr;
169 char* buffer = new char[size];
171 if (!buffer)
172 return nullptr;
174 if (!ReadBinary(name, buffer, size))
175 {
176 delete [] buffer;
177 return nullptr;
178 }
180 return buffer;
181 }
183 // Allocate input and output memory for each EO
184 void AllocateMemory(const vector<ExecutionObject *>& eos)
185 {
186 // Allocate input and output buffers for each execution object
187 for (auto eo : eos)
188 {
189 size_t in_size = eo->GetInputBufferSizeInBytes();
190 size_t out_size = eo->GetOutputBufferSizeInBytes();
191 void* in_ptr = malloc(in_size);
192 void* out_ptr = malloc(out_size);
193 assert(in_ptr != nullptr && out_ptr != nullptr);
195 ArgInfo in = { ArgInfo(in_ptr, in_size)};
196 ArgInfo out = { ArgInfo(out_ptr, out_size)};
197 eo->SetInputOutputBuffer(in, out);
198 }
199 }
201 // Free the input and output memory associated with each EO
202 void FreeMemory(const vector<ExecutionObject *>& eos)
203 {
204 for (auto eo : eos)
205 {
206 free(eo->GetInputBufferPtr());
207 free(eo->GetOutputBufferPtr());
208 }
209 }
211 // Allocate input and output memory for each EOP
212 void AllocateMemory(const vector<ExecutionObjectPipeline *>& eops)
213 {
214 // Allocate input and output buffers for each execution object
215 for (auto eop : eops)
216 {
217 size_t in_size = eop->GetInputBufferSizeInBytes();
218 size_t out_size = eop->GetOutputBufferSizeInBytes();
219 void* in_ptr = malloc(in_size);
220 void* out_ptr = malloc(out_size);
221 assert(in_ptr != nullptr && out_ptr != nullptr);
223 ArgInfo in = { ArgInfo(in_ptr, in_size)};
224 ArgInfo out = { ArgInfo(out_ptr, out_size)};
225 eop->SetInputOutputBuffer(in, out);
226 }
227 }
229 // Free the input and output memory associated with each EOP
230 void FreeMemory(const vector<ExecutionObjectPipeline *>& eops)
231 {
232 for (auto eop : eops)
233 {
234 free(eop->GetInputBufferPtr());
235 free(eop->GetOutputBufferPtr());
236 }
237 }