PandA-2024.02
technology_node.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  */
40 #include "technology_node.hpp"
41 #include "Parameter.hpp"
42 #include "area_info.hpp"
43 #include "config_HAVE_CIRCUIT_BUILT.hpp"
44 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
45 #include "exceptions.hpp"
46 #include "library_manager.hpp"
47 #include "polixml.hpp"
48 #include "string_manipulation.hpp"
49 #include "structural_manager.hpp"
50 #include "structural_objects.hpp"
51 #include "technology_manager.hpp"
52 #include "time_info.hpp"
53 #include "xml_helper.hpp"
54 #include <algorithm>
55 #include <list>
56 #include <utility>
57 
59 
61 
63 
64 operation::operation() : commutative(false), bounded(true), primary_inputs_registered(false)
65 {
66 }
67 
68 operation::~operation() = default;
69 
70 void operation::xload(const xml_element* Enode, const technology_nodeRef fu, const ParameterConstRef Param)
71 {
72  THROW_ASSERT(CE_XVM(operation_name, Enode), "An operation must have a name");
74  LOAD_XVM(operation_name, Enode);
76  if(CE_XVM(commutative, Enode))
77  {
78  LOAD_XVM(commutative, Enode);
79  }
80 
81  if(CE_XVM(bounded, Enode))
82  {
83  LOAD_XVM(bounded, Enode);
84  }
85 
87  {
89  }
90 
92  if(CE_XVM(supported_types, Enode))
93  {
94  std::string supported_types_string;
95  LOAD_XVFM(supported_types_string, Enode, supported_types);
96  std::vector<std::string> types = SplitString(supported_types_string, "|");
97  for(const auto& type : types)
98  {
99  if(type == "")
100  {
101  THROW_ERROR("wrong XML syntax for supported_types attribute: null type description in \"" +
102  supported_types_string + "\" [" + operation_name + "]");
103  }
104  std::string type_name;
105  std::vector<unsigned int> type_precs;
106  std::vector<std::string> type_name_to_precs = SplitString(type, ":");
107  if(type_name_to_precs.size() != 2)
108  {
109  THROW_ERROR("wrong XML syntax for supported_types attribute around \":\" \"" + type + "\" [" +
110  operation_name + "]");
111  }
112  type_name = type_name_to_precs[0];
113  if(type_name == "")
114  {
115  THROW_ERROR("wrong XML syntax for supported_types attribute: missing the supported type - \"" + type +
116  "\" [" + operation_name + "]");
117  }
118 
119  if(type_name_to_precs[1] != "*")
120  {
121  std::vector<std::string> precs = SplitString(type_name_to_precs[1], ",");
122  ;
123  for(auto single_prec = precs.begin(); single_prec != precs.end() && *single_prec != ""; ++single_prec)
124  {
125  auto type_uint = static_cast<unsigned>(std::stoul(*single_prec));
126  type_precs.push_back(type_uint);
127  }
128  }
129  supported_types.insert(std::make_pair(type_name, type_precs));
130  }
131  }
132  if(CE_XVM(pipe_parameters, Enode))
133  {
134  LOAD_XVM(pipe_parameters, Enode);
135  }
136  if(CE_XVM(portsize_parameters, Enode))
137  {
139  }
140 
142  time_m = time_info::factory(Param);
143  double execution_time = time_info::execution_time_DEFAULT;
144  auto initiation_time = from_strongtype_cast<unsigned int>(time_info::initiation_time_DEFAULT);
145  unsigned int cycles = time_info::cycles_time_DEFAULT;
146  double stage_period = time_info::stage_period_DEFAULT;
147  if(CE_XVM(execution_time, Enode))
148  {
149  LOAD_XVM(execution_time, Enode);
150  }
151  if(CE_XVM(initiation_time, Enode))
152  {
153  LOAD_XVM(initiation_time, Enode);
154  }
155  if(CE_XVM(cycles, Enode))
156  {
157  LOAD_XVM(cycles, Enode);
158  }
159  if(CE_XVM(stage_period, Enode))
160  {
161  LOAD_XVM(stage_period, Enode);
162  }
163  bool synthesis_dependent = false;
164  if(CE_XVM(synthesis_dependent, Enode))
165  {
166  LOAD_XVM(synthesis_dependent, Enode);
167  }
168  if(synthesis_dependent && cycles)
169  {
170  double clock_period = GetPointer<functional_unit>(fu)->get_clock_period();
171  if(clock_period == 0.0)
172  {
173  THROW_ERROR("Missing clock period for operation \"" + operation_name + "\" in unit " + fu->get_name());
174  }
175  double clock_period_resource_fraction = GetPointer<functional_unit>(fu)->get_clock_period_resource_fraction();
176  execution_time = cycles * clock_period * clock_period_resource_fraction;
177  }
178  time_m->set_execution_time(execution_time, cycles);
179  const ControlStep ii(initiation_time);
181  time_m->set_synthesis_dependent(synthesis_dependent);
182  time_m->set_stage_period(stage_period);
183  const xml_node::node_list list_int = Enode->get_children();
184  for(const auto& iter_int : list_int)
185  {
186  const auto* EnodeC = GetPointer<const xml_element>(iter_int);
187  if(!EnodeC)
188  {
189  continue;
190  }
191  }
192 }
193 
195 {
196  xml_element* Enode = rootnode->add_child_element(get_kind_text());
197 
199  WRITE_XVM(operation_name, Enode);
201  if(commutative)
202  {
203  WRITE_XVM(commutative, Enode);
204  }
205  if(!bounded)
206  {
207  WRITE_XVM(bounded, Enode);
208  }
209 
211  auto it_end = supported_types.end();
212  auto it_begin = supported_types.begin();
213  std::string supported_types_string;
214  for(auto it = it_begin; it != it_end; ++it)
215  {
216  if(it != it_begin)
217  {
218  supported_types_string += "|";
219  }
220  supported_types_string += it->first + ":";
221  if(it->second.size() == 0)
222  {
223  supported_types_string += "*";
224  }
225  else
226  {
227  auto prec_end = it->second.end();
228  auto prec_begin = it->second.begin();
229  for(auto prec_it = prec_begin; prec_it != prec_end; ++prec_it)
230  {
231  if(prec_it != prec_begin)
232  {
233  supported_types_string += ",";
234  }
235  supported_types_string += STR(*prec_it);
236  }
237  }
238  }
239  if(supported_types_string != "")
240  {
241  WRITE_XNVM(supported_types, supported_types_string, Enode);
242  }
243  if(pipe_parameters != "")
244  {
245  WRITE_XVM(pipe_parameters, Enode);
246  }
247  if(portsize_parameters != "")
248  {
250  }
251 
253  if(time_m)
254  {
256  {
257  unsigned int cycles = time_m->get_cycles();
258  WRITE_XVM(cycles, Enode);
259  }
261  {
262  double execution_time = time_m->get_execution_time();
263  WRITE_XVM(execution_time, Enode);
264  }
265 
267  {
268  auto initiation_time = from_strongtype_cast<unsigned int>(time_m->get_initiation_time());
269  WRITE_XVM(initiation_time, Enode);
270  }
272  {
273  double stage_period = time_m->get_stage_period();
274  WRITE_XVM(stage_period, Enode);
275  }
277  {
278  bool synthesis_dependent = time_m->get_synthesis_dependent();
279  WRITE_XVM(synthesis_dependent, Enode);
280  }
282  {
284  }
285  }
286 }
287 
288 void operation::print(std::ostream& os) const
289 {
290  os << " [OP: " << operation_name << " " << (time_m ? STR(time_m->get_execution_time()) : "(n.a.)") << " "
291  << (time_m ? STR(time_m->get_initiation_time()) : "(n.a.)") << " ";
292  os << (commutative ? " commutative" : " non-commutative");
293  os << (bounded ? " bounded" : " unbounded") << "]";
294 }
295 
296 bool operation::is_type_supported(const std::string& type_name) const
297 {
299  return supported_types.empty() || supported_types.count(type_name);
300 }
301 
302 bool operation::is_type_supported(const std::string& type_name, unsigned long long type_prec) const
303 {
304  if(!supported_types.empty())
305  {
306  if(!is_type_supported(type_name))
307  {
308  return false;
309  }
311  auto supported_type = supported_types.find(type_name);
312  if(!supported_type->second.empty() && std::find(supported_type->second.begin(), supported_type->second.end(),
313  type_prec) == supported_type->second.end())
314  {
315  return false;
316  }
317  }
318  return true;
319 }
320 
321 bool operation::is_type_supported(const std::string& type_name, const std::vector<unsigned long long>& type_prec,
322  const std::vector<unsigned long long>& /*type_n_element*/) const
323 {
324  const auto max_prec = type_prec.empty() ? 0 : *max_element(type_prec.begin(), type_prec.end());
325  return is_type_supported(type_name, max_prec);
326 }
327 
329 {
330  std::string result;
331  auto supported_type_it_end = supported_types.end();
332  for(auto supported_type_it = supported_types.begin(); supported_type_it != supported_type_it_end;
333  ++supported_type_it)
334  {
335  if(supported_type_it != supported_types.begin())
336  {
337  result += "|";
338  }
339  result += supported_type_it->first;
340  }
341  return result;
342 }
343 
345  : logical_type(UNKNOWN), clock_period(0), clock_period_resource_fraction(1), characterization_timestamp()
346 {
347 }
348 
349 functional_unit::functional_unit(const xml_nodeRef _XML_description)
351  clock_period(0),
353  XML_description(_XML_description),
355 {
356 }
357 
359 
360 void functional_unit::set_clock_period(double _clock_period)
361 {
362  THROW_ASSERT(_clock_period > 0.0, "Clock period must be greater than zero");
363  if(std::find(ordered_attributes.begin(), ordered_attributes.end(), "clock_period") == ordered_attributes.end())
364  {
365  ordered_attributes.push_back("clock_period");
366  }
367  std::vector<attributeRef> content;
368  content.push_back(attributeRef(new attribute("float64", STR(_clock_period))));
369  attributes["clock_period"] = attributeRef(new attribute(content));
370  clock_period = _clock_period;
371 }
372 
373 void functional_unit::set_clock_period_resource_fraction(double _clock_period_resource_fraction)
374 {
375  if(std::find(ordered_attributes.begin(), ordered_attributes.end(), "clock_period_resource_fraction") ==
376  ordered_attributes.end())
377  {
378  ordered_attributes.push_back("clock_period_resource_fraction");
379  }
380  std::vector<attributeRef> content;
381  content.push_back(attributeRef(new attribute("float64", STR(_clock_period_resource_fraction))));
382  attributes["clock_period_resource_fraction"] = attributeRef(new attribute(content));
383  clock_period_resource_fraction = _clock_period_resource_fraction;
384 }
385 
386 void functional_unit::print(std::ostream& os) const
387 {
388  PP(os, "FU:\n[");
389  PP(os, functional_unit_name + "\n");
390  if(memory_type != "")
391  {
392  PP(os, "memory_type: " + memory_type + "\n");
393  }
394  if(list_of_operation.size() > 0)
395  {
396  std::copy(list_of_operation.begin(), list_of_operation.end(),
397  std::ostream_iterator<const technology_nodeRef>(os, ""));
398  PP(os, "\n");
399  }
400  if(area_m)
401  {
402  PP(os, "A: " + std::to_string(area_m->get_area_value()) + "\n");
403  }
404 #if HAVE_CIRCUIT_BUILT
405  if(CM)
406  {
407  CM->print(os);
408  }
409 #endif
410  PP(os, "]\n");
411 }
412 
413 technology_nodeRef functional_unit::get_operation(const std::string& op_name) const
414 {
415  auto i = op_name_to_op.find(op_name);
416  if(i == op_name_to_op.end())
417  {
418  return technology_nodeRef();
419  }
420  return i->second;
421 }
422 
424 {
425 #ifndef NDEBUG
426  auto debug_level = Param->get_class_debug_level(GET_CLASS(*this));
427 #endif
428 #if HAVE_CIRCUIT_BUILT
430 #endif
431 
433  const xml_node::node_list list_int = Enode->get_children();
434  for(const auto& iter_int : list_int)
435  {
436  const auto* EnodeC = GetPointer<const xml_element>(iter_int);
437  if(!EnodeC)
438  {
439  continue;
440  }
441  if(EnodeC->get_name() == "name")
442  {
443  const xml_text_node* text = EnodeC->get_child_text();
444  if(!text)
445  {
446  THROW_ERROR("name is missing for " + EnodeC->get_name());
447  }
449  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Started reading the module: " + functional_unit_name);
450  }
451  else if(EnodeC->get_name() == "template")
452  {
453  /*
454  * Getting functional unit template name and parameters. It
455  * will be responsibility of higher layer to retrieve a
456  * reference to the template looking in the library.
457  */
458  fu_template_name = EnodeC->get_attribute("name")->get_value();
459  fu_template_parameters = EnodeC->get_attribute("parameter")->get_value();
460  }
461  else if(EnodeC->get_name() == GET_CLASS_NAME(characterizing_constant_value))
462  {
463  /*
464  * Getting the constant value used to characterize the
465  * specialization of a functional unit template.
466  */
467  const xml_text_node* text = EnodeC->get_child_text();
468  if(!text)
469  {
470  THROW_ERROR("characterizing_constant_value is missing for " + EnodeC->get_name());
471  }
472  if(text->get_content() == "")
473  {
474  THROW_ERROR("characterizing_constant_value is missing for " + EnodeC->get_name());
475  }
477  }
478  else if(EnodeC->get_name() == GET_CLASS_NAME(memory_type))
479  {
480  /*
481  * Getting the memory type the functional unit is compliant with.
482  */
483  const xml_text_node* text = EnodeC->get_child_text();
484  if(!text)
485  {
486  THROW_ERROR("memory_type is missing for " + EnodeC->get_name());
487  }
488  if(text->get_content() == "")
489  {
490  THROW_ERROR("memory_type is missing for " + EnodeC->get_name());
491  }
492  memory_type = text->get_content();
493  }
494  else if(EnodeC->get_name() == GET_CLASS_NAME(channels_type))
495  {
496  /*
497  * Getting the channels type the functional unit is compliant with.
498  */
499  const xml_text_node* text = EnodeC->get_child_text();
500  if(!text)
501  {
502  THROW_ERROR("channels_type is missing for " + EnodeC->get_name());
503  }
504  if(text->get_content() == "")
505  {
506  THROW_ERROR("channels_type is missing for " + EnodeC->get_name());
507  }
508  channels_type = text->get_content();
509  }
510  else if(EnodeC->get_name() == GET_CLASS_NAME(memory_ctrl_type))
511  {
512  /*
513  * Getting the memory controller type the functional unit is compliant with.
514  */
515  const xml_text_node* text = EnodeC->get_child_text();
516  if(!text)
517  {
518  THROW_ERROR("memory_ctrl_type is missing for " + EnodeC->get_name());
519  }
520  if(text->get_content() == "")
521  {
522  THROW_ERROR("memory_ctrl_type is missing for " + EnodeC->get_name());
523  }
524  memory_ctrl_type = text->get_content();
525  }
526  else if(EnodeC->get_name() == GET_CLASS_NAME(bram_load_latency))
527  {
528  /*
529  * Getting the bram load latency the functional unit is compliant with.
530  */
531  const xml_text_node* text = EnodeC->get_child_text();
532  if(!text)
533  {
534  THROW_ERROR("bram_load_latency is missing for " + EnodeC->get_name());
535  }
536  if(text->get_content() == "")
537  {
538  THROW_ERROR("bram_load_latency is missing for " + EnodeC->get_name());
539  }
540  bram_load_latency = text->get_content();
541  }
542  else if(EnodeC->get_name() == GET_CLASS_NAME(component_timing_alias))
543  {
544  /*
545  * Getting the bram load latency the functional unit is compliant with.
546  */
547  const xml_text_node* text = EnodeC->get_child_text();
548  if(!text)
549  {
550  THROW_ERROR("component_timing_alias is missing for " + EnodeC->get_name());
551  }
552  if(text->get_content() == "")
553  {
554  THROW_ERROR("component_timing_alias is missing for " + EnodeC->get_name());
555  }
557  }
558  else if(EnodeC->get_name() == GET_CLASS_NAME(specialized))
559  {
560  }
561  else if(EnodeC->get_name() == GET_CLASS_NAME(no_constant_characterization))
562  {
563  }
564  else if(EnodeC->get_name() == "operation")
565  {
567  }
568  else if(EnodeC->get_name() == "characterization_timestamp")
569  {
570  const xml_text_node* text = EnodeC->get_child_text();
571  if(!text)
572  {
573  THROW_ERROR("Timestamp is missing for " + EnodeC->get_name());
574  }
575  if(text->get_content() == "")
576  {
577  THROW_ERROR("Timestamp is missing for " + EnodeC->get_name());
578  }
580  }
581 #if HAVE_CIRCUIT_BUILT
582  else if(EnodeC->get_name() == "circuit")
583  {
584  if(!CM)
585  {
586  CM = structural_managerRef(new structural_manager(Param));
587  structural_type_descriptorRef build_type =
589  CM->set_top_info(functional_unit_name, build_type);
590  }
591  // top must be a component_o
592  const xml_node::node_list listC = EnodeC->get_children();
593  for(const auto& iterC : listC)
594  {
595  const auto* EnodeCC = GetPointer<const xml_element>(iterC);
596  if(!EnodeCC)
597  {
598  continue;
599  }
600  if(EnodeCC->get_name() == GET_CLASS_NAME(component_o))
601  {
602  CM->get_circ()->xload(EnodeCC, CM->get_circ(), CM);
603  }
604  }
605  }
606 #endif
607  else if(EnodeC->get_name() == "attribute")
608  {
610  if(attributes.find("clock_period") != attributes.end())
611  {
612  clock_period = attributes["clock_period"]->get_content<double>();
613  }
614  if(attributes.find("clock_period_resource_fraction") != attributes.end())
615  {
616  clock_period_resource_fraction = attributes["clock_period_resource_fraction"]->get_content<double>();
617  }
618  }
619  else
620  {
621  THROW_ERROR("functional_unit - not yet supported: " + EnodeC->get_name());
622  }
623  }
624 
625  for(const auto& iter_int : list_int)
626  {
627  const auto* EnodeC = GetPointer<const xml_element>(iter_int);
628  if(!EnodeC)
629  {
630  continue;
631  }
632  if(EnodeC->get_name() == "operation")
633  {
635  op_curr->xload(EnodeC, fu, Param);
636  add(op_curr);
637  }
638  }
639 
640  if(get_operations_num() == 0)
641  {
643  GetPointer<operation>(op_curr)->operation_name = functional_unit_name;
644  add(op_curr);
645  }
646 
647  area_m = area_info::factory(Param);
648  if(attributes.find("area") != attributes.end())
649  {
650  area_m->set_area_value(attributes["area"]->get_content<double>());
651  }
652  if(attributes.find("REGISTERS") != attributes.end())
653  {
654  area_m->set_resource_value(area_info::REGISTERS, attributes["REGISTERS"]->get_content<double>());
655  }
656  if(attributes.find("SLICE_LUTS") != attributes.end())
657  {
658  area_m->set_resource_value(area_info::SLICE_LUTS, attributes["SLICE_LUTS"]->get_content<double>());
659  }
660  if(attributes.find("SLICE") != attributes.end())
661  {
662  area_m->set_resource_value(area_info::SLICE, attributes["SLICE"]->get_content<double>());
663  }
664  if(attributes.find("LUT_FF_PAIRS") != attributes.end())
665  {
666  area_m->set_resource_value(area_info::LUT_FF_PAIRS, attributes["LUT_FF_PAIRS"]->get_content<double>());
667  }
668  if(attributes.find("DSP") != attributes.end())
669  {
670  area_m->set_resource_value(area_info::DSP, attributes["DSP"]->get_content<double>());
671  }
672  if(attributes.find("BRAM") != attributes.end())
673  {
674  area_m->set_resource_value(area_info::BRAM, attributes["BRAM"]->get_content<double>());
675  }
676  if(attributes.find("DRAM") != attributes.end())
677  {
678  area_m->set_resource_value(area_info::DRAM, attributes["DRAM"]->get_content<double>());
679  }
680 }
681 
683 {
684  xml_element* xml_name = rootnode->add_child_element("name");
687 
689  if(!list_of_operation.size())
690  {
692  GetPointer<operation>(curr_op)->operation_name = functional_unit_name;
693  add(curr_op);
694  }
695 
697  if(area_m)
698  {
699  double area_value = area_m->get_area_value();
700  if(std::find(ordered_attributes.begin(), ordered_attributes.end(), "area") == ordered_attributes.end())
701  {
702  ordered_attributes.push_back("area");
703  }
704  attributes["area"] = attributeRef(new attribute(attribute::FLOAT64, std::to_string(area_value)));
705  if(area_m)
706  {
707  if(area_m->get_resource_value(area_info::REGISTERS) != 0.0)
708  {
709  attributes["REGISTERS"] = attributeRef(
710  new attribute(attribute::FLOAT64, std::to_string(area_m->get_resource_value(area_info::REGISTERS))));
711  }
712  if(area_m->get_resource_value(area_info::SLICE_LUTS) != 0.0)
713  {
714  attributes["SLICE_LUTS"] = attributeRef(
715  new attribute(attribute::FLOAT64, std::to_string(area_m->get_resource_value(area_info::SLICE_LUTS))));
716  }
717  if(area_m->get_resource_value(area_info::LUT_FF_PAIRS) != 0.0)
718  {
719  attributes["LUT_FF_PAIRS"] = attributeRef(
720  new attribute(attribute::FLOAT64, std::to_string(area_m->get_resource_value(area_info::LUT_FF_PAIRS))));
721  }
722  if(area_m->get_resource_value(area_info::DSP) != 0.0)
723  {
724  attributes["DSP"] = attributeRef(
725  new attribute(attribute::FLOAT64, std::to_string(area_m->get_resource_value(area_info::DSP))));
726  }
727  if(area_m->get_resource_value(area_info::BRAM) != 0.0)
728  {
729  attributes["BRAM"] = attributeRef(
730  new attribute(attribute::FLOAT64, std::to_string(area_m->get_resource_value(area_info::BRAM))));
731  }
732  if(area_m->get_resource_value(area_info::DRAM) != 0.0)
733  {
734  attributes["DRAM"] = attributeRef(
735  new attribute(attribute::FLOAT64, std::to_string(area_m->get_resource_value(area_info::DRAM))));
736  }
737  }
738  }
739 
741  for(const auto& ordered_attribute : ordered_attributes)
742  {
743  const attributeRef attr = attributes[ordered_attribute];
744  attr->xwrite(rootnode, ordered_attribute);
745  }
746 
748  if(fu_template_name != "" && fu_template_parameters != "")
749  {
750  xml_element* template_el = rootnode->add_child_element("template");
751  WRITE_XNVM2("name", fu_template_name, template_el);
752  WRITE_XNVM2("parameter", fu_template_parameters, template_el);
753 
755  {
758  }
759  }
760 
761  if(memory_type != "")
762  {
763  xml_element* constant_el = rootnode->add_child_element(GET_CLASS_NAME(memory_type));
764  constant_el->add_child_text(memory_type);
765  }
766  if(channels_type != "")
767  {
768  xml_element* constant_el = rootnode->add_child_element(GET_CLASS_NAME(channels_type));
769  constant_el->add_child_text(channels_type);
770  }
771  if(memory_ctrl_type != "")
772  {
774  constant_el->add_child_text(memory_ctrl_type);
775  }
776  if(bram_load_latency != "")
777  {
778  xml_element* xml_specialized = rootnode->add_child_element(GET_CLASS_NAME(bram_load_latency));
779  xml_specialized->add_child_text(bram_load_latency);
780  }
781  if(component_timing_alias != "")
782  {
784  xml_specialized->add_child_text(component_timing_alias);
785  }
786  auto xml_characterization_timestamp = rootnode->add_child_element("characterization_timestamp");
787  xml_characterization_timestamp->add_child_text(STR(characterization_timestamp));
789  auto it_end = list_of_operation.end();
790  for(auto it = list_of_operation.begin(); it != it_end; ++it)
791  {
792  GetPointer<operation>(*it)->xwrite(rootnode, tn, Param);
793  }
794 
796 #if HAVE_CIRCUIT_BUILT
797  if(CM && CM->get_circ())
798  {
799  CM->xwrite(rootnode, tn);
800  }
801 #endif
802 }
803 
805 {
806 }
807 
808 functional_unit_template::functional_unit_template(const xml_nodeRef XML_description)
809  : FU(new functional_unit(XML_description)), no_constant_characterization(false)
810 {
811 }
812 
814  const ParameterConstRef Param)
815 {
816  const xml_node::node_list list_int = Enode->get_children();
817  for(const auto& iter_int : list_int)
818  {
819  const auto* EnodeC = GetPointer<const xml_element>(iter_int);
820  if(!EnodeC)
821  {
822  continue;
823  }
824  if(EnodeC->get_name() == GET_CLASS_NAME(specialized))
825  {
826  const xml_text_node* text = EnodeC->get_child_text();
827  if(!text)
828  {
829  THROW_ERROR("specialization identifier is missing for " + EnodeC->get_name());
830  }
831  specialized = text->get_content();
832  xml_node::convert_escaped(specialized);
833  }
834  else if(EnodeC->get_name() == GET_CLASS_NAME(characterizing_constant_value))
835  {
836  const xml_text_node* text = EnodeC->get_child_text();
837  if(!text)
838  {
839  THROW_ERROR("specialization identifier is missing for " + EnodeC->get_name());
840  }
842  xml_node::convert_escaped(characterizing_constant_value);
843  }
844  else if(EnodeC->get_name() == GET_CLASS_NAME(memory_type))
845  {
846  const xml_text_node* text = EnodeC->get_child_text();
847  if(!text)
848  {
849  THROW_ERROR("specialization identifier is missing for " + EnodeC->get_name());
850  }
851  memory_type = text->get_content();
852  xml_node::convert_escaped(memory_type);
853  }
854  else if(EnodeC->get_name() == GET_CLASS_NAME(channels_type))
855  {
856  const xml_text_node* text = EnodeC->get_child_text();
857  if(!text)
858  {
859  THROW_ERROR("specialization identifier is missing for " + EnodeC->get_name());
860  }
861  channels_type = text->get_content();
862  xml_node::convert_escaped(channels_type);
863  }
864  else if(EnodeC->get_name() == GET_CLASS_NAME(memory_ctrl_type))
865  {
866  const xml_text_node* text = EnodeC->get_child_text();
867  if(!text)
868  {
869  THROW_ERROR("specialization identifier is missing for " + EnodeC->get_name());
870  }
871  memory_ctrl_type = text->get_content();
872  xml_node::convert_escaped(memory_ctrl_type);
873  }
874  else if(EnodeC->get_name() == GET_CLASS_NAME(bram_load_latency))
875  {
876  const xml_text_node* text = EnodeC->get_child_text();
877  if(!text)
878  {
879  THROW_ERROR("specialization identifier is missing for " + EnodeC->get_name());
880  }
881  bram_load_latency = text->get_content();
882  xml_node::convert_escaped(bram_load_latency);
883  }
884  else if(EnodeC->get_name() == GET_CLASS_NAME(no_constant_characterization))
885  {
887  }
888  }
889  FU->xload(Enode, tnd, Param);
890 }
891 
893  const ParameterConstRef Param)
894 {
895  if(specialized != "")
896  {
897  xml_element* xml_specialized = rootnode->add_child_element("specialized");
898  xml_specialized->add_child_text(specialized);
899  }
901  {
904  }
905  if(memory_type != "")
906  {
907  xml_element* xml_specialized = rootnode->add_child_element(GET_CLASS_NAME(memory_type));
908  xml_specialized->add_child_text(memory_type);
909  }
910  if(channels_type != "")
911  {
912  xml_element* xml_specialized = rootnode->add_child_element(GET_CLASS_NAME(channels_type));
913  xml_specialized->add_child_text(channels_type);
914  }
915  if(memory_ctrl_type != "")
916  {
917  xml_element* xml_specialized = rootnode->add_child_element(GET_CLASS_NAME(memory_ctrl_type));
918  xml_specialized->add_child_text(memory_ctrl_type);
919  }
920  if(bram_load_latency != "")
921  {
922  xml_element* xml_specialized = rootnode->add_child_element(GET_CLASS_NAME(bram_load_latency));
923  xml_specialized->add_child_text(bram_load_latency);
924  }
926  {
928  }
929  FU->xwrite(rootnode, tnd, Param);
930 }
931 
932 void functional_unit_template::print(std::ostream& os) const
933 {
934  FU->print(os);
935 }
virtual std::string get_kind_text() const =0
Virtual function used to get the string name of a technology_node instance.
void set_clock_period(double _clock_period)
Sets the clock period adopted for the synthesis (0 means that it has been generated with unconstraine...
std::map< std::string, std::vector< unsigned int > > supported_types
supported types and precision of the operation, in form (name, list_of_prec).
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
void add(const technology_nodeRef &curr)
Add the given operation to the current functional_unit.
Collect information about resource area.
std::string bram_load_latency
Specify the bram load latency the functional unit is compliant with.
refcount< structural_type_descriptor > structural_type_descriptorRef
RefCount type definition of the structural_type_descriptor class structure.
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
Structure representing the most relevant information about the type of a structural object...
refcount< attribute > attributeRef
#define GET_CLASS(obj)
Macro returning the actual type of an object.
std::string pipe_parameters
comma separated string with the parameter for the different implementation of the pipeline...
std::string operation_name
name of the operation mappen on a given functional unit.
Dest from_strongtype_cast(Source source)
std::string fu_template_parameters
Template parameters.
std::vector< std::string > ordered_attributes
list of attributes associated to the components
const std::vector< std::string > SplitString(const std::string &input, const std::string &separators)
Function which splits a string into tokens.
std::string fu_template_name
Name of the template.
operation_vec list_of_operation
At each functional unit can be associate several operations with different performances.
void print(std::ostream &os) const override
function that prints the class functional_unit.
void set_execution_time(double execution_time, unsigned int cycles=time_info::cycles_time_DEFAULT)
Definition: time_info.cpp:64
std::string functional_unit_name
name of the functional unit.
std::map< std::string, technology_nodeRef > op_name_to_op
Redefinition of get_kind_text()
This class manages the circuit structures.
virtual void print(std::ostream &os) const =0
Virtual function that prints the class.
exceptions managed by PandA
double clock_period_resource_fraction
clock period resource fraction
~operation() override
Destructor.
void print(std::ostream &os) const override
function that prints the class operation.
std::string bram_load_latency
Specify the bram load latency the functional unit is compliant with.
bool get_synthesis_dependent() const
Definition: time_info.cpp:75
bool primary_inputs_registered
true when the primary input of the functional unit are registered
Collect information about resource performance.
time_infoRef time_m
class representing the timing information associated with this operation
std::string channels_type
Specify the type of the channel the functional unit is compliant with.
#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
void xwrite(xml_element *rootnode, const technology_nodeRef tn, const ParameterConstRef Param) override
Add a functional unit to an xml tree.
ControlStep get_initiation_time() const
Definition: time_info.cpp:90
void xload(const xml_element *Enode, const technology_nodeRef fu, const ParameterConstRef Param) override
Load a operation node starting from an xml file.
std::string get_type_supported_string() const
Returns the supported type as a string.
xml_text_node * add_child_text(const std::string &content)
Append a new text node.
Definition: xml_node.cpp:68
void set_resource_value(value_t val, double num)
Definition: area_info.cpp:67
Class specification of the manager of the technology library data structures.
std::string characterizing_constant_value
Value used during the characterization of this instance.
bool no_constant_characterization
The template will not consider constants connected to the inputs during the module characterization...
This class specifies the characteristic of a particular functional unit.
std::string portsize_parameters
comma separed string with the parameter for different portsize values.
functional_unit()
Constructor.
TimeStamp characterization_timestamp
The timestamp of the characterization of this functional unit.
std::map< std::string, attributeRef > attributes
map between the attribute keys and the corresponding values
std::string memory_type
Specify the type of memory the functional unit is compliant with.
void set_stage_period(double st_per)
Definition: time_info.cpp:105
std::string channels_type
Specify the type of the channel the functional unit is compliant with.
refcount< technology_node > technology_nodeRef
refcount definition of the class
unsigned int get_cycles() const
Definition: time_info.cpp:95
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
void set_initiation_time(const ControlStep _initiation_time)
Definition: time_info.cpp:85
void xload(const xml_element *node, const technology_nodeRef fu, const ParameterConstRef Param) override
Load a functional unit starting from an xml file.
xml_nodeRef XML_description
pointer to the XML description of the cell
double get_resource_value(value_t val) const
Definition: area_info.cpp:77
technology_node()
Constructor.
This class specifies the characteristic of a particular operation working on a given functional unit...
area_infoRef area_m
This variable stores the resource information of the component.
static const double stage_period_DEFAULT
zero means that the operation last in ceil(execution_time/clock_period)
Definition: time_info.hpp:106
Class specification of the data structures used to manage technology information. ...
double get_area_value() const
Return the nominal value for the area of the component.
Definition: area_info.cpp:57
void xwrite(xml_element *rootnode, const technology_nodeRef tn, const ParameterConstRef Param) override
Add a operation node to an xml tree.
#define LOAD_XVFM(variable, node, field)
LOAD XML Value for field Macro. Set a variable starting from an XML value. Conversion is performed if...
Definition: xml_helper.hpp:69
std::string specialized
when non empty it defines with respect what the functional unit template has been specialized ...
static const unsigned int cycles_time_DEFAULT
zero means that the operation is not pipelined
Definition: time_info.hpp:105
double get_execution_time() const
Definition: time_info.cpp:80
bool bounded
flag to determine if the operation is bounded or not
size_t get_operations_num() const
Return the number of the operations that the functional unit can handle.
std::string characterizing_constant_value
Value used during the characterization of templates.
struct definition of the field attr on function_decl, field_decl, var_decl tree node.
Definition: tree_node.hpp:774
bool is_type_supported(const std::string &type_name) const
Checks if the specified type name is supported.
#define GET_CLASS_NAME(meth)
Macro returning the name of a class.
Definition: utility.hpp:102
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
std::string memory_ctrl_type
Specify the type of memory controller the functional unit is compliant with.
refcount< structural_manager > structural_managerRef
RefCount type definition of the structural_manager class structure.
static simple_indent PP
pretty print functor object used by all print members to indent the output of the print function...
int result[SIZE]
Definition: adpcm.c:800
static const double execution_time_DEFAULT
Definition: time_info.hpp:103
static const ControlStep initiation_time_DEFAULT
Definition: time_info.hpp:104
#define WRITE_XNVM2(name, value, node)
WRITE XML Name Value Macro second version. Insert a value in an XML tree given the name of the attrib...
Definition: xml_helper.hpp:58
bool commutative
property of commutativity
virtual ~technology_node()
Destructor.
virtual void xwrite(xml_element *rootnode, const technology_nodeRef tn, const ParameterConstRef Param)=0
Add a technology_node to an xml tree.
Very simple pretty printer functor.
~functional_unit() override
Destructor.
This class describes all classes used to represent a structural object.
functional_unit_template()
Constructor.
static area_infoRef factory(const ParameterConstRef &Param)
Factory method.
Definition: area_info.cpp:52
#define WRITE_XNVM(variable, value, node)
WRITE XML Name Value Macro.
Definition: xml_helper.hpp:55
technology_nodeRef get_operation(const std::string &op_name) const
This method returns the operationRef from its name if the functional unit contains an operation of ty...
std::string memory_ctrl_type
Specify the type of memory controller the functional unit is compliant with.
virtual const std::string & get_name() const =0
Return the name of the technology node.
#define WRITE_XVM(variable, node)
WRITE XML Value Macro. Insert a value in an XML tree.
Definition: xml_helper.hpp:51
void set_area_value(const double &_area_)
Set the nominal value for the area of the component.
Definition: area_info.cpp:62
std::string get_content() const
Get the text of this content node.
std::string memory_type
Specify the type of memory the functional unit is compliant with.
void xload(const xml_element *Enode, const technology_nodeRef tnd, const ParameterConstRef Param) override
Load a functional unit starting from an xml file.
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
void set_clock_period_resource_fraction(double _clock_period_resource_fraction)
Sets the clock period resource fraction adopted for the synthesis.
The type used for timestamp.
Definition: utility.hpp:280
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
Class implementation of the structural_manager.
This class describes a generic component.
void xwrite(xml_element *rootnode, const technology_nodeRef tn, const ParameterConstRef Param) override
Add a functional unit to an xml tree.
void print(std::ostream &os) const override
function that prints the class functional_unit.
Class specification of the manager for each library.
int debug_level
The debug level.
double get_stage_period() const
Definition: time_info.cpp:100
operation()
Constructor.
virtual void xload(const xml_element *Enode, const technology_nodeRef owner, const ParameterConstRef Param)=0
Load a technology_node starting from an xml file.
static void convert_escaped(std::string &ioString)
Convert escaped characters.
Definition: xml_node.hpp:197
static void xload(const xml_element *EnodeC, std::vector< std::string > &ordered_attributes, std::map< std::string, attributeRef > &attributes)
technology_nodeRef FU
Functional Unit.
std::string component_timing_alias
Specify that the functional unit has the same timing per operation it has the one specified by this f...
static time_infoRef factory(const ParameterConstRef Param)
Definition: time_info.cpp:110
xml_element * add_child_element(const std::string &name)
Add a child element to this node.
Definition: xml_node.cpp:54
type_t logical_type
return the logical type of the cell
double clock_period
clock period adopted for the synthesis (in ns)
void set_synthesis_dependent(bool value)
Definition: time_info.cpp:70
#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:55 for PandA-2024.02 by doxygen 1.8.13