PandA-2024.02
translator.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
44 #include "translator.hpp"
45 #include "Parameter.hpp"
46 #include "custom_map.hpp"
47 #include "custom_set.hpp"
48 #include "dbgPrintHelper.hpp"
49 #include "evaluation.hpp"
50 #include "exceptions.hpp"
52 #include "fileIO.hpp"
54 #include "latex_table_xml.hpp"
55 #include "polixml.hpp"
56 #include "string_manipulation.hpp"
57 #include "utility.hpp"
58 #include "xml_dom_parser.hpp"
59 #include "xml_helper.hpp"
60 
61 #include <boost/algorithm/string/replace.hpp>
62 #include <cmath>
63 #include <filesystem>
64 #include <fstream>
65 #include <iomanip>
66 #include <string>
67 
68 #define CSV_COL_SEPARATOR ","
69 
70 #define SKIPPED_COLUMN \
71  ("Loop_number")("bit_expr")("comp_expr")("const_readings")("div_expr")("mult_expr")("plusminus_expr")( \
72  "memory_writings")("register_accesses")("memory_readings")("register_writing")("Backward_branches")
73 
74 #define SKIPPING_MACRO(r, data, elem) skipping.insert(elem);
75 
76 #define TF_NAME(r, data, elem) \
77  name = "CA_" #elem; \
78  name = name.substr(22); \
79  name = name.substr(0, name.find(')')); \
80  string_to_TF[name] = BOOST_PP_CAT(TF_, elem);
81 
82 #define CO_NAME(r, data, elem) \
83  name = "CO_" #elem; \
84  name = name.substr(22); \
85  name = name.substr(0, name.find(')')); \
86  string_to_CO[name] = BOOST_PP_CAT(CO_, elem);
87 
88 #define TOF_NAME(r, data, elem) \
89  name = "TOF_" #elem; \
90  name = name.substr(23); \
91  name = name.substr(0, name.find(')')); \
92  string_to_TOF[name] = BOOST_PP_CAT(TOF_, elem);
93 
95 #include "latex_format_stat.data"
96 };
98  : column_alignment("c|"),
99  text_format(LatexColumnFormat::TF_number),
101  comparison_operator(LatexColumnFormat::CO_abs_le),
102  total_format(LatexColumnFormat::TOF_none)
103 {
104 }
105 
107 
110 
113 
115 Translator::LatexColumnFormat::LatexColumnFormat::get_TF(const std::string& string)
116 {
117  if(string_to_TF.empty())
118  {
119  // cppcheck-suppress unusedVariable
120  std::string name;
121  BOOST_PP_SEQ_FOR_EACH(TF_NAME, BOOST_PP_EMPTY, TEXT_FORMAT);
122  }
123  THROW_ASSERT(string_to_TF.find(string) != string_to_TF.end(), "String " + string + " is not a valid Text Format");
124  return string_to_TF.find(string)->second;
125 }
126 
128 Translator::LatexColumnFormat::LatexColumnFormat::get_CO(const std::string& string)
129 {
130  if(string_to_CO.empty())
131  {
132  // cppcheck-suppress unusedVariable
133  std::string name;
135  }
136  THROW_ASSERT(string_to_CO.find(string) != string_to_CO.end(),
137  "String " + string + " is not a valid Comparison Operator");
138  return string_to_CO.find(string)->second;
139 }
140 
142 Translator::LatexColumnFormat::LatexColumnFormat::GetTotalFormat(const std::string& string)
143 {
144  if(string_to_TOF.empty())
145  {
146  // cppcheck-suppress unusedVariable
147  std::string name;
148  BOOST_PP_SEQ_FOR_EACH(TOF_NAME, BOOST_PP_EMPTY, TOTAL_FORMAT);
149  }
150  THROW_ASSERT(string_to_TOF.find(string) != string_to_TOF.end(), "String " + string + " is not a valid Total Format");
151  return string_to_TOF.find(string)->second;
152 }
153 
154 bool Translator::LatexColumnFormat::Compare(const long double A, const ComparisonOperator comparator,
155  const long double B)
156 {
157  switch(comparator)
158  {
159  case(CO_abs_le):
160  {
161  return fabsl(A) <= fabsl(B);
162  }
163  default:
164  {
165  THROW_UNREACHABLE("Operator " + STR(comparator) + " not supported");
166  }
167  }
168  return false;
169 }
170 
172  : Param(_Param), debug_level(_Param->get_class_debug_level(GET_CLASS(*this)))
173 {
174 }
175 
177  const std::string& file_name) const
178 {
179  std::ofstream out(file_name.c_str());
180  THROW_ASSERT(out, "Error in opening output file " + file_name);
181  CustomOrderedSet<std::string> column_labels;
182  for(const auto& row : results)
183  {
184  for(const auto& column : row.second)
185  {
186  column_labels.insert(column.first);
187  }
188  }
189  out << "Benchmark";
190  for(const auto& column_label : column_labels)
191  {
192  out << CSV_COL_SEPARATOR << column_label;
193  }
194  out << std::endl;
195  for(const auto& row : results)
196  {
197  out << row.first;
198  for(const auto& column_label : column_labels)
199  {
200  const auto val_it = row.second.find(column_label);
201  if(val_it != row.second.end())
202  {
203  out << CSV_COL_SEPARATOR << row.second.at(column_label);
204  }
205  else
206  {
207  out << CSV_COL_SEPARATOR;
208  }
209  }
210  out << std::endl;
211  }
212 }
213 
215  const std::map<std::string, CustomOrderedSet<std::string>>& tags,
216  const CustomUnorderedMap<std::string,
218  results,
219  const std::string& file_name) const
220 {
221  std::ofstream out(file_name.c_str());
222  THROW_ASSERT(out, "Error in opening output file " + file_name);
224  std::string,
226  it_end = results.end();
227  for(it = results.begin(); it != it_end; ++it)
228  {
229  out << "#Benchmark " << it->first << "# ";
230  std::map<std::string, CustomOrderedSet<std::string>>::const_iterator it2, it2_end = tags.end();
231  for(it2 = tags.begin(); it2 != it2_end; ++it2)
232  {
233  out << "#" << it2->first << "# ";
234  const auto& bench_counters = it->second;
235  if(bench_counters.find(it2->first) != bench_counters.end())
236  {
237  const auto& cat_tags = it2->second;
238  const auto& cat_counters = bench_counters.find(it2->first)->second;
239  CustomOrderedSet<std::string>::const_iterator it4, it4_end = cat_tags.end();
240  for(it4 = cat_tags.begin(); it4 != it4_end; ++it4)
241  {
242  out << "#" << *it4 << "# ";
243  if(cat_counters.find(*it4) != cat_counters.end())
244  {
245  out << cat_counters.find(*it4)->second;
246  }
247  else
248  {
249  out << "0.0";
250  }
251  out << CSV_COL_SEPARATOR;
252  }
253  }
254  }
255  out << std::endl;
256  }
257 }
258 
260  const Parameters_FileFormat, const std::string& file_name) const
261 {
263  {
264 #ifndef NDEBUG
266  for(const auto& row : results)
267  {
269  for(auto const& column : row.second)
270  {
271  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---" + column.first + ":" + column.second);
272  }
274  }
276 #endif
277  }
278 
280  size_t max_column_width = NUM_CST_latex_table_max_column_width;
281 
283  std::map<std::string, CustomUnorderedMapStable<std::string, bool>> bold_cells;
284 
286  std::string bambu_version;
287 
289  std::string timestamp;
290 
292  std::string bambu_arguments;
293 
295  std::list<std::string> benchmarks;
296 
297  if(Param->isOption(OPT_experimental_setup_file))
298  {
299  try
300  {
301  XMLDomParser parser(Param->getOption<std::string>(OPT_experimental_setup_file));
302  parser.Exec();
303 
304  const xml_element* node = parser.get_document()->get_root_node(); // deleted by DomParser.
305 
306  for(const auto& root_child : node->get_children())
307  {
308  const auto* child = GetPointer<const xml_element>(root_child);
309  if(not child)
310  {
311  continue;
312  }
313  if(child->get_name() == STR_XML_experimental_setup_bambu_version)
314  {
315  bambu_version = child->get_attribute(STR_XML_experimental_setup_value)->get_value();
316  }
317  else if(child->get_name() == STR_XML_experimental_setup_timestamp)
318  {
319  timestamp = child->get_attribute(STR_XML_experimental_setup_value)->get_value();
320  }
321  else if(child->get_name() == STR_XML_experimental_setup_bambu_arguments)
322  {
323  bambu_arguments = child->get_attribute(STR_XML_experimental_setup_value)->get_value();
324  }
325  else if(child->get_name() == STR_XML_experimental_setup_benchmarks)
326  {
327  for(const auto& benchmark : child->get_children())
328  {
329  const auto* benchmark_xml = GetPointer<const xml_element>(benchmark);
330  if(not benchmark_xml)
331  {
332  continue;
333  }
334  benchmarks.push_back(benchmark_xml->get_attribute(STR_XML_experimental_setup_value)->get_value());
335  }
336  }
337  }
338  }
339  catch(const char* msg)
340  {
341  std::cerr << msg << std::endl;
342  THROW_ERROR("Error during parsing of experimental setup");
343  }
344  catch(const std::string& msg)
345  {
346  std::cerr << msg << std::endl;
347  THROW_ERROR("Error during parsing of experimental setup");
348  }
349  catch(const std::exception& ex)
350  {
351  std::cout << "Exception caught: " << ex.what() << std::endl;
352  THROW_ERROR("Error during parsing of experimental setup");
353  }
354  catch(...)
355  {
356  std::cerr << "unknown exception" << std::endl;
357  THROW_ERROR("Error during parsing of experimental setup");
358  }
359  }
360 
363 
364  if(Param->isOption(OPT_latex_format_file))
365  {
366  parser = XMLDomParserRef(new XMLDomParser(Param->getOption<std::string>(OPT_latex_format_file)));
367  }
368  else
369  {
370  parser = XMLDomParserRef(new XMLDomParser("default_latex_format_stat.data", default_latex_format_stat));
371  }
372 
373  std::list<LatexColumnFormat> latex_column_formats;
374  read_column_formats(parser, latex_column_formats, max_column_width);
375 
376  // The width of the column in the data section
378 
379  std::ofstream out(file_name.c_str());
380 
381  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Computing totals");
384  for(const auto& latex_column_format : latex_column_formats)
385  {
386  switch(latex_column_format.total_format)
387  {
388  case(LatexColumnFormat::TotalFormat::TOF_none):
389  break;
390  case(LatexColumnFormat::TotalFormat::TOF_average):
391  {
392  bool found = false;
393  long double total = 0;
394  for(auto line : results)
395  {
396  if(line.second.find(latex_column_format.source_name) != line.second.end())
397  {
398  total += std::stold(line.second[latex_column_format.source_name]);
399  found = true;
400  }
401  }
402  if(found)
403  {
404  total /= results.size();
405  totals[latex_column_format.source_name] = STR(total);
406  }
407  break;
408  }
409  case(LatexColumnFormat::TotalFormat::TOF_overall):
410  {
411  bool found = false;
412  long double total = 0;
413  for(auto line : results)
414  {
415  if(line.second.find(latex_column_format.source_name) != line.second.end())
416  {
417  total += std::stold(line.second[latex_column_format.source_name]);
418  found = true;
419  }
420  }
421  if(found)
422  {
423  totals[latex_column_format.source_name] = STR(total);
424  }
425  break;
426  }
427  default:
428  THROW_UNREACHABLE("");
429  }
430  }
431  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Computed totals");
432 
433  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Adjusting precision");
435  for(const auto& column : latex_column_formats)
436  {
437  if(column.text_format == LatexColumnFormat::TF_number and column.precision != 0)
438  {
439  for(auto& line : results)
440  {
441  if(line.second.find(column.source_name) != line.second.end())
442  {
443  std::stringstream modified_string_stream;
444  modified_string_stream.setf(std::ios::fixed, std::ios::floatfield);
445  modified_string_stream.precision(column.precision);
446  modified_string_stream << std::stold((line.second)[column.source_name]);
447  (line.second)[column.source_name] = modified_string_stream.str();
448  }
449  }
450  if(totals.find(column.source_name) != totals.end())
451  {
452  std::stringstream modified_string_stream;
453  modified_string_stream.setf(std::ios::fixed, std::ios::floatfield);
454  modified_string_stream.precision(column.precision);
455  modified_string_stream << std::stold(totals[column.source_name]);
456  totals[column.source_name] = modified_string_stream.str();
457  }
458  }
459  }
460  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Adjusted precision");
461 
462  // Checking for bold column
463  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking bold cells");
464  for(auto const& column : latex_column_formats)
465  {
466  if(column.compared_columns.size())
467  {
468  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking column " + column.source_name);
469  for(auto line : results)
470  {
471  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking cell " + line.first);
472  bool bold = true;
473  const CustomUnorderedSet<std::string> columns_to_be_compared = column.compared_columns;
475  column_to_be_compared_end = columns_to_be_compared.end();
476  for(column_to_be_compared = columns_to_be_compared.begin();
477  column_to_be_compared != column_to_be_compared_end; ++column_to_be_compared)
478  {
479  if(not LatexColumnFormat::Compare(std::stold(line.second[column.source_name]),
480  column.comparison_operator,
481  std::stold(line.second[*column_to_be_compared])))
482  {
483  bold = false;
484  break;
485  }
486  }
487  if(bold)
488  {
490  bold_cells[line.first][column.source_name] = true;
491  }
492  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked cell " + line.first);
493  }
494  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked column " + column.source_name);
495  }
496  }
497  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked bold cells");
498 
499  // Computing data_width
500  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Computing column width");
501  for(const auto& line : results)
502  {
503  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Reading benchmark " + line.first);
504  std::string escaped_index = line.first;
505  add_escape(escaped_index, "_");
506  if(escaped_index.size() > data_width[(latex_column_formats.begin())->source_name])
507  {
508  data_width[(latex_column_formats.begin())->source_name] = escaped_index.size();
510  "---Set data width for column " + std::string((latex_column_formats.begin())->source_name) +
511  " to " + STR(escaped_index.size()));
512  }
513 
514  const auto& current_line = line.second;
515  for(const auto& current_tag : current_line)
516  {
517  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Reading column " + current_tag.first);
518  if(current_tag.second.size() > data_width[current_tag.first])
519  {
520  data_width[current_tag.first] = current_tag.second.size();
522  "---New column width " + STR(data_width[current_tag.first]));
523  }
524  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Read column " + current_tag.first);
525  }
526  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Read benchmark " + line.first);
527  }
528  for(const auto& total : totals)
529  {
531  "-->Considering width total for column " + total.first + ": " + STR(total.second.size()) + " vs " +
532  STR(data_width[total.first]));
533  if(total.second.size() > data_width[total.first])
534  {
535  data_width[total.first] = total.second.size();
536  }
538  }
539  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Computed column width");
540 
542  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking exponential notation column width");
543  for(auto& column : latex_column_formats)
544  {
545  if(column.text_format == LatexColumnFormat::TF_number)
546  {
548  "---" + column.column_name + " " + STR(data_width[column.source_name]) + " vs " +
549  STR(max_column_width));
550  }
551  if(data_width[column.source_name] > max_column_width and column.text_format == LatexColumnFormat::TF_number)
552  {
553  column.text_format = LatexColumnFormat::TF_exponential;
554  }
555  }
556  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked exponential notation column width");
557 
558  // Transforming into exponential_notation
559  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking exponential notation");
560  for(auto const& column : latex_column_formats)
561  {
562  if(column.text_format == LatexColumnFormat::TF_exponential)
563  {
564  for(auto& line : results)
565  {
566  auto& current_line = line.second;
567  if(current_line.find(column.source_name) != current_line.end())
568  {
569  const auto value = current_line.find(column.source_name)->second;
570  current_line[column.source_name] = get_exponential_notation(value);
571  }
572  }
573  if(totals.find(column.source_name) != totals.end())
574  {
575  const auto value = totals.find(column.source_name)->second;
576  totals[column.source_name] = get_exponential_notation(value);
577  }
578  }
579  }
580  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked exponential notation");
581 
582  for(auto const& bold_line : bold_cells)
583  {
584  const auto& current_bold_line = bold_line.second;
585  CustomUnorderedMapStable<std::string, bool>::const_iterator bold_cell, bold_cell_end = current_bold_line.end();
586  for(bold_cell = current_bold_line.begin(); bold_cell != bold_cell_end; ++bold_cell)
587  {
588  std::string before_bold = results[bold_line.first][bold_cell->first];
589  results[bold_line.first][bold_cell->first] = "\\textbf{" + before_bold + "}";
590  }
591  }
592 
594  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Recomputing column width");
595  for(auto const& column : latex_column_formats)
596  {
597  if(column.text_format == LatexColumnFormat::TF_exponential or column.compared_columns.size())
598  {
599  data_width[column.source_name] = 0;
600  for(auto const& line : results)
601  {
602  if(line.second.find(column.source_name) != line.second.end() and
603  line.second.find(column.source_name)->second.size() > data_width[column.source_name])
604  {
605  data_width[column.source_name] = line.second.find(column.source_name)->second.size();
606  }
607  }
608  data_width[column.source_name] += 4;
609  }
610  else if(column.text_format == LatexColumnFormat::TF_number)
611  {
612  data_width[column.source_name] += 4;
614  "---New size of " + std::string(column.source_name) + ": " +
615  STR(data_width[column.source_name]));
616  }
617  }
618  for(auto const& column : latex_column_formats)
619  {
620  if(column.column_name.size() > data_width[column.source_name])
621  {
622  data_width[column.source_name] = column.column_name.size();
623  }
624  }
625  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Recomputed column width");
626 
627  // Writing file
628  // Opening tabular
629  // cppcheck-suppress duplicateExpression
630  if(bambu_version != "" or timestamp != "" or bambu_arguments != "")
631  {
632  out << "%Generated";
633  if(timestamp != "")
634  {
635  out << " at " << timestamp;
636  }
637  if(bambu_version != "")
638  {
639  out << " with bambu " << bambu_version;
640  }
641  if(bambu_arguments != "")
642  {
643  out << " with arguments " << bambu_arguments;
644  }
645  out << std::endl;
646  }
647  out << "\\begin{tabular}{|";
648  for(auto const& column : latex_column_formats)
649  {
650  out << column.column_alignment;
651  }
652  out << "}\n";
653  out << "\\hline\n";
654 
655  // Writing the header
656  bool first_column = true;
657  for(const auto& column : latex_column_formats)
658  {
659  if(not first_column)
660  {
661  out << " & ";
662  }
663  first_column = false;
664  std::string column_name = column.column_name;
665  if(column_name.size() < data_width[column.source_name])
666  {
667  column_name.resize(data_width[column.source_name], ' ');
668  }
669  out << column_name;
670  }
671  out << " \\\\" << std::endl;
672  out << "\\hline" << std::endl;
673  for(auto const& line : results)
674  {
675  first_column = true;
676  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Printing line for benchmark " + line.first);
677  for(auto const& column : latex_column_formats)
678  {
680  "-->Printing column " + column.column_name + " (" + column.source_name + ")");
681  if(not first_column)
682  {
683  out << " & ";
684  }
685  if(column.text_format == LatexColumnFormat::TF_number or
686  column.text_format == LatexColumnFormat::TF_exponential)
687  {
688  out << "$ ";
689  }
690  std::string value;
691  if(first_column)
692  {
693  value = line.first;
694  }
695  else if(line.second.find(column.source_name) != line.second.end())
696  {
697  value = line.second.find(column.source_name)->second;
698  }
699  add_escape(value, "_");
700  size_t numerical_delimiters_size = (column.text_format == LatexColumnFormat::TF_number or
701  column.text_format == LatexColumnFormat::TF_exponential) ?
702  4 :
703  0;
704  if(value.size() + numerical_delimiters_size < data_width[column.source_name])
705  {
707  "---Resize to " + STR(data_width[column.source_name]));
708  value.resize(data_width[column.source_name] - numerical_delimiters_size, ' ');
709  }
710  out << value;
711  if(column.text_format == LatexColumnFormat::TF_number or
712  column.text_format == LatexColumnFormat::TF_exponential)
713  {
714  out << " $";
715  }
716  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Printed column " + column.column_name);
717  first_column = false;
718  }
719  out << " \\\\" << std::endl;
720  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Printed line for benchmark " + line.first);
721  }
722 
724 
726  for(const auto& latex_column_format : latex_column_formats)
727  {
728  switch(latex_column_format.total_format)
729  {
730  case(LatexColumnFormat::TotalFormat::TOF_average):
731  case(LatexColumnFormat::TotalFormat::TOF_overall):
732  {
733  totals_to_be_written.insert(latex_column_format.total_format);
734  break;
735  }
736  case(LatexColumnFormat::TotalFormat::TOF_none):
737  {
738  break;
739  }
740  default:
741  {
742  THROW_UNREACHABLE("");
743  }
744  }
745  }
746  for(const auto& line_to_be_written : totals_to_be_written)
747  {
748  out << "\\hline" << std::endl;
749  first_column = true;
750  for(const auto& column : latex_column_formats)
751  {
752  if(not first_column)
753  {
754  out << " & ";
755  }
756  if(column.text_format == LatexColumnFormat::TF_number or
757  column.text_format == LatexColumnFormat::TF_exponential)
758  {
759  out << "$ ";
760  }
761  std::string value;
762  if(first_column)
763  {
764  switch(line_to_be_written)
765  {
766  case(LatexColumnFormat::TotalFormat::TOF_average):
767  {
768  value = "Average";
769  break;
770  }
771  case(LatexColumnFormat::TotalFormat::TOF_overall):
772  {
773  value = "Overall";
774  break;
775  }
776  case(LatexColumnFormat::TotalFormat::TOF_none):
777  {
778  THROW_UNREACHABLE("");
779  break;
780  }
781  default:
782  {
783  THROW_UNREACHABLE("");
784  }
785  }
786  }
787  else if(column.total_format == line_to_be_written and totals.find(column.source_name) != totals.end())
788  {
789  value = totals.find(column.source_name)->second;
790  }
791  add_escape(value, "_");
792  size_t numerical_delimiters_size = (column.text_format == LatexColumnFormat::TF_number or
793  column.text_format == LatexColumnFormat::TF_exponential) ?
794  4 :
795  0;
796  if(value.size() + numerical_delimiters_size < data_width[column.source_name])
797  {
799  "---Resize to " + STR(data_width[column.source_name]));
800  value.resize(data_width[column.source_name] - numerical_delimiters_size, ' ');
801  }
802  out << value;
803  if(column.text_format == LatexColumnFormat::TF_number or
804  column.text_format == LatexColumnFormat::TF_exponential)
805  {
806  out << " $";
807  }
808  first_column = false;
809  }
810  out << " \\\\" << std::endl;
811  }
812 
813  // Closing tabular
814  out << "\\hline" << std::endl;
815  out << "\\end{tabular}\n";
816  if(not benchmarks.empty())
817  {
818  out << "%Benchmarks:" << std::endl;
819  for(const auto& benchmark : benchmarks)
820  {
821  out << "%" << benchmark << std::endl;
822  }
823  }
824 }
825 
827  const std::map<std::string, CustomOrderedSet<std::string>>& tags,
828  const CustomUnorderedMap<std::string, CustomOrderedSet<std::string>>& keys,
829  const CustomUnorderedMap<std::string,
831  input_data,
832  const CustomUnorderedMap<std::string,
834  merge_data,
835  CustomUnorderedMap<std::string,
837  output_data) const
838 {
840  output_data = input_data;
842  std::string,
844  it_end = input_data.end();
845  for(it = input_data.begin(); it != it_end; ++it)
846  {
847  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Considering input " + it->first);
848  const auto& cat = it->second;
850  it2_end = cat.end();
851  for(it2 = cat.begin(); it2 != it2_end; ++it2)
852  {
853  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Considering category " + it2->first);
854  if(tags.find(it2->first) != tags.end())
855  {
856  CustomOrderedSet<std::string>::const_iterator it3, it3_end = tags.find(it2->first)->second.end();
857  for(it3 = tags.find(it2->first)->second.begin(); it3 != it3_end; ++it3)
858  {
859  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Considering tag " + *it3);
860  if(keys.find(it2->first) != keys.end())
861  {
862  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Considering key category " + it2->first);
863  if(merge_data.find(it->first) != merge_data.end())
864  {
865  const auto& benchmark_merge_data = merge_data.find(it->first)->second;
866  if(benchmark_merge_data.find(it2->first) != benchmark_merge_data.end())
867  {
868  const auto& cat_merge_data = benchmark_merge_data.find(it2->first)->second;
869  if(cat_merge_data.find(*it3) != cat_merge_data.end())
870  {
871  output_data[it->first][it2->first][*it3] = cat_merge_data.find(*it3)->second;
873  "Replacing " + it->first + "." + it2->first);
874  }
875  }
876  }
877  }
878  }
879  }
880  }
881  }
883 }
884 
886 {
887  try
888  {
889  XMLDomParser parser(Param->getOption<std::string>(OPT_normalization_file));
891  parser.Exec();
892  if(parser)
893  {
894  // Walk the tree:
895  const xml_element* node = parser.get_document()->get_root_node(); // deleted by DomParser.
896 
898  // Recurse through child nodes:
899  const xml_node::node_list list = node->get_children();
900  for(const auto& iter : list)
901  {
902  const auto* feature = GetPointer<const xml_element>(iter);
903  if(!feature)
904  {
905  continue;
906  }
907  if(feature->get_name() == "feature")
908  {
909  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Read a new feature");
910  long double value;
911  std::string name;
912  LOAD_XVM(name, feature);
913  LOAD_XVM(value, feature);
914  normalization[name] = value;
916  "Read feature normalization" + name + " " + STR(value));
917  }
918  }
919  }
920  }
921  catch(const char* msg)
922  {
923  std::cerr << msg << std::endl;
924  THROW_ERROR("Error during parsing of normalization file");
925  }
926  catch(const std::string& msg)
927  {
928  std::cerr << msg << std::endl;
929  THROW_ERROR("Error during parsing of normalization file");
930  }
931  catch(const std::exception& ex)
932  {
933  std::cout << "Exception caught: " << ex.what() << std::endl;
934  THROW_ERROR("Error during parsing of normalization file");
935  }
936  catch(...)
937  {
938  std::cerr << "unknown exception" << std::endl;
939  THROW_ERROR("Error during parsing of normalization file");
940  }
941 }
942 
943 void Translator::replace_underscore(std::string& ioString)
944 {
945  boost::algorithm::replace_all(ioString, "_", " ");
946 }
947 
948 std::string Translator::get_exponential_notation(const std::string& input) const
949 {
950  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " Get exponential notation of " + input);
951  std::ostringstream output;
952  output << std::setiosflags(std::ios::scientific);
953  output << std::setprecision(Param->getOption<int>(OPT_precision));
954  output << std::stold(input);
955  std::string result = output.str();
956  std::string mantissa = result.substr(0, result.find('e'));
957  std::string exponent = result.substr(result.find('e') + 1);
958  std::string::size_type pos = 1;
959  while(exponent[pos] == '0')
960  {
961  pos++;
962  }
963  if(pos != exponent.size())
964  {
965  if(exponent[0] == '-')
966  {
967  exponent = exponent[0] + exponent.substr(pos);
968  }
969  else
970  {
971  exponent = exponent.substr(pos);
972  }
973  }
974  else
975  {
976  exponent = "0";
977  }
978  return mantissa + " \\cdot 10^{" + exponent + "}";
979 }
980 
981 void Translator::read_column_formats(const XMLDomParserRef parser, std::list<LatexColumnFormat>& latex_column_formats,
982  size_t& max_column_size) const
983 {
984  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Read column formats");
985  parser->Exec();
986  xml_element* root = parser->get_document()->get_root_node();
987  THROW_ASSERT(root->get_name() == STR_XML_latex_table_root, "XML root node not correct: " + root->get_name());
988  if(CE_XVM(max_column_size, root))
989  {
990  LOAD_XVM(max_column_size, root);
991  }
992  const xml_node::node_list list = root->get_children();
993  xml_node::node_list::const_iterator child, child_end = list.end();
994  for(child = list.begin(); child != child_end; ++child)
995  {
996  const auto* child_element = GetPointer<const xml_element>(*child);
997  if(!child_element)
998  {
999  continue;
1000  }
1001  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Reading information about new column");
1002  THROW_ASSERT(child_element->get_name() == STR_XML_latex_table_column,
1003  "Child not known: " + child_element->get_name());
1004  LatexColumnFormat latex_column_format;
1005  const std::string column_name = child_element->get_attribute(STR_XML_latex_table_column_name)->get_value();
1006  latex_column_format.column_name = column_name;
1007  const xml_node::node_list fields = child_element->get_children();
1008  xml_node::node_list::const_iterator field, field_end = fields.end();
1009  for(field = fields.begin(); field != field_end; ++field)
1010  {
1011  const auto* field_element = GetPointer<const xml_element>(*field);
1012  if(!field_element)
1013  {
1014  continue;
1015  }
1016  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Read field " + field_element->get_name());
1017  if(field_element->get_name() == STR_XML_latex_table_alignment)
1018  {
1019  const std::string alignment = field_element->get_attribute(STR_XML_latex_table_value)->get_value();
1020  latex_column_format.column_alignment = alignment;
1021  }
1022  else if(field_element->get_name() == STR_XML_latex_table_text_format)
1023  {
1024  const std::string text_format = field_element->get_attribute(STR_XML_latex_table_value)->get_value();
1025  latex_column_format.text_format = LatexColumnFormat::get_TF(text_format);
1026  }
1027  else if(field_element->get_name() == STR_XML_latex_table_source_name)
1028  {
1029  const std::string source_name = field_element->get_attribute(STR_XML_latex_table_value)->get_value();
1030  latex_column_format.source_name = source_name;
1031  }
1032  else if(field_element->get_name() == STR_XML_latex_table_precision)
1033  {
1034  const std::string precision = field_element->get_attribute(STR_XML_latex_table_value)->get_value();
1035  latex_column_format.precision = boost::lexical_cast<std::streamsize>(precision);
1036  }
1037  else if(field_element->get_name() == STR_XML_latex_table_comparison)
1038  {
1039  const std::string values = field_element->get_attribute(STR_XML_latex_table_value)->get_value();
1040  std::vector<std::string> splitted = SplitString(values, ",");
1041  for(const auto& column : splitted)
1042  {
1043  latex_column_format.compared_columns.insert(column);
1044  }
1045  if(field_element->get_attribute(STR_XML_latex_table_operator))
1046  {
1047  const std::string comparison_operator =
1048  field_element->get_attribute(STR_XML_latex_table_operator)->get_value();
1049  latex_column_format.comparison_operator = LatexColumnFormat::get_CO(comparison_operator);
1050  }
1051  }
1052  else if(field_element->get_name() == STR_XML_latex_table_total)
1053  {
1054  const std::string total = field_element->get_attribute(STR_XML_latex_table_value)->get_value();
1055  latex_column_format.total_format = LatexColumnFormat::GetTotalFormat(total);
1056  }
1057  else
1058  {
1059  THROW_ERROR("Field " + field_element->get_name() + " not supported");
1060  }
1061  }
1062  latex_column_formats.push_back(latex_column_format);
1063  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Read information about new column");
1064  }
1066  "<--Read " + STR(latex_column_formats.size()) + " column format");
1067 }
Class to compute evaluations about high-level synthesis.
static CustomUnorderedMap< std::string, TotalFormat > string_to_TOF
Map string->enum for total format.
Definition: translator.hpp:113
#define STR_XML_latex_table_column
The node containing information about single column.
xml nodes used in file specifying latex table format
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define STR_XML_latex_table_text_format
The node containing type of text to be printed.
#define STR_XML_experimental_setup_timestamp
The node containing the timestamp of the data generation.
static CustomUnorderedMap< std::string, TextFormat > string_to_TF
Map string->enum for text format.
Definition: translator.hpp:107
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define NUM_CST_latex_table_max_column_width
The maximum width of a latex column.
File containing functions and utilities to support the printing of debug messagges.
static TextFormat get_TF(const std::string &string)
Given a string return the corresponding enum.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void merge_pa(const std::map< std::string, CustomOrderedSet< std::string >> &tags, const CustomUnorderedMap< std::string, CustomOrderedSet< std::string >> &keys, const CustomUnorderedMap< std::string, CustomUnorderedMapStable< std::string, CustomUnorderedMapStable< std::string, long double >>> &input_data, const CustomUnorderedMap< std::string, CustomUnorderedMapStable< std::string, CustomUnorderedMapStable< std::string, long double >>> &merge_data, CustomUnorderedMap< std::string, CustomUnorderedMapStable< std::string, CustomUnorderedMapStable< std::string, long double >>> &output_data) const
Merget profiling analysis.
Definition: translator.cpp:826
const std::vector< std::string > SplitString(const std::string &input, const std::string &separators)
Function which splits a string into tokens.
static void replace_underscore(std::string &ioString)
Replace &#39;_&#39; with &#39; &#39;.
Definition: translator.cpp:943
int input[SIZE]
Definition: hash.h:1
#define STR_XML_latex_table_comparison
The node containing information about column comparison.
#define STR_XML_experimental_setup_bambu_arguments
The node containing the bambu argments.
#define STR_XML_latex_table_operator
The attribute containing information about type of comparison.
int debug_level
the debug level
Definition: translator.hpp:90
void write_to_latex(std::map< std::string, CustomMap< std::string, std::string >> &results, const Parameters_FileFormat input_format, const std::string &file_name) const
Write data in latex table format.
Definition: translator.cpp:259
CustomOrderedMap< T, U > CustomMap
Definition: custom_map.hpp:167
#define COMPARISON_OPERATOR
Definition: translator.hpp:72
exceptions managed by PandA
enum { BOOST_PP_SEQ_FOR_EACH(TOF_ENUM, BOOST_PP_EMPTY, TOTAL_FORMAT) } TotalFormat
Total format.
Definition: translator.hpp:103
#define CE_XVM(variable, node)
Check existence XML Value Macro. Check if an XML attribute is present in the XML tree.
Definition: xml_helper.hpp:88
static TotalFormat GetTotalFormat(const std::string &string)
Given a string return the corresponding enum.
void read_column_formats(const XMLDomParserRef parser, std::list< LatexColumnFormat > &latex_column_formats, size_t &max_column_width) const
Read latex column format from xml.
Definition: translator.cpp:981
#define STR_XML_experimental_setup_value
The attribute containing the actual value of a node.
redefinition of map to manage ordered/unordered structures
volatile int output[DIM_Y][DIM_X]
Definition: los.h:1
void add_escape(std::string &ioString, const std::string &to_be_escaped)
Header include.
#define TEXT_FORMAT
Definition: translator.hpp:68
#define STR_XML_latex_table_column_name
The node containing information about the name of the column.
#define A
Definition: generate.c:13
void get_normalization(CustomUnorderedMap< std::string, long double > &normalization) const
Read normalization file.
Definition: translator.cpp:885
#define STR(s)
Macro which performs a lexical_cast to a string.
void line(int x1, int y1, int x2, int y2, unsigned int color)
Definition: main.c:110
Auxiliary methods for manipulating string.
#define STR_XML_experimental_setup_bambu_version
The node containing the version of bambu.
std::string get_exponential_notation(const std::string &input) const
Return a number in latex exponential notation.
Definition: translator.cpp:948
static CustomUnorderedMap< std::string, ComparisonOperator > string_to_CO
Map string->enum for comparison operator.
Definition: translator.hpp:110
const ParameterConstRef Param
the set of parameters
Definition: translator.hpp:87
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
enum { BOOST_PP_SEQ_FOR_EACH(CO_ENUM, BOOST_PP_EMPTY, COMPARISON_OPERATOR) } ComparisonOperator
Comparison operator.
Definition: translator.hpp:100
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
std::string get_name() const
Get the name of this node.
Definition: xml_node.hpp:132
#define NUM_CST_latex_table_number_precision
The default precision of the number.
std::string column_name
The name of the column.
Definition: translator.hpp:117
LatexColumnFormat()
Constructor.
Definition: translator.cpp:97
#define STR_XML_latex_table_alignment
The node containing type of alignment.
static bool Compare(const long double A, const ComparisonOperator comparator, const long double B)
Return A operator B.
Definition: translator.cpp:154
refcount< XMLDomParser > XMLDomParserRef
redefinition of set to manage ordered/unordered structures
enum { BOOST_PP_SEQ_FOR_EACH(TF_ENUM, BOOST_PP_EMPTY, TEXT_FORMAT) } TextFormat
Text format.
Definition: translator.hpp:97
XML DOM parser.
XML DOM parser.
utility function used to read files.
void write_to_csv(const std::map< std::string, CustomOrderedSet< std::string >> &tags, const CustomUnorderedMap< std::string, CustomUnorderedMapStable< std::string, CustomUnorderedMapStable< std::string, long double >>> &results, const std::string &file_name) const
Write rtl data in csv format.
#define STR_XML_latex_table_source_name
The node containing the source name of this column.
Class describing the characteristic of a column of latex table.
Definition: translator.hpp:93
This file collects some utility functions and macros.
void Exec()
Parse an XML document from a file.
std::list< xml_nodeRef > node_list
type for list of xml nodes
Definition: xml_node.hpp:90
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
Translator(const ParameterConstRef Param)
Constructor.
Definition: translator.cpp:171
#define TF_NAME(r, data, elem)
Definition: translator.cpp:76
int result[SIZE]
Definition: adpcm.c:800
#define CSV_COL_SEPARATOR
Definition: translator.cpp:68
coord_t input_data[TEST_COUNT][2]
Definition: cordic_test.cpp:44
void write_to_pa(const std::map< std::string, CustomOrderedSet< std::string >> &tags, const CustomUnorderedMap< std::string, CustomUnorderedMapStable< std::string, CustomUnorderedMapStable< std::string, long double >>> &results, const std::string &file_name) const
Write profiling analysis to pa.
Definition: translator.cpp:214
#define STR_XML_latex_table_total
The node containing information about column total.
#define CO_NAME(r, data, elem)
Definition: translator.cpp:82
#define STR_XML_experimental_setup_benchmarks
The node containing the list of benchmarks.
#define STR_XML_latex_table_root
The root node.
const char * default_latex_format_stat
Definition: translator.cpp:94
xml nodes used in file specifying experimental setup
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
xml_documentRef get_document()
Obtain the parsed document.
Parameters_FileFormat
File formats.
Definition: Parameter.hpp:261
#define STR_XML_latex_table_value
The attribute containing the value of the field.
this class is used to manage the command-line or XML options.
#define LOAD_XVM(variable, node)
LOAD XML Value Macro. Set a variable starting from an XML value. Conversion is performed if needed...
Definition: xml_helper.hpp:65
Dump information read already read from profiling file to other files.
Some macro used to interface with the XML library.
node_list const & get_children()
Obtain the list of child nodes.
Definition: xml_node.hpp:310
absl::node_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMapStable
Definition: custom_map.hpp:152
#define TOF_NAME(r, data, elem)
Definition: translator.cpp:88
#define STR_XML_latex_table_precision
The node containg information about the precision of the number.
#define B
Definition: generate.c:14
default value for latex tables
#define TOTAL_FORMAT
Definition: translator.hpp:76
static ComparisonOperator get_CO(const std::string &string)
Given a string return the corresponding enum.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:51 for PandA-2024.02 by doxygen 1.8.13