NVIDIA NvNeural SDK  2021.1
GPU inference framework for NVIDIA Nsight Deep Learning Designer
CodeGenHelpers.h
Go to the documentation of this file.
1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2020-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 
25 #ifndef NVNEURAL_CODEGENHELPERS_H
26 #define NVNEURAL_CODEGENHELPERS_H
27 
28 #include <iosfwd>
29 #include <sstream>
30 #include <string>
31 #include <nvneural/CodeGenTypes.h>
32 
33 namespace nvneural { namespace {
34 
45 class SourceWriter
46 {
47 public:
48  SourceWriter() = default;
49  ~SourceWriter() = default;
50 
51  std::string str() const
52  {
53  return m_output;
54  }
55 
56  void pushIndent(const std::string& indent)
57  {
58  m_indents.push_back(indent);
59  }
60 
61  void popIndent()
62  {
63  m_indents.pop_back();
64  }
65 
66  void writeFragment(const std::string& fragment)
67  {
68  std::string indentPrefix;
69  for (const std::string& indent : m_indents)
70  {
71  indentPrefix += indent;
72  }
73  indentFragment(indentPrefix, fragment);
74  }
75 
76  class Line
77  {
78  friend class SourceWriter;
79  public:
80  ~Line()
81  {
82  m_owner.writeFragment(m_stream.str());
83  }
84 
85  template<typename TObject>
86  Line& operator<<(TObject obj)
87  {
88  m_stream << obj;
89  return *this;
90  }
91  private:
92  explicit Line(SourceWriter& owner)
93  : m_owner(owner)
94  {
95  }
96  Line(const Line& copyFrom)
97  : m_owner(copyFrom.m_owner)
98  , m_stream()
99  {
100  // Not a true copy because ostringstream is noncopyable,
101  // But C++14 builds need to do a single copy when the
102  // SourceWriter::write() function returns. In this case,
103  // we know that the stream hasn't been used yet so we'll
104  // default-construct it instead.
105  }
106 
107  SourceWriter& m_owner;
108  std::ostringstream m_stream;
109  };
110 
111  Line write()
112  {
113  return Line{*this};
114  }
115 
116  class ScopedIndent
117  {
118  friend class SourceWriter;
119  public:
120  ~ScopedIndent()
121  {
122  m_owner.popIndent();
123  }
124  private:
125  explicit ScopedIndent(SourceWriter& owner)
126  : m_owner(owner)
127  {
128  m_owner.pushIndent(" ");
129  }
130  SourceWriter& m_owner;
131  };
132 
133  ScopedIndent indent()
134  {
135  return ScopedIndent(*this);
136  }
137 
138  class ScopedBraceBlock
139  {
140  friend class SourceWriter;
141  public:
142  ~ScopedBraceBlock()
143  {
144  m_owner.popIndent();
145  m_owner.writeFragment("}" + m_suffix);
146  }
147  private:
148  ScopedBraceBlock(SourceWriter& owner, const std::string& suffix)
149  : m_owner(owner)
150  , m_suffix(suffix)
151  {
152  m_owner.writeFragment("{");
153  m_owner.pushIndent(" ");
154  }
155  SourceWriter& m_owner;
156  std::string m_suffix;
157  };
158 
159  ScopedBraceBlock brace(const std::string& suffix = "")
160  {
161  return ScopedBraceBlock(*this, suffix);
162  }
163 
164 private:
165  std::string m_output;
166  std::vector<std::string> m_indents;
167 
168  void indentFragment(const std::string& indent, const std::string& fragment)
169  {
170  std::string::size_type lineBegin = 0;
171  std::string::size_type lineEnd;
172  do
173  {
174  lineEnd = fragment.find('\n', lineBegin);
175  const std::string line = fragment.substr(lineBegin, lineEnd - lineBegin);
176  if (line.size())
177  {
178  m_output += indent;
179  m_output += line;
180  }
181  m_output += "\n";
182  lineBegin = lineEnd + 1;
183  } while (lineEnd != std::string::npos);
184  }
185 };
186 
187 std::string generateTypeString(TensorDataType data)
188 {
189  switch (data)
190  {
191  case TensorDataType::Float:
192  return "nvneural::TensorDataType::Float";
193  case TensorDataType::Half:
194  return "nvneural::TensorDataType::Half";
195  case TensorDataType::CompressedPng:
196  return "nvneural::TensorDataType::CompressedPng";
197  default:
198  break;
199  }
200 
201  return "unrecognizable type";
202 }
203 
204 std::string generateTypeString(TensorDataLayout layout)
205 {
206  switch (layout)
207  {
208  case TensorDataLayout::TestOnly:
209  return "nvneural::TensorDataLayout::TestOnly";
210  case TensorDataLayout::Nchw:
211  return "nvneural::TensorDataLayout::Nchw";
212  case TensorDataLayout::Nhwc:
213  return "nvneural::TensorDataLayout::Nhwc";
214 
215  default:
216  break;
217  }
218 
219  return "unrecognizable layout";
220 }
221 
222 std::string generateTypeString(NetworkBackendId backend)
223 {
224  switch (backend)
225  {
226  case NetworkBackendId::TestOnly:
227  return "nvneural::NetworkBackendId::TestOnly";
228  case NetworkBackendId::Cpu:
229  return "nvneural::NetworkBackendId::Cpu";
230  case NetworkBackendId::Cuda:
231  return "nvneural::NetworkBackendId::Cuda";
232 
233  default:
234  break;
235  }
236 
237  return "unrecognizable backend";
238 }
239 
240 std::string floatToStr(float n)
241 {
242  std::string s = std::to_string(n);
243  if (s.find('.') == std::string::npos) // Did not find decimal point
244  {
245  s += ".";
246  }
247  s += "f";
248  return s;
249 }
250 
251 char toHex(int val)
252 {
253  if(val<10) return '0'+val;
254  return 'A'+val-10;
255 }
256 
257 std::string toCppString(std::string str)
258 {
259  std::string rv;
260  for(size_t i=0;i<str.size();i++)
261  {
262  if(i+1 < str.size() && ((str[i]=='\n' && str[i+1]=='\r') || (str[i]=='\r' && str[i+1]=='\n')))
263  {
264  rv+="\\n";
265  i++;
266  }
267  else if(str[i]=='\r' || str[i]=='\n')
268  {
269  rv+="\\n";
270  }
271  else if(str[i]=='\"')
272  {
273  rv+="\\\"";
274  }
275  else if(str[i]=='\\')
276  {
277  rv+="\\\\";
278  }
279  else if(str[i]<0x20 && str[i]!='\t')
280  {
281  rv+="\\x";
282  rv.push_back(toHex((str[i]>>4)&0xf));
283  rv.push_back(toHex(str[i]&0xf));
284  }
285  else
286  {
287  rv.push_back(str[i]);
288  }
289  }
290  return rv;
291 }
292 std::vector<std::string> toCppStringLines(std::string str)
293 {
294  std::vector<std::string> lines;
295  std::string temp;
296 
297  for(size_t i=0;i<str.size();i++)
298  {
299  if(i+1 < str.size() && ((str[i]=='\n' && str[i+1]=='\r') || (str[i]=='\r' && str[i+1]=='\n')))
300  {
301  i++;
302  }
303  temp.push_back(str[i]);
304  if(str[i]=='\r' || str[i]=='\n')
305  {
306  lines.push_back(toCppString(temp));
307  temp.clear();
308  }
309  }
310 
311  lines.push_back(toCppString(temp));
312 
313  return lines;
314 }
315 }} // namespace nvneural::<anon>
316 
317 #endif // NVNEURAL_CODEGENHELPERS_H
Definitions of C++ code generation interfaces exported by tools and plugins.