SST  8.0.0
StructuralSimulationToolkit
output.h
1 // Copyright 2009-2018 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2018, NTESS
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 
13 
14 #ifndef SST_CORE_OUTPUT_H
15 #define SST_CORE_OUTPUT_H
16 
17 #include <string.h>
18 
19 // UNCOMMENT OUT THIS LINE TO ENABLE THE DEBUG METHOD -OR_
20 // CHOOSE THE --enable-debug OPTION DURING SST CONFIGURATION
21 //#define __SST_DEBUG_OUTPUT__
22 
23 //This must be defined before inclusion of intttypes.h
24 #ifndef __STDC_FORMAT_MACROS
25 #define __STDC_FORMAT_MACROS
26 #endif
27 #include <cinttypes>
28 #include <cstdio>
29 #include <thread>
30 #include <unordered_map>
31 
32 #include <stdarg.h>
33 
34 #include <sst/core/rankInfo.h>
35 
36 extern int main(int argc, char **argv);
37 
38 namespace SST {
39 
40 // MACROS TO HELP BUILD THE CALLING FUNCTIONS INFORMATION
41 #define CALL_INFO __LINE__, __FILE__, __FUNCTION__
42 
43 #if defined(__GNUC__) || defined(__clang__)
44 #define CALL_INFO_LONG __LINE__, __FILE__, __PRETTY_FUNCTION__
45 #else
46 #define CALL_INFO_LONG __LINE__, __FILE__, __FUNCTION__
47 #endif
48 
49 /**
50  * Output object provides consistent method for outputting data to
51  * stdout, stderr and/or sst debug file. All components should
52  * use this class to log any information.
53  */
54 class Output
55 {
56 public:
57  /** Choice of output location
58  */
60  NONE, /*!< No output */
61  STDOUT, /*!< Print to stdout */
62  STDERR, /*!< Print to stderr */
63  FILE /*!< Print to a file */
64  };
65 
66  /** Constructor. Set up output configuration.
67  @param prefix Prefix to be prepended to all strings emitted by calls to
68  debug(), verbose(), fatal() and possibly output().
69  NOTE: No space will be inserted between the prepended prefix
70  string and the normal output string.
71  Prefix can contain the following escape codes:
72  - \@f Name of the file in which output call was made.
73  - \@l Line number in the file in which output call was made.
74  - \@p Name of the function from which output call was made.
75  - \@r MPI rank of the calling process. Will be empty if
76  MPI_COMM_WORLD size is 1.
77  - \@R MPI rank of the calling process. Will be 0 if
78  MPI_COMM_WORLD size is 1.
79  - \@i Thread Id of the calling process. Will be empty if
80  number of threads is 1.
81  - \@I Thread Id of the calling process. Will be 0 if
82  number of threads is 1.
83  - \@x Rank information of the calling process. Will be empty if
84  number of MPI ranks and number of threads are both 1
85  Same as [\@r:\@i]
86  - \@X Rank information of the calling process. Will be [0.0] if
87  number of MPI ranks and number of threads are both 1
88  Same as [\@R:\@I]
89  - \@t Simulation time. Will be the raw simulation cycle time
90  retrieved from the SST Core.
91  @param verbose_level Debugging output level. Calls to debug(),
92  verbose() and fatal() are only output if their output_level
93  parameter is less than or equal to the verbose_level currently
94  set for the object
95  @param verbose_mask Bitmask of allowed message types for debug(),
96  verbose() and fatal(). The Output object will only output the
97  message if the set bits of the output_bits parameter
98  are set in the verbose_mask of the object. It uses this logic:
99  if (~verbose_mask & output_bits == 0) then output is enabled.
100  @param location Output location. Output will be directed to STDOUT,
101  STDERR, FILE, or NONE. If FILE output is selected, the
102  output will be directed to the file defined by the
103  --debug runtime parameter, or to the file 'sst_output' if the
104  --debug parameter is not defined. If the size of MPI_COMM_WORLD
105  is > 1, then the rank process will be appended to the file name.
106  @param localoutputfilename. Send the output of this class to the
107  file identified in localoutputfilename instead of the of the
108  normal output file set by the run time parameter --debug-file.
109  location parameter must be set to FILE. This parameter is
110  intended for special case debug purposes only.
111  */
112  // CONSTRUCTION / DESTRUCTION
113  Output(const std::string& prefix, uint32_t verbose_level,
114  uint32_t verbose_mask, output_location_t location,
115  std::string localoutputfilename = "");
116 
117  /** Default Constructor. User must call init() to properly initialize obj.
118  Until init() is called, no output will occur.
119  */
120  Output(); // Default constructor
121 
122  virtual ~Output();
123 
124 
125  /** Initialize the object after construction
126  @param prefix Prefix to be prepended to all strings emitted by calls to
127  debug(), verbose(), fatal() and possibly output().
128  NOTE: No space will be inserted between the prepended prefix
129  string and the normal output string.
130  Prefix can contain the following escape codes:
131  - \@f Name of the file in which output call was made.
132  - \@l Line number in the file in which output call was made.
133  - \@p Name of the function from which output call was made.
134  - \@r MPI rank of the calling process. Will be empty if
135  MPI_COMM_WORLD size is 1.
136  - \@R MPI rank of the calling process. Will be 0 if
137  MPI_COMM_WORLD size is 1.
138  - \@i Thread Id of the calling process. Will be empty if
139  number of threads is 1.
140  - \@I Thread Id of the calling process. Will be 0 if
141  number of threads is 1.
142  - \@x Rank information of the calling process. Will be empty if
143  number of MPI ranks and number of threads are both 1
144  Same as [\@r:\@i]
145  - \@X Rank information of the calling process. Will be [0.0] if
146  number of MPI ranks and number of threads are both 1
147  Same as [\@R:\@I]
148  - \@t Simulation time. Will be the raw simulation cycle time
149  retrieved from the SST Core.
150  @param verbose_level Debugging output level. Calls to debug(),
151  verbose() and fatal() are only output if their output_level
152  parameter is less than or equal to the verbose_level currently
153  set for the object
154  @param verbose_mask Bitmask of allowed message types for debug(),
155  verbose() and fatal(). The Output object will only output the
156  message if the set bits of the output_bits parameter
157  are set in the verbose_mask of the object. It uses this logic:
158  if (~verbose_mask & output_bits == 0) then output is enabled.
159  @param location Output location. Output will be directed to STDOUT,
160  STDERR, FILE, or NONE. If FILE output is selected, the
161  output will be directed to the file defined by the
162  --debug runtime parameter, or to the file 'sst_output' if the
163  --debug parameter is not defined. If the size of MPI_COMM_WORLD
164  is > 1, then the rank process will be appended to the file name.
165  @param localoutputfilename. Send the output of this class to the
166  file identified in localoutputfilename instead of the of the
167  normal output file set by the run time parameter --debug-file.
168  location parameter must be set to FILE. This parameter is
169  intended for special case debug purposes only.
170  */
171  // INITIALIZATION
172  void init(const std::string& prefix, uint32_t verbose_level,
173  uint32_t verbose_mask, output_location_t location,
174  std::string localoutputfilename = "");
175 
176  /** Output the message with formatting as specified by the format parameter.
177  The output will be prepended with the expanded prefix set in the object.
178  @param line Line number of calling function (use CALL_INFO macro)
179  @param file File name calling function (use CALL_INFO macro)
180  @param func Function name calling function (use CALL_INFO macro)
181  @param format Format string. All valid formats for printf are available.
182  @param ... Argument strings for format.
183  */
184  void output(uint32_t line, const char* file, const char* func,
185  const char* format, ...) const
186  __attribute__ ((format (printf, 5, 6)))
187  {
188  va_list arg;
189  if (true == m_objInitialized && NONE != m_targetLoc ) {
190  // Get the argument list and then print it out
191  va_start(arg, format);
192  outputprintf(line, file, func, format, arg);
193  va_end(arg);
194  }
195  }
196 
197  /** Output the message with formatting as specified by the format parameter.
198  @param format Format string. All valid formats for printf are available.
199  @param ... Arguments for format.
200  */
201  void output(const char* format, ...) const
202  __attribute__ ((format (printf, 2, 3)))
203  {
204  va_list arg;
205  if (true == m_objInitialized && NONE != m_targetLoc) {
206  // Get the argument list and then print it out
207  va_start(arg, format);
208  outputprintf(format, arg);
209  va_end(arg);
210  }
211  }
212 
213  /** Output the verbose message with formatting as specified by the format
214  parameter. Output will only occur if specified output_level and
215  output_bits meet criteria defined by object. The output will be
216  prepended with the expanded prefix set in the object.
217  @param line Line number of calling function (use CALL_INFO macro)
218  @param file File name calling function (use CALL_INFO macro)
219  @param func Function name calling function (use CALL_INFO macro)
220  @param output_level For output to occur, output_level must be less than
221  or equal to verbose_level set in object
222  @param output_bits The Output object will only output the
223  message if the set bits of the output_bits parameter are set in
224  the verbose_mask of the object. It uses this logic:
225  if (~verbose_mask & output_bits == 0) then output is enabled.
226  @param format Format string. All valid formats for printf are available.
227  @param ... Arguments for format.
228  */
229  void verbose(uint32_t line, const char* file, const char* func,
230  uint32_t output_level, uint32_t output_bits,
231  const char* format, ...) const
232  __attribute__ ((format (printf, 7, 8)))
233  {
234  va_list arg;
235 
236  if (true == m_objInitialized && NONE != m_targetLoc ) {
237  // First check to see if we are allowed to send output based upon the
238  // verbose_mask and verbose_level checks
239  if (((output_bits & ~m_verboseMask) == 0) &&
240  (output_level <= m_verboseLevel)){
241  // Get the argument list and then print it out
242  va_start(arg, format);
243  outputprintf(line, file, func, format, arg);
244  va_end(arg);
245  }
246  }
247  }
248 
249  /** Output the verbose message with formatting as specified by the format
250  parameter. Output will only occur if specified output_level and
251  output_bits meet criteria defined by object. The output will be
252  prepended with the expanded prefix set in the object.
253  @param tempPrefix For just this call use this prefix
254  @param line Line number of calling function (use CALL_INFO macro)
255  @param file File name calling function (use CALL_INFO macro)
256  @param func Function name calling function (use CALL_INFO macro)
257  @param output_level For output to occur, output_level must be less than
258  or equal to verbose_level set in object
259  @param output_bits The Output object will only output the
260  message if the set bits of the output_bits parameter are set in
261  the verbose_mask of the object. It uses this logic:
262  if (~verbose_mask & output_bits == 0) then output is enabled.
263  @param format Format string. All valid formats for printf are available.
264  @param ... Arguments for format.
265  */
266  void verbosePrefix(const char* tempPrefix, uint32_t line, const char* file, const char* func,
267  uint32_t output_level, uint32_t output_bits,
268  const char* format, ...)
269  __attribute__ ((format (printf, 8, 9)))
270  {
271 
272  va_list arg;
273 
274  if (true == m_objInitialized && NONE != m_targetLoc ) {
275  const std::string normalPrefix = m_outputPrefix;
276  m_outputPrefix = tempPrefix;
277 
278  // First check to see if we are allowed to send output based upon the
279  // verbose_mask and verbose_level checks
280  if (((output_bits & ~m_verboseMask) == 0) &&
281  (output_level <= m_verboseLevel)){
282  // Get the argument list and then print it out
283  va_start(arg, format);
284  outputprintf(line, file, func, format, arg);
285  va_end(arg);
286  }
287 
288  m_outputPrefix = normalPrefix;
289  }
290  }
291 
292  /** Output the debug message with formatting as specified by the format
293  parameter. Output will only occur if specified output_level and
294  output_bits meet criteria defined by object. The output will be
295  prepended with the expanded prefix set in the object.
296  NOTE: Debug outputs will only occur if the __SST_DEBUG_OUTPUT__ is defined.
297  this define can be set in source code or by setting the
298  --enable-debug option during SST configuration.
299  @param line Line number of calling function (use CALL_INFO macro)
300  @param file File name calling function (use CALL_INFO macro)
301  @param func Function name calling function (use CALL_INFO macro)
302  @param output_level For output to occur, output_level must be less than
303  or equal to verbose_level set in object
304  @param output_bits The Output object will only output the
305  message if the set bits of the output_bits parameter are set in
306  the verbose_mask of the object. It uses this logic:
307  if (~verbose_mask & output_bits == 0) then output is enabled.
308  @param format Format string. All valid formats for printf are available.
309  @param ... Arguments for format.
310  */
311  void debug(uint32_t line, const char* file, const char* func,
312  uint32_t output_level, uint32_t output_bits,
313  const char* format, ...) const
314  __attribute__ ((format (printf, 7, 8)))
315  {
316 #ifdef __SST_DEBUG_OUTPUT__
317  va_list arg;
318  if (true == m_objInitialized && NONE != m_targetLoc ) {
319  // First check to see if we are allowed to send output based upon the
320  // verbose_mask and verbose_level checks
321  if (((output_bits & ~m_verboseMask) == 0) &&
322  (output_level <= m_verboseLevel)){
323  // Get the argument list and then print it out
324  va_start(arg, format);
325  outputprintf(line, file, func, format, arg);
326  va_end(arg);
327  }
328  }
329 #else
330  /* When debug is disabled, silence warnings of unused parameters */
331  (void)line;
332  (void)file;
333  (void)func;
334  (void)output_level;
335  (void)output_bits;
336  (void)format;
337 #endif
338  }
339 
340 
341  /** Output the fatal message with formatting as specified by the format
342  parameter. Message will be sent to the output location and to stderr.
343  The output will be prepended with the expanded prefix set
344  in the object.
345  NOTE: fatal() will call MPI_Abort(exit_code) to terminate simulation.
346  @param line Line number of calling function (use CALL_INFO macro)
347  @param file File name calling function (use CALL_INFO macro)
348  @param func Function name calling function (use CALL_INFO macro)
349  @param exit_code The exit code used for termination of simulation.
350  will be passed to MPI_Abort()
351  @param format Format string. All valid formats for printf are available.
352  @param ... Arguments for format.
353  */
354  void fatal(uint32_t line, const char* file, const char* func,
355  uint32_t exit_code,
356  const char* format, ...) const
357  __attribute__ ((format (printf, 6, 7))) ;
358 
359 
360  // GET / SET METHODS
361 
362  /** Sets object prefix
363  @param prefix Prefix to be prepended to all strings emitted by calls to
364  debug(), verbose(), fatal() and possibly output().
365  NOTE: No space will be inserted between the prepended prefix
366  string and the normal output string.
367  Prefix can contain the following escape codes:
368  - \@f Name of the file in which output call was made.
369  - \@l Line number in the file in which output call was made.
370  - \@p Name of the function from which output call was made.
371  - \@r MPI rank of the calling process. Will be empty if
372  MPI_COMM_WORLD size is 1.
373  - \@R MPI rank of the calling process. Will be 0 if
374  MPI_COMM_WORLD size is 1.
375  - \@i Thread Id of the calling process. Will be empty if
376  number of threads is 1.
377  - \@I Thread Id of the calling process. Will be 0 if
378  number of threads is 1.
379  - \@x Rank information of the calling process. Will be empty if
380  number of MPI ranks and number of threads are both 1
381  Same as [\@r:\@i]
382  - \@X Rank information of the calling process. Will be [0.0] if
383  number of MPI ranks and number of threads are both 1
384  Same as [\@R:\@I]
385  - \@t Simulation time. Will be the raw simulation cycle time
386  retrieved from the SST Core.
387  */
388  void setPrefix(const std::string& prefix);
389 
390  /** Returns object prefix */
391  std::string getPrefix() const;
392 
393  /** Sets object verbose mask
394  @param verbose_mask Bitmask of allowed message types for debug(),
395  verbose() and fatal(). The Output object will only output the
396  message if the set bits of the output_bits parameter
397  are set in the verbose_mask of the object. It uses this logic:
398  if (~verbose_mask & output_bits == 0) then output is enabled.
399  */
400  void setVerboseMask(uint32_t verbose_mask);
401 
402  /** Returns object verbose mask */
403  uint32_t getVerboseMask() const;
404 
405  /** Sets object verbose level
406  @param verbose_level Debugging output level. Calls to debug(),
407  verbose() and fatal() are only output if their output_level
408  parameter is less than or equal to the verbose_level currently
409  set for the object
410  */
411  void setVerboseLevel(uint32_t verbose_level);
412 
413  /** Returns object verbose level */
414  uint32_t getVerboseLevel() const;
415 
416  /** Sets object output location
417  @param location Output location. Output will be directed to STDOUT,
418  STDERR, FILE, or NONE. If FILE output is selected, the
419  output will be directed to the file defined by the
420  --debug runtime parameter, or to the file 'sst_output' if the
421  --debug parameter is not defined. If the size of MPI_COMM_WORLD
422  is > 1, then the rank process will be appended to the file name.
423  */
424  void setOutputLocation(output_location_t location);
425 
426  /** Returns object output location */
428 
429  /** This method allows for the manual flushing of the output. */
430  inline void flush() const {std::fflush(*m_targetOutputRef);}
431 
432 
433  /** This method sets the static filename used by SST. It can only be called
434  once, and is automatically called by the SST Core. No components should
435  call this method.
436  */
437  static void setFileName(const std::string& filename);
438 
439  static Output& getDefaultObject() { return m_defaultObject; }
440 
441 private:
442  // Support Methods
443  void setTargetOutput(output_location_t location);
444  void openSSTTargetFile() const;
445  void closeSSTTargetFile();
446  // std::string getMPIProcName() const;
447  int getMPIWorldRank() const;
448  int getMPIWorldSize() const;
449  uint32_t getNumThreads() const;
450  uint32_t getThreadRank() const;
451  std::string buildPrefixString(uint32_t line,
452  const std::string& file,
453  const std::string& func) const;
454  void outputprintf(uint32_t line,
455  const std::string &file,
456  const std::string &func,
457  const char *format,
458  va_list arg) const;
459  void outputprintf(const char *format, va_list arg) const;
460 
461  friend int ::main(int argc, char **argv);
462  static Output& setDefaultObject(const std::string& prefix, uint32_t verbose_level,
463  uint32_t verbose_mask, output_location_t location,
464  std::string localoutputfilename = "")
465  {
466  m_defaultObject.init(prefix, verbose_level, verbose_mask, location, localoutputfilename);
467  return getDefaultObject();
468  }
469 
470  static void setWorldSize(const RankInfo &ri, int mpiRank)
471  {
472  m_worldSize = ri;
473  m_mpiRank = mpiRank;
474  }
475 
476  static void setThreadID(std::thread::id mach, uint32_t user)
477  {
478  m_threadMap.insert(std::make_pair(mach, user));
479  }
480 
481 
482  // Internal Member Variables
483  bool m_objInitialized;
484  std::string m_outputPrefix;
485  uint32_t m_verboseLevel;
486  uint32_t m_verboseMask;
487  output_location_t m_targetLoc;
488 
489  static Output m_defaultObject;
490 
491  // m_targetOutputRef is a pointer to a FILE* object. This is because
492  // the actual FILE* object (m_sstFileHandle) is not created on construction,
493  // but during the first call any of output(), verbose() or debug() methods.
494  // m_targetOutputRef points to either &m_sstFileHandle, &stdout, or &stderr
495  // depending upon constructor for the object. However m_sstFileHandle is a
496  // static variable that is set by the startup of SST, and the location
497  // cannot be changed in the constructor or a call to setFileName().
498  std::FILE** m_targetOutputRef;
499 
500  // m_targetFileHandleRef, m_targetFileNameRef, and m_targetFileAccessCount
501  // are pointers to their associated types. These point to either the local
502  // output file information or to the global simulation output file information.
503  std::FILE** m_targetFileHandleRef;
504  std::string* m_targetFileNameRef;
505  uint32_t* m_targetFileAccessCountRef;
506 
507  // Static Member Variables regarding the Global simulation file info
508  static std::string m_sstGlobalSimFileName;
509  static std::FILE* m_sstGlobalSimFileHandle;
510  static uint32_t m_sstGlobalSimFileAccessCount;
511 
512  // File Member Variables regarding the local simulation file info
513  std::string m_sstLocalFileName;
514  std::FILE* m_sstLocalFileHandle;
515  uint32_t m_sstLocalFileAccessCount;
516 
517  static std::unordered_map<std::thread::id, uint32_t> m_threadMap;
518  static RankInfo m_worldSize;
519  static int m_mpiRank;
520 
521 };
522 
523 // Class to easily trace function enter and exit
525 public:
526  TraceFunction(uint32_t line, const char* file, const char* func);
527  ~TraceFunction();
528 
529  Output& getOutput() {return output;}
530 
531 private:
532  Output output;
533  uint32_t line;
534  std::string file;
535  std::string function;
536  uint32_t rank;
537  uint32_t thread;
538 };
539 
540 
541 } // namespace SST
542 
543 #endif // SST_CORE_OUTPUT_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:54
void setVerboseLevel(uint32_t verbose_level)
Sets object verbose level.
Definition: output.cc:103
void setOutputLocation(output_location_t location)
Sets object output location.
Definition: output.cc:139
void debug(uint32_t line, const char *file, const char *func, uint32_t output_level, uint32_t output_bits, const char *format,...) const
Output the debug message with formatting as specified by the format parameter.
Definition: output.h:311
output_location_t
Choice of output location.
Definition: output.h:59
uint32_t getVerboseLevel() const
Returns object verbose level.
Definition: output.cc:109
void setVerboseMask(uint32_t verbose_mask)
Sets object verbose mask.
Definition: output.cc:115
void output(const char *format,...) const
Output the message with formatting as specified by the format parameter.
Definition: output.h:201
void init(const std::string &prefix, uint32_t verbose_level, uint32_t verbose_mask, output_location_t location, std::string localoutputfilename="")
Initialize the object after construction.
Definition: output.cc:71
Output()
Default Constructor.
Definition: output.cc:59
std::string getPrefix() const
Returns object prefix.
Definition: output.cc:133
Definition: output.h:60
void verbose(uint32_t line, const char *file, const char *func, uint32_t output_level, uint32_t output_bits, const char *format,...) const
Output the verbose message with formatting as specified by the format parameter.
Definition: output.h:229
void verbosePrefix(const char *tempPrefix, uint32_t line, const char *file, const char *func, uint32_t output_level, uint32_t output_bits, const char *format,...)
Output the verbose message with formatting as specified by the format parameter.
Definition: output.h:266
Definition: output.h:63
Definition: output.h:524
static void setFileName(const std::string &filename)
This method sets the static filename used by SST.
Definition: output.cc:218
Definition: output.h:61
void output(uint32_t line, const char *file, const char *func, const char *format,...) const
Output the message with formatting as specified by the format parameter.
Definition: output.h:184
Definition: output.h:62
void fatal(uint32_t line, const char *file, const char *func, uint32_t exit_code, const char *format,...) const
Output the fatal message with formatting as specified by the format parameter.
Definition: output.cc:155
uint32_t getVerboseMask() const
Returns object verbose mask.
Definition: output.cc:121
void flush() const
This method allows for the manual flushing of the output.
Definition: output.h:430
output_location_t getOutputLocation() const
Returns object output location.
Definition: output.cc:149
void setPrefix(const std::string &prefix)
Sets object prefix.
Definition: output.cc:127