NVIDIA NvNeural SDK  2022.2
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 inline std::string generateTypeString(TensorDataType data)
188 {
189  switch (data)
190  {
191  case TensorDataType::TestOnly:
192  return "nvneural::TensorDataType::TestOnly";
193  case TensorDataType::Float:
194  return "nvneural::TensorDataType::Float";
195  case TensorDataType::Half:
196  return "nvneural::TensorDataType::Half";
197  case TensorDataType::CompressedPng:
198  return "nvneural::TensorDataType::CompressedPng";
199  case TensorDataType::UncompressedRgb:
200  return "nvneural::TensorDataType::UncompressedRgb";
201  default:
202  break;
203  }
204 
205  return "unrecognizable type";
206 }
207 
208 inline std::string generateTypeString(TensorDataLayout layout)
209 {
210  switch (layout)
211  {
212  case TensorDataLayout::TestOnly:
213  return "nvneural::TensorDataLayout::TestOnly";
214  case TensorDataLayout::Nchw:
215  return "nvneural::TensorDataLayout::Nchw";
216  case TensorDataLayout::Nhwc:
217  return "nvneural::TensorDataLayout::Nhwc";
218 
219  default:
220  break;
221  }
222 
223  return "unrecognizable layout";
224 }
225 
226 inline std::string generateTypeString(NetworkBackendId backend)
227 {
228  switch (backend)
229  {
230  case NetworkBackendId::TestOnly:
231  return "nvneural::NetworkBackendId::TestOnly";
232  case NetworkBackendId::Cpu:
233  return "nvneural::NetworkBackendId::Cpu";
234  case NetworkBackendId::Cuda:
235  return "nvneural::NetworkBackendId::Cuda";
236 
237  default:
238  break;
239  }
240 
241  return "unrecognizable backend";
242 }
243 
244 inline std::string floatToStr(float n)
245 {
246  std::string s = std::to_string(n);
247  if (s.find('.') == std::string::npos) // Did not find decimal point
248  {
249  s += ".";
250  }
251  s += "f";
252  return s;
253 }
254 
255 inline char toHex(int val)
256 {
257  if(val<10) return '0'+val;
258  return 'A'+val-10;
259 }
260 
261 inline std::string toCppString(std::string str)
262 {
263  std::string rv;
264  for(size_t i=0;i<str.size();i++)
265  {
266  if(i+1 < str.size() && ((str[i]=='\n' && str[i+1]=='\r') || (str[i]=='\r' && str[i+1]=='\n')))
267  {
268  rv+="\\n";
269  i++;
270  }
271  else if(str[i]=='\r' || str[i]=='\n')
272  {
273  rv+="\\n";
274  }
275  else if(str[i]=='\"')
276  {
277  rv+="\\\"";
278  }
279  else if(str[i]=='\\')
280  {
281  rv+="\\\\";
282  }
283  else if(str[i]<0x20 && str[i]!='\t')
284  {
285  rv+="\\x";
286  rv.push_back(toHex((str[i]>>4)&0xf));
287  rv.push_back(toHex(str[i]&0xf));
288  }
289  else
290  {
291  rv.push_back(str[i]);
292  }
293  }
294  return rv;
295 }
296 
297 inline std::vector<std::string> toCppStringLines(std::string str)
298 {
299  std::vector<std::string> lines;
300  std::string temp;
301 
302  for(size_t i=0;i<str.size();i++)
303  {
304  if(i+1 < str.size() && ((str[i]=='\n' && str[i+1]=='\r') || (str[i]=='\r' && str[i+1]=='\n')))
305  {
306  i++;
307  }
308  temp.push_back(str[i]);
309  if(str[i]=='\r' || str[i]=='\n')
310  {
311  lines.push_back(toCppString(temp));
312  temp.clear();
313  }
314  }
315 
316  lines.push_back(toCppString(temp));
317 
318  return lines;
319 }
320 }} // namespace nvneural::<anon>
321 
322 #endif // NVNEURAL_CODEGENHELPERS_H
Definitions of C++ code generation interfaces exported by tools and plugins.