PandA-2024.02
RTL_characterization.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 "RTL_characterization.hpp"
45 
47 #include "config_HAVE_FLOPOCO.hpp"
48 
49 #include "BackendFlow.hpp"
50 #include "HDL_manager.hpp"
51 #include "NP_functionality.hpp"
52 #include "Parameter.hpp"
54 #include "area_info.hpp"
55 #include "design_flow_graph.hpp"
56 #include "design_flow_manager.hpp"
57 #include "fileIO.hpp"
58 #include "generic_device.hpp"
59 #include "language_writer.hpp"
60 #include "library_manager.hpp"
61 #include "op_graph.hpp"
62 #include "parse_technology.hpp"
63 #include "polixml.hpp"
64 #include "structural_manager.hpp"
65 #include "structural_objects.hpp"
66 #include "technology_flow_step.hpp"
68 #include "technology_manager.hpp"
69 #include "technology_node.hpp"
70 #include "time_info.hpp"
71 #include "xml_helper.hpp"
72 #include <algorithm>
73 #include <list>
74 #include <string>
75 #if HAVE_FLOPOCO
76 #include "flopoco_wrapper.hpp"
77 #endif
78 #include "string_manipulation.hpp" // for GET_CLASS
79 
80 #define PORT_VECTOR_N_PORTS 2
81 
82 RTLCharacterization::RTLCharacterization(const generic_deviceRef _device, const std::string& _cells,
83  const DesignFlowManagerConstRef _design_flow_manager,
84  const ParameterConstRef _parameters)
85  : DesignFlowStep(_design_flow_manager, _parameters),
86  FunctionalUnitStep(_device, _design_flow_manager, _parameters),
87  component(ComputeComponent(_cells)),
88  cells(ComputeCells(_cells))
89 #ifndef NDEBUG
90  ,
91  dummy_synthesis(_parameters->IsParameter("dummy_synthesis") and
92  _parameters->GetParameter<std::string>("dummy_synthesis") == "yes")
93 #endif
94 {
95  debug_level = parameters->get_class_debug_level(GET_CLASS(*this));
96 }
97 
99 
101 {
106 }
107 
109 {
110  const auto functional_unit = LM->get_fu(component);
112  // fix_execution_time_std();
114  // if(is_xilinx) fix_muxes();
117 }
118 
120 {
122  auto* fu_br = GetPointer<functional_unit>(f_unit_br);
123  technology_nodeRef op_br_node = fu_br->get_operation(ASSIGN);
124  auto* op_ASSIGN = GetPointer<operation>(op_br_node);
125  double ASSIGN_exec_time = op_ASSIGN->time_m->get_execution_time();
126  std::vector<unsigned int> bitsizes;
127  bitsizes.push_back(8);
128  bitsizes.push_back(16);
129  bitsizes.push_back(32);
130  bitsizes.push_back(64);
131  const auto b_it_end = bitsizes.end();
132  for(auto b_it = bitsizes.begin(); b_it != b_it_end; ++b_it)
133  {
134  std::string test_mul_mux_name = std::string(TEST_MUL_MUX_8) + "_" + STR(*b_it) + "_" + STR(*b_it) + "_" +
135  STR(*b_it) + "_" + STR(*b_it) + "_" + STR(*b_it) + "_" + STR(*b_it) + "_" +
136  STR(*b_it) + "_" + STR(*b_it) + "_" + STR(*b_it) + "_" + STR(*b_it) + "_" +
137  STR(*b_it);
138  technology_nodeRef f_unit_test = TM->get_fu(test_mul_mux_name, LIBRARY_STD_FU);
139  if(!f_unit_test)
140  {
141  continue;
142  }
143  auto* fu_test = GetPointer<functional_unit>(f_unit_test);
144  technology_nodeRef op_test_node = fu_test->get_operation(TEST_MUL_MUX_8);
145  auto* op_test = GetPointer<operation>(op_test_node);
146  double test_exec_time = op_test->time_m->get_execution_time();
147 
148  technology_nodeRef f_unit_mult = TM->get_fu(
149  std::string(MULTIPLIER_STD) + "_" + STR(*b_it) + "_" + STR(*b_it) + "_" + STR(*b_it) + "_0", LIBRARY_STD_FU);
150  auto* fu_mult = GetPointer<functional_unit>(f_unit_mult);
151  technology_nodeRef op_mult_node = fu_mult->get_operation("mult_expr");
152  auto* op_mult = GetPointer<operation>(op_mult_node);
153  double mult_exec_time = op_mult->time_m->get_execution_time();
154 
155  technology_nodeRef f_unit_mux = TM->get_fu(
156  std::string(MUX_GATE_STD) + "_1_" + STR(*b_it) + "_" + STR(*b_it) + "_" + STR(*b_it), LIBRARY_STD_FU);
157  auto* fu_mux = GetPointer<functional_unit>(f_unit_mux);
158  const functional_unit::operation_vec& ops = fu_mux->get_operations();
159  for(const auto& op : ops)
160  {
161  auto* current_op = GetPointer<operation>(op);
162  if(!current_op->time_m)
163  {
164  continue;
165  }
166  unsigned int curr_cycles = current_op->time_m->get_cycles();
167  double curr_exec = current_op->time_m->get_execution_time();
168  double new_exec_time = (test_exec_time - mult_exec_time) / 3 + ASSIGN_exec_time;
169  if(new_exec_time > curr_exec)
170  {
171  current_op->time_m->set_execution_time(new_exec_time, curr_cycles);
172  }
173  }
174  }
175 }
176 
178 {
180  auto* fu_br = GetPointer<functional_unit>(f_unit_br);
181  technology_nodeRef op_br_node = fu_br->get_operation(ASSIGN);
182  auto* op_br_LOAD = GetPointer<operation>(op_br_node);
183  double ASSIGN_exec_time = op_br_LOAD->time_m->get_execution_time();
186  {
187  return;
188  }
189  const auto tn = LM->get_fu(component);
190  auto* current_fu = GetPointer<functional_unit>(tn);
191  if(current_fu)
192  {
193  if((!parameters->isOption(OPT_component_name) || current_fu->get_operations_num() == 0) &&
194  completed.find(current_fu->functional_unit_name) == completed.end())
195  {
196  return;
197  }
198  const functional_unit::operation_vec& ops = current_fu->get_operations();
199  for(const auto& op : ops)
200  {
201  auto* current_op = GetPointer<operation>(op);
202  if(!current_op->time_m)
203  {
204  continue;
205  }
206  double curr_exec = current_op->time_m->get_execution_time();
207  unsigned int curr_cycles = current_op->time_m->get_cycles();
208  if(curr_exec - ASSIGN_exec_time < 0)
209  {
210  current_op->time_m->set_execution_time(0, curr_cycles);
211  }
212  else
213  {
214  current_op->time_m->set_execution_time(curr_exec - ASSIGN_exec_time, curr_cycles);
215  }
216  }
217  }
218 }
219 
221 {
222  std::vector<std::string> high_latency_postfix_list;
223  high_latency_postfix_list.push_back(std::string("_3"));
224  high_latency_postfix_list.push_back(std::string("_4"));
225  for(const auto& high_latency_postfix : high_latency_postfix_list)
226  {
228  auto* fu_br = GetPointer<functional_unit>(f_unit_br);
229  technology_nodeRef op_br_node = fu_br->get_operation("STORE");
230  auto* op_br_STORE = GetPointer<operation>(op_br_node);
231  double STORE_exec_time = op_br_STORE->time_m->get_execution_time();
233  auto* fu_br_nn = GetPointer<functional_unit>(f_unit_br_nn);
234  technology_nodeRef op_br_nn_node = fu_br_nn->get_operation("STORE");
235  auto* op_br_nn_STORE = GetPointer<operation>(op_br_nn_node);
236  double nn_STORE_exec_time = op_br_nn_STORE->time_m->get_execution_time();
237 
238  technology_nodeRef f_unit_br_hl = TM->get_fu(ARRAY_1D_STD_BRAM + high_latency_postfix, LIBRARY_STD_FU);
239  auto* fu_br_hl = GetPointer<functional_unit>(f_unit_br_hl);
240  technology_nodeRef op_br_node_hl = fu_br_hl->get_operation("STORE");
241  auto* op_br_STORE_hl = GetPointer<operation>(op_br_node_hl);
242  double STORE_exec_time_hl = op_br_STORE_hl->time_m->get_execution_time();
243  technology_nodeRef f_unit_br_nn_hl = TM->get_fu(ARRAY_1D_STD_BRAM_NN + high_latency_postfix, LIBRARY_STD_FU);
244  auto* fu_br_nn_hl = GetPointer<functional_unit>(f_unit_br_nn_hl);
245  technology_nodeRef op_br_nn_node_hl = fu_br_nn_hl->get_operation("STORE");
246  auto* op_br_nn_STORE_hl = GetPointer<operation>(op_br_nn_node_hl);
247  double nn_STORE_exec_time_hl = op_br_nn_STORE_hl->time_m->get_execution_time();
248 
251  {
252  return;
253  }
254  const auto tn = LM->get_fu(component);
255  auto* current_fu = GetPointer<functional_unit>(tn);
256  if(!current_fu)
257  {
258  return;
259  }
260  std::string fu_name = current_fu->functional_unit_name;
261  std::string memory_ctrl_type = current_fu->memory_ctrl_type;
262  std::string bram_load_latency = current_fu->bram_load_latency;
263  if(memory_ctrl_type == MEMORY_CTRL_TYPE_PROXY || memory_ctrl_type == MEMORY_CTRL_TYPE_DPROXY ||
264  memory_ctrl_type == MEMORY_CTRL_TYPE_SPROXY || fu_name == BMEMORY_STD ||
265  fu_name == BMEMORY_STD + (bram_load_latency != "2" ? high_latency_postfix : ""))
266  {
267  if((!parameters->isOption(OPT_component_name) || current_fu->get_operations_num() == 0) &&
268  completed.find(fu_name) == completed.end())
269  {
270  return;
271  }
272  const functional_unit::operation_vec& ops = current_fu->get_operations();
273  for(const auto& op : ops)
274  {
275  auto* current_op = GetPointer<operation>(op);
276  if(!current_op->time_m)
277  {
278  continue;
279  }
280  unsigned int curr_cycles = current_op->time_m->get_cycles();
281  if(bram_load_latency == "2")
282  {
283  if(curr_cycles > 0)
284  {
285  current_op->time_m->set_stage_period(STORE_exec_time);
286  }
287  else
288  {
289  current_op->time_m->set_execution_time(STORE_exec_time, curr_cycles);
290  }
291  }
292  else
293  {
294  if(curr_cycles > 0)
295  {
296  current_op->time_m->set_stage_period(STORE_exec_time_hl);
297  }
298  else
299  {
300  current_op->time_m->set_execution_time(STORE_exec_time_hl, curr_cycles);
301  }
302  }
303  }
304  }
305  if(memory_ctrl_type == MEMORY_CTRL_TYPE_PROXYN || memory_ctrl_type == MEMORY_CTRL_TYPE_DPROXYN ||
306  memory_ctrl_type == MEMORY_CTRL_TYPE_SPROXYN || fu_name == BMEMORY_STDN ||
307  fu_name == BMEMORY_STDN + (bram_load_latency != "2" ? high_latency_postfix : ""))
308  {
309  if((!parameters->isOption(OPT_component_name) || current_fu->get_operations_num() == 0) &&
310  completed.find(fu_name) == completed.end())
311  {
312  return;
313  }
314  const functional_unit::operation_vec& ops = current_fu->get_operations();
315  for(const auto& op : ops)
316  {
317  auto* current_op = GetPointer<operation>(op);
318  if(!current_op->time_m)
319  {
320  continue;
321  }
322  unsigned int curr_cycles = current_op->time_m->get_cycles();
323  if(bram_load_latency == "2")
324  {
325  if(curr_cycles > 0)
326  {
327  current_op->time_m->set_stage_period(nn_STORE_exec_time);
328  }
329  else
330  {
331  current_op->time_m->set_execution_time(nn_STORE_exec_time, curr_cycles);
332  }
333  }
334  else
335  {
336  if(curr_cycles > 0)
337  {
338  current_op->time_m->set_stage_period(nn_STORE_exec_time_hl);
339  }
340  else
341  {
342  current_op->time_m->set_execution_time(nn_STORE_exec_time_hl, curr_cycles);
343  }
344  }
345  }
346  }
347  }
348 }
349 
351 {
352  const auto file_name = GetPath("characterization.xml");
353  try
354  {
355  xml_document document;
356  xml_element* nodeRoot = document.create_root_node("target");
357 
358  device->xwrite(nodeRoot);
359 
360  xwrite_characterization(nodeRoot);
361 
362  document.write_to_file_formatted(file_name);
363  }
364  catch(const char* msg)
365  {
366  THROW_ERROR(std::string(msg));
367  }
368  catch(const std::string& msg)
369  {
370  THROW_ERROR(msg);
371  }
372  catch(const std::exception& ex)
373  {
374  THROW_ERROR("Exception caught: " + std::string(ex.what()));
375  }
376  catch(...)
377  {
378  THROW_ERROR("unknown exception");
379  }
380 }
381 
383 {
384  xml_element* tmRoot = nodeRoot->add_child_element("technology");
385 
386  xml_element* lmRoot = tmRoot->add_child_element("library");
387  xml_element* name_el = lmRoot->add_child_element("name");
388  name_el->add_child_text(LM->get_library_name());
389 
391  for(const auto& cell : cells)
392  {
393  if(fus.find(cell) == fus.end())
394  {
395  THROW_ERROR(cell + " is not in any technology library");
396  }
397  technology_nodeRef tn = fus.find(cell)->second;
398  auto* current_fu = GetPointer<functional_unit>(tn);
399  if(!current_fu)
400  {
401  auto* current_fu_temp = GetPointer<functional_unit_template>(tn);
402  if(current_fu_temp->specialized != "")
403  {
404  xml_element* template_el = lmRoot->add_child_element("template");
405  current_fu_temp->xwrite(template_el, tn, parameters);
406  }
407  }
408  else
409  {
410  if((!parameters->isOption(OPT_component_name) || current_fu->get_operations_num() == 0) &&
411  completed.find(current_fu->functional_unit_name) == completed.end())
412  {
413  THROW_ERROR("");
414  }
415 
416  if(!current_fu->area_m)
417  {
419  current_fu->area_m = area_info::factory(parameters);
420  }
421 
422  xml_element* cell_el = lmRoot->add_child_element("cell");
423  xml_element* cell_name_el = cell_el->add_child_element("name");
424  cell_name_el->add_child_text(current_fu->get_name());
425 
426  xml_element* attribute_el = cell_el->add_child_element("attribute");
427  WRITE_XNVM2("name", "area", attribute_el);
428  WRITE_XNVM2("value_type", "float64", attribute_el);
429  attribute_el->add_child_text(STR(current_fu->area_m->get_area_value()));
430  if(current_fu->area_m && current_fu->area_m->get_resource_value(area_info::REGISTERS) != 0)
431  {
432  attribute_el = cell_el->add_child_element("attribute");
433  WRITE_XNVM2("name", "REGISTERS", attribute_el);
434  WRITE_XNVM2("value_type", "float64", attribute_el);
435  attribute_el->add_child_text(STR(current_fu->area_m->get_resource_value(area_info::REGISTERS)));
436  }
437  if(current_fu->area_m && current_fu->area_m->get_resource_value(area_info::SLICE_LUTS) != 0)
438  {
439  attribute_el = cell_el->add_child_element("attribute");
440  WRITE_XNVM2("name", "SLICE_LUTS", attribute_el);
441  WRITE_XNVM2("value_type", "float64", attribute_el);
442  attribute_el->add_child_text(STR(current_fu->area_m->get_resource_value(area_info::SLICE_LUTS)));
443  }
444  if(current_fu->area_m && current_fu->area_m->get_resource_value(area_info::SLICE) != 0)
445  {
446  attribute_el = cell_el->add_child_element("attribute");
447  WRITE_XNVM2("name", "SLICE", attribute_el);
448  WRITE_XNVM2("value_type", "float64", attribute_el);
449  attribute_el->add_child_text(STR(current_fu->area_m->get_resource_value(area_info::SLICE)));
450  }
451  if(current_fu->area_m && current_fu->area_m->get_resource_value(area_info::LUT_FF_PAIRS) != 0)
452  {
453  attribute_el = cell_el->add_child_element("attribute");
454  WRITE_XNVM2("name", "LUT_FF_PAIRS", attribute_el);
455  WRITE_XNVM2("value_type", "float64", attribute_el);
456  attribute_el->add_child_text(STR(current_fu->area_m->get_resource_value(area_info::LUT_FF_PAIRS)));
457  }
458  if(current_fu->area_m && current_fu->area_m->get_resource_value(area_info::DSP) != 0)
459  {
460  attribute_el = cell_el->add_child_element("attribute");
461  WRITE_XNVM2("name", "DSP", attribute_el);
462  WRITE_XNVM2("value_type", "float64", attribute_el);
463  attribute_el->add_child_text(STR(current_fu->area_m->get_resource_value(area_info::DSP)));
464  }
465  if(current_fu->area_m && current_fu->area_m->get_resource_value(area_info::BRAM) != 0)
466  {
467  attribute_el = cell_el->add_child_element("attribute");
468  WRITE_XNVM2("name", "BRAM", attribute_el);
469  WRITE_XNVM2("value_type", "float64", attribute_el);
470  attribute_el->add_child_text(STR(current_fu->area_m->get_resource_value(area_info::BRAM)));
471  }
472  if(current_fu->area_m && current_fu->area_m->get_resource_value(area_info::DRAM) != 0)
473  {
474  attribute_el = cell_el->add_child_element("attribute");
475  WRITE_XNVM2("name", "DRAM", attribute_el);
476  WRITE_XNVM2("value_type", "float64", attribute_el);
477  attribute_el->add_child_text(STR(current_fu->area_m->get_resource_value(area_info::DRAM)));
478  }
479 
480  if(current_fu->fu_template_name != "" && current_fu->fu_template_parameters != "")
481  {
482  xml_element* template_el = cell_el->add_child_element("template");
483  WRITE_XNVM2("name", current_fu->fu_template_name, template_el);
484  WRITE_XNVM2("parameter", current_fu->fu_template_parameters, template_el);
485 
486  if(current_fu->characterizing_constant_value != "")
487  {
488  xml_element* constant_el = cell_el->add_child_element(GET_CLASS_NAME(characterizing_constant_value));
489  constant_el->add_child_text(STR(current_fu->characterizing_constant_value));
490  }
491  }
492  auto characterization_timestamp_el = cell_el->add_child_element("characterization_timestamp");
493  characterization_timestamp_el->add_child_text(STR(TimeStamp::GetCurrentTimeStamp()));
494  const functional_unit::operation_vec& ops = current_fu->get_operations();
495  for(const auto& op : ops)
496  {
497  auto* current_op = GetPointer<operation>(op);
498  current_op->xwrite(cell_el, op, parameters);
499  }
500  if(current_fu->CM && current_fu->CM->get_circ() && GetPointer<module>(current_fu->CM->get_circ()) &&
501  GetPointer<module>(current_fu->CM->get_circ())->get_specialized() != "")
502  {
503  if(current_fu->memory_type != "")
504  {
505  xml_element* item_el = cell_el->add_child_element(GET_CLASS_NAME(memory_type));
506  item_el->add_child_text(STR(current_fu->memory_type));
507  }
508  if(current_fu->channels_type != "")
509  {
510  xml_element* item_el = cell_el->add_child_element(GET_CLASS_NAME(channels_type));
511  item_el->add_child_text(STR(current_fu->channels_type));
512  }
513  if(current_fu->memory_ctrl_type != "")
514  {
515  xml_element* item_el = cell_el->add_child_element(GET_CLASS_NAME(memory_ctrl_type));
516  item_el->add_child_text(STR(current_fu->memory_ctrl_type));
517  }
518  if(current_fu->bram_load_latency != "")
519  {
520  xml_element* item_el = cell_el->add_child_element(GET_CLASS_NAME(bram_load_latency));
521  item_el->add_child_text(STR(current_fu->bram_load_latency));
522  }
523  current_fu->CM->xwrite(cell_el);
524  }
525  }
526  }
527 }
528 
529 void RTLCharacterization::resize_port(const structural_objectRef& port, unsigned int prec)
530 {
532  {
533  return;
534  }
535  if(GetPointer<port_o>(port)->get_is_doubled())
536  {
540  {
541  port_o::resize_std_port(2 * prec, 128 / (2 * prec), 0, port);
542  }
543  else
544  {
545  port_o::resize_std_port(2 * prec, 0, 0, port);
546  }
547  }
548  else if(GetPointer<port_o>(port)->get_is_halved())
549  {
553  {
554  port_o::resize_std_port(prec / 2, 128 / (prec / 2), 0, port);
555  }
556  else
557  {
558  port_o::resize_std_port(prec / 2, 0, 0, port);
559  }
560  }
564  {
565  port_o::resize_std_port(prec, 128 / prec, 0, port);
566  }
567  else
568  {
569  port_o::resize_std_port(prec, 0, 0, port);
570  }
571 }
572 
573 void RTLCharacterization::specialize_fu(const module* mod, unsigned int prec, unsigned int bus_data_bitsize,
574  unsigned int bus_addr_bitsize, unsigned int bus_size_bitsize,
575  unsigned int bus_tag_bitsize, size_t portsize_value)
576 {
577  for(unsigned int i = 0; i < mod->get_in_port_size(); i++)
578  {
579  const structural_objectRef& port = mod->get_in_port(i);
580  if(port->get_kind() == port_vector_o_K)
581  {
582  if(GetPointer<port_o>(port)->get_ports_size() == 0)
583  {
584  GetPointer<port_o>(port)->add_n_ports(static_cast<unsigned int>(portsize_value), port);
585  }
586  if(!port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port))
587  {
588  for(unsigned int p = 0; p < GetPointer<port_o>(port)->get_ports_size(); ++p)
589  {
590  resize_port(GetPointer<port_o>(port)->get_port(p), prec);
591  }
592  }
593  }
594  else
595  {
596  if(!port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port))
597  {
598  resize_port(port, prec);
599  }
600  }
601  }
602  for(unsigned int i = 0; i < mod->get_out_port_size(); i++)
603  {
604  const structural_objectRef& port = mod->get_out_port(i);
605  if(port->get_kind() == port_vector_o_K)
606  {
607  if(GetPointer<port_o>(port)->get_ports_size() == 0)
608  {
609  GetPointer<port_o>(port)->add_n_ports(static_cast<unsigned int>(portsize_value), port);
610  }
611  if(!port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port))
612  {
613  for(unsigned int p = 0; p < GetPointer<port_o>(port)->get_ports_size(); ++p)
614  {
615  resize_port(GetPointer<port_o>(port)->get_port(p), prec);
616  }
617  }
618  }
619  else
620  {
621  if(!port_o::resize_if_busport(bus_size_bitsize, bus_addr_bitsize, bus_data_bitsize, bus_tag_bitsize, port))
622  {
623  resize_port(port, prec);
624  }
625  }
626  }
627 }
628 
629 void RTLCharacterization::add_input_register(structural_objectRef port_in, const std::string& register_library,
630  const std::string& port_prefix, structural_objectRef reset_port,
631  structural_objectRef circuit, structural_objectRef clock_port,
633 {
634  structural_objectRef r_signal;
635  structural_objectRef reg_mod;
637  {
638  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME_INT, register_library,
639  circuit, TM);
640  }
641  else if(port_in->get_typeRef()->type == structural_type_descriptor::UINT)
642  {
643  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME_UINT,
644  register_library, circuit, TM);
645  }
646  else if(port_in->get_typeRef()->type == structural_type_descriptor::REAL)
647  {
648  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME_REAL,
649  register_library, circuit, TM);
650  }
651  else
652  {
653  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME, register_library,
654  circuit, TM);
655  }
656  GetPointer<module>(reg_mod)->get_in_port(2)->type_resize(GET_TYPE_SIZE(port_in));
657  GetPointer<module>(reg_mod)->get_out_port(0)->type_resize(GET_TYPE_SIZE(port_in));
658 
659  structural_objectRef port_ck = reg_mod->find_member(CLOCK_PORT_NAME, port_o_K, reg_mod);
660  SM->add_connection(clock_port, port_ck);
661 
662  structural_objectRef reset_ck = reg_mod->find_member(RESET_PORT_NAME, port_o_K, reg_mod);
663  if(reset_ck)
664  {
665  SM->add_connection(reset_port, reset_ck);
666  }
667 
668  r_signal = SM->add_sign(port_prefix + "_SIGI1", circuit, port_in->get_typeRef());
669  SM->add_connection(e_port, r_signal);
670  SM->add_connection(GetPointer<module>(reg_mod)->get_in_port(2), r_signal);
671 
672  r_signal = SM->add_sign(port_prefix + "_SIGI2", circuit, port_in->get_typeRef());
673  SM->add_connection(GetPointer<module>(reg_mod)->get_out_port(0), r_signal);
674  SM->add_connection(port_in, r_signal);
675 }
676 
678  structural_objectRef circuit, structural_objectRef reset_port,
679  structural_objectRef port_out, const std::string& port_prefix,
680  structural_objectRef clock_port, const std::string& register_library)
681 {
682  structural_objectRef r_signal;
683  structural_objectRef reg_mod;
685  {
686  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME_INT, register_library,
687  circuit, TM);
688  }
689  else if(port_out->get_typeRef()->type == structural_type_descriptor::UINT)
690  {
691  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME_UINT,
692  register_library, circuit, TM);
693  }
694  else if(port_out->get_typeRef()->type == structural_type_descriptor::REAL)
695  {
696  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME_REAL,
697  register_library, circuit, TM);
698  }
699  else
700  {
701  reg_mod = SM->add_module_from_technology_library(port_prefix + "_REG", register_AR_NORETIME, register_library,
702  circuit, TM);
703  }
704  GetPointer<module>(reg_mod)->get_in_port(2)->type_resize(GET_TYPE_SIZE(port_out));
705  GetPointer<module>(reg_mod)->get_out_port(0)->type_resize(GET_TYPE_SIZE(port_out));
706 
707  structural_objectRef port_ck = reg_mod->find_member(CLOCK_PORT_NAME, port_o_K, reg_mod);
708  SM->add_connection(clock_port, port_ck);
709 
710  structural_objectRef reset_ck = reg_mod->find_member(RESET_PORT_NAME, port_o_K, reg_mod);
711  if(reset_ck)
712  {
713  SM->add_connection(reset_port, reset_ck);
714  }
715 
716  r_signal = SM->add_sign(port_prefix + "_SIGO1", circuit, port_out->get_typeRef());
717  SM->add_connection(port_out, r_signal);
718  SM->add_connection(GetPointer<module>(reg_mod)->get_in_port(2), r_signal);
719  r_signal = SM->add_sign(port_prefix + "_SIGO2", circuit, port_out->get_typeRef());
720  SM->add_connection(GetPointer<module>(reg_mod)->get_out_port(0), r_signal);
721  SM->add_connection(e_port, r_signal);
722 }
723 
725 {
726  return true;
727 }
728 
730 {
731  return "RTLCharacterization";
732 }
733 
734 std::string RTLCharacterization::GetName() const
735 {
736  return "RTLCharacterization";
737 }
738 
740  const DesignFlowStep::RelationshipType relationship_type)
741 {
742  switch(relationship_type)
743  {
745  {
746  const DesignFlowGraphConstRef design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
747  const auto* technology_flow_step_factory = GetPointer<const TechnologyFlowStepFactory>(
748  design_flow_manager.lock()->CGetDesignFlowStepFactory("Technology"));
749  const std::string technology_flow_signature =
751  const vertex technology_flow_step = design_flow_manager.lock()->GetDesignFlowStep(technology_flow_signature);
752  const DesignFlowStepRef technology_design_flow_step =
753  technology_flow_step ?
754  design_flow_graph->CGetDesignFlowStepInfo(technology_flow_step)->design_flow_step :
755  technology_flow_step_factory->CreateTechnologyFlowStep(TechnologyFlowStep_Type::LOAD_TECHNOLOGY);
756  relationship.insert(technology_design_flow_step);
757  break;
758  }
761  {
762  break;
763  }
764  default:
765  {
766  THROW_UNREACHABLE("");
767  }
768  }
769 }
770 
771 DesignFlowStepFactoryConstRef RTLCharacterization::CGetDesignFlowStepFactory() const
772 {
773  THROW_UNREACHABLE("Not implemented");
774  return DesignFlowStepFactoryConstRef();
775 }
776 
777 void RTLCharacterization::AnalyzeCell(functional_unit* fu, const unsigned int prec,
778  const std::vector<std::string>& portsize_parameters, const size_t portsize_index,
779  const std::vector<std::string>& pipe_parameters, const size_t stage_index,
780  const unsigned int constPort, const bool is_commutative, size_t max_lut_size)
781 {
782  const auto fu_name = fu->get_name();
783  const auto fu_base_name = fu->fu_template_name != "" ? fu->fu_template_name : fu_name;
784  if(cells.find(fu_name) != cells.end())
785  {
786  size_t n_portsize_parameters = portsize_parameters.size();
787  size_t n_pipe_parameters = pipe_parameters.size();
788 
789  const structural_objectRef obj = fu->CM->get_circ();
790  unsigned int n_ports = GetPointer<module>(obj)->get_in_port_size();
791  const NP_functionalityRef NPF = GetPointer<module>(obj)->get_NP_functionality();
792  const bool isTemplate = fu->fu_template_parameters != "";
793  if(constPort < n_ports)
794  {
796  if(isTemplate && fu->characterizing_constant_value == "")
797  {
798  fu->characterizing_constant_value = STR(6148914691236517205);
799  }
800  }
801  else
802  {
804  }
805 #ifndef NDEBUG
806  const bool assertion_argument = NPF->exist_NP_functionality(NP_functionality::VERILOG_PROVIDED)
807 #if HAVE_FLOPOCO
809 #endif
812  THROW_ASSERT(assertion_argument,
813  "Verilog, VHDL, SystemVerilog or Flopoco description not provided for functional unit " + fu_name);
814 #endif
817  auto top_wrapper_name = "top" + fu_name + "_wrapper";
818  boost::replace_all(top_wrapper_name, "__", "");
819  structural_type_descriptorRef module_type =
822  SM->set_top_info(top_wrapper_name, module_type);
823  structural_objectRef circuit = SM->get_circ();
824  THROW_ASSERT(circuit, "Top circuit is missing");
826  fu_base_name + "_inst0", fu_base_name, LM->get_library_name(), circuit, TM);
827 
828  PRINT_OUT_MEX(OUTPUT_LEVEL_VERBOSE, output_level, " - Generating HDL of functional unit " + fu_name);
829  auto* spec_module = GetPointer<module>(template_circuit);
830 
831  std::string memory_type = fu->memory_type;
832  std::string channels_type = fu->channels_type;
833  unsigned int BRAM_BITSIZE = 16;
834  if(BRAM_BITSIZE > device->get_parameter<unsigned int>("BRAM_bitsize_max"))
835  {
836  BRAM_BITSIZE = device->get_parameter<unsigned int>("BRAM_bitsize_max");
837  }
838  unsigned int ALIGNED_BITSIZE = 2 * BRAM_BITSIZE;
839  unsigned int BUS_DATA_BITSIZE = 2 * BRAM_BITSIZE;
840  unsigned int BUS_ADDR_BITSIZE = 15;
841  unsigned int BUS_SIZE_BITSIZE = 7;
842  unsigned int BUS_TAG_BITSIZE = 8;
843  unsigned int NUMBER_OF_BYTES_ALLOCATED = 1024;
844  if(memory_type == MEMORY_TYPE_ASYNCHRONOUS)
845  {
846  NUMBER_OF_BYTES_ALLOCATED = NUMBER_OF_BYTES_ALLOCATED / 16;
847  }
848  specialize_fu(spec_module, prec, BUS_DATA_BITSIZE, BUS_ADDR_BITSIZE, BUS_SIZE_BITSIZE, BUS_TAG_BITSIZE,
849  n_portsize_parameters > 0 ? static_cast<unsigned>(std::stoul(portsize_parameters[portsize_index])) :
851 
852  if(fu_base_name == "MC_FU")
853  {
854  spec_module->SetParameter("EXECUTION_TIME", STR(2));
855  spec_module->SetParameter("BITSIZE", STR(8));
856  spec_module->SetParameter("INITIATION_TIME", STR(1));
857  }
858  else if(memory_type != "")
859  {
860  unsigned int base_address = 0;
861  std::string init_filename = "array_ref_" + STR(base_address) + ".mem";
862  unsigned int counter = 0;
863  unsigned int nbyte_on_memory = BRAM_BITSIZE / 8;
864  unsigned int elts_size = BUS_DATA_BITSIZE;
865  unsigned int vec_size = NUMBER_OF_BYTES_ALLOCATED / (elts_size / 8);
866  if(memory_type == MEMORY_TYPE_ASYNCHRONOUS)
867  {
868  BRAM_BITSIZE = elts_size;
869  nbyte_on_memory = elts_size / 8;
870  base_address = 0;
871  }
872  if(memory_type == MEMORY_TYPE_SYNCHRONOUS_SDS || memory_type == MEMORY_TYPE_SYNCHRONOUS_SDS_BUS)
873  {
874  BRAM_BITSIZE = elts_size;
875  nbyte_on_memory = elts_size / 8;
876  }
877  if(memory_type == MEMORY_TYPE_SYNCHRONOUS_UNALIGNED &&
878  (channels_type.find(CHANNELS_TYPE_MEM_ACC_NN) != std::string::npos ||
879  (channels_type.find(CHANNELS_TYPE_MEM_ACC_N1) != std::string::npos &&
880  channels_type.find(CHANNELS_TYPE_MEM_ACC_11) == std::string::npos)))
881  {
882  std::ofstream init_file_a(GetPath("a_" + init_filename));
883  std::ofstream init_file_b(GetPath("b_" + init_filename));
884  bool is_even = true;
885  for(unsigned int i = 0; i < vec_size; ++i)
886  {
887  for(unsigned int j = 0; j < BRAM_BITSIZE; ++j)
888  {
889  long int random_value = random();
890  std::string bit_val = (random_value & 1) == 0 ? "0" : "1";
891  if(is_even)
892  {
893  init_file_a << bit_val;
894  }
895  else
896  {
897  init_file_b << bit_val;
898  }
899  counter++;
900  if(counter % (nbyte_on_memory * 8) == 0)
901  {
902  if(is_even)
903  {
904  init_file_a << std::endl;
905  }
906  else
907  {
908  init_file_b << std::endl;
909  }
910  is_even = !is_even;
911  }
912  }
913  }
914  init_file_a.close();
915  init_file_b.close();
916  }
917  else
918  {
919  std::ofstream init_file(GetPath(init_filename));
920  for(unsigned int i = 0; i < vec_size; ++i)
921  {
922  for(unsigned int j = 0; j < elts_size; ++j)
923  {
924  long int random_value = random();
925  std::string bit_val = (random_value & 1) == 0 ? "0" : "1";
926  init_file << bit_val;
927  counter++;
928  if(counter % (nbyte_on_memory * 8) == 0)
929  {
930  init_file << std::endl;
931  }
932  }
933  }
934  init_file.close();
935  }
936  spec_module->SetParameter("address_space_begin", STR(base_address));
937  spec_module->SetParameter("address_space_rangesize", STR((elts_size / 8) * vec_size));
938  spec_module->SetParameter("USE_SPARSE_MEMORY", "1");
939  if(memory_type == MEMORY_TYPE_SYNCHRONOUS_UNALIGNED &&
940  (channels_type.find(CHANNELS_TYPE_MEM_ACC_NN) != std::string::npos ||
941  (channels_type.find(CHANNELS_TYPE_MEM_ACC_N1) != std::string::npos &&
942  channels_type.find(CHANNELS_TYPE_MEM_ACC_11) == std::string::npos)))
943  {
944  spec_module->SetParameter("MEMORY_INIT_file_a", "\"\"" + GetPath("a_" + init_filename) + "\"\"");
945  spec_module->SetParameter("MEMORY_INIT_file_b", "\"\"" + GetPath("b_" + init_filename) + "\"\"");
946  }
947  else
948  {
949  spec_module->SetParameter("MEMORY_INIT_file", "\"\"" + GetPath(init_filename) + "\"\"");
950  }
951  spec_module->SetParameter("n_elements", STR(vec_size));
952  spec_module->SetParameter("data_size", STR(elts_size));
953  if(memory_type != MEMORY_TYPE_SYNCHRONOUS_SDS && memory_type != MEMORY_TYPE_SYNCHRONOUS_SDS_BUS &&
954  memory_type != MEMORY_TYPE_ASYNCHRONOUS)
955  {
956  spec_module->SetParameter("BRAM_BITSIZE", STR(BRAM_BITSIZE));
957  }
958  spec_module->SetParameter("BUS_PIPELINED", "1");
959  spec_module->SetParameter("PRIVATE_MEMORY", "0");
960  }
961  else if(fu_base_name == MEMLOAD_STD)
962  {
963  spec_module->SetParameter("base_address", "8");
964  }
965  else if(fu_base_name == MEMSTORE_STD)
966  {
967  spec_module->SetParameter("base_address", "8");
968  }
969  structural_objectRef e_port, one_port;
970 
971  if(n_pipe_parameters > 0)
972  {
973  spec_module->SetParameter(PIPE_PARAMETER, pipe_parameters[stage_index]);
974  PRINT_OUT_MEX(OUTPUT_LEVEL_VERBOSE, output_level, " - PIPE_PARAMETER=" + pipe_parameters[stage_index]);
975  }
976  if(NPF)
977  {
978  std::vector<std::string> params;
979  NPF->get_library_parameters(params);
980  for(const auto& param : params)
981  {
982  if(param == "PRECISION")
983  {
984  unsigned int precision_bitsize = prec;
985  precision_bitsize = std::max(8u, precision_bitsize);
986  spec_module->SetParameter("PRECISION", STR(precision_bitsize));
987  }
988  else if(param == "ALIGNED_BITSIZE")
989  {
990  spec_module->SetParameter("ALIGNED_BITSIZE", STR(ALIGNED_BITSIZE));
991  }
992  else if(param == "LSB_PARAMETER")
993  {
994  spec_module->SetParameter("LSB_PARAMETER", STR(0));
995  }
996  THROW_ASSERT(template_circuit->find_member(param, port_o_K, template_circuit) ||
997  template_circuit->find_member(param, port_vector_o_K, template_circuit) ||
998  spec_module->ExistsParameter(param),
999  "parameter not yet specialized: " + param + " for module " +
1000  spec_module->get_typeRef()->get_name());
1001  }
1002  }
1003 
1004  structural_type_descriptorRef bool_type =
1006  one_port = SM->add_constant(fu_name + "_constant_" + STR(1), circuit, bool_type, STR(1));
1007  std::string register_library = TM->get_library(register_AR_NORETIME);
1008  structural_objectRef clock_port, reset_port;
1009 
1011  for(unsigned int i = 0; i < spec_module->get_in_port_size(); i++)
1012  {
1013  const structural_objectRef port_in = spec_module->get_in_port(i);
1014  if(port_in->get_id() == CLOCK_PORT_NAME)
1015  {
1016  clock_port =
1017  SM->add_port(GetPointer<port_o>(port_in)->get_id(), port_o::IN, circuit, port_in->get_typeRef());
1018  SM->add_connection(port_in, clock_port);
1019  }
1020  if(port_in->get_id() == RESET_PORT_NAME)
1021  {
1022  reset_port =
1023  SM->add_port(GetPointer<port_o>(port_in)->get_id(), port_o::IN, circuit, port_in->get_typeRef());
1024  SM->add_connection(port_in, reset_port);
1025  }
1026  else if(port_in->get_id() == START_PORT_NAME)
1027  {
1028  e_port = SM->add_port(GetPointer<port_o>(port_in)->get_id(), port_o::IN, circuit, port_in->get_typeRef());
1029  SM->add_connection(port_in, e_port);
1030  }
1031  }
1032  if(!clock_port)
1033  {
1034  clock_port = SM->add_port(CLOCK_PORT_NAME, port_o::IN, circuit, bool_type);
1035  }
1036  if(!reset_port)
1037  {
1038  reset_port = SM->add_port(RESET_PORT_NAME, port_o::IN, circuit, bool_type);
1039  }
1040 
1041  for(unsigned int i = 0; i < spec_module->get_in_port_size(); i++)
1042  {
1043  structural_objectRef port_in = spec_module->get_in_port(i);
1044  if(port_in->get_id() == CLOCK_PORT_NAME || port_in->get_id() == RESET_PORT_NAME ||
1045  port_in->get_id() == START_PORT_NAME)
1046  {
1047  continue;
1048  }
1049  if(fu_base_name == LUT_EXPR_STD && i == 0)
1050  {
1051  resize_port(port_in, 64);
1052  e_port = SM->add_constant("constant_0", circuit, port_in->get_typeRef(), STR(0xFF7F3F1F0F070301));
1053  SM->add_connection(port_in, e_port);
1054  }
1055  else if(fu_base_name == LUT_EXPR_STD && i > max_lut_size)
1056  {
1057  e_port = SM->add_constant("constant_" + STR(i), circuit, port_in->get_typeRef(), STR(0));
1058  SM->add_connection(port_in, e_port);
1059  }
1060  else if(isTemplate && i == constPort)
1061  {
1062  THROW_ASSERT(fu->characterizing_constant_value != "", "expected a value");
1063  e_port = SM->add_constant("constant_" + STR(constPort), circuit, port_in->get_typeRef(),
1065  SM->add_connection(port_in, e_port);
1066  }
1067  else if(false)
1068  {
1069  if(port_in->get_kind() == port_vector_o_K)
1070  {
1071  for(unsigned int p = 0; p < GetPointer<port_o>(port_in)->get_ports_size(); ++p)
1072  {
1073  e_port = SM->add_constant("constant_" + STR(i) + "_" + STR(p), circuit, port_in->get_typeRef(),
1074  STR(BUS_DATA_BITSIZE));
1075  SM->add_connection(GetPointer<port_o>(port_in)->get_port(p), e_port);
1076  }
1077  }
1078  else
1079  {
1080  e_port = SM->add_constant("constant_" + STR(i), circuit, port_in->get_typeRef(), STR(BUS_DATA_BITSIZE));
1081  SM->add_connection(port_in, e_port);
1082  }
1083  }
1084  else
1085  {
1086  if(port_in->get_kind() == port_vector_o_K)
1087  {
1088  e_port = SM->add_port_vector(GetPointer<port_o>(port_in)->get_id(), port_o::IN,
1089  GetPointer<port_o>(port_in)->get_ports_size(), circuit,
1090  GetPointer<port_o>(port_in)->get_port(0)->get_typeRef());
1091  }
1092  else
1093  {
1094  e_port =
1095  SM->add_port(GetPointer<port_o>(port_in)->get_id(), port_o::IN, circuit, port_in->get_typeRef());
1096  }
1097  std::string port_prefix = GetPointer<port_o>(port_in)->get_id();
1098 
1100  if(port_in->get_kind() == port_vector_o_K)
1101  {
1102  for(unsigned int p = 0; p < GetPointer<port_o>(port_in)->get_ports_size(); ++p)
1103  {
1104  add_input_register(GetPointer<port_o>(port_in)->get_port(p), register_library,
1105  port_prefix + GetPointer<port_o>(port_in)->get_port(p)->get_id(), reset_port,
1106  circuit, clock_port, GetPointer<port_o>(e_port)->get_port(p), SM);
1107  }
1108  }
1109  else
1110  {
1111  add_input_register(port_in, register_library, port_prefix, reset_port, circuit, clock_port, e_port, SM);
1112  }
1113  }
1114  }
1115 
1116 #if HAVE_FLOPOCO
1117  bool is_doubled_out = false;
1118  bool is_halved_out = false;
1119 #endif
1120  for(unsigned int i = 0; i < spec_module->get_out_port_size(); i++)
1121  {
1122  structural_objectRef port_out = spec_module->get_out_port(i);
1123 #if HAVE_FLOPOCO
1124  if(GetPointer<port_o>(port_out)->get_is_doubled())
1125  {
1126  is_doubled_out = true;
1127  }
1128  else if(GetPointer<port_o>(port_out)->get_is_halved())
1129  {
1130  is_halved_out = true;
1131  }
1132 #endif
1133  if(port_out->get_kind() == port_vector_o_K)
1134  {
1135  e_port = SM->add_port_vector(GetPointer<port_o>(port_out)->get_id(), port_o::OUT,
1136  GetPointer<port_o>(port_out)->get_ports_size(), circuit,
1137  GetPointer<port_o>(port_out)->get_port(0)->get_typeRef());
1138  }
1139  else
1140  {
1141  e_port =
1142  SM->add_port(GetPointer<port_o>(port_out)->get_id(), port_o::OUT, circuit, port_out->get_typeRef());
1143  }
1144  std::string port_prefix = GetPointer<port_o>(port_out)->get_id();
1145 
1147  if(port_out->get_kind() == port_vector_o_K)
1148  {
1149  for(unsigned int p = 0; p < GetPointer<port_o>(port_out)->get_ports_size(); ++p)
1150  {
1151  add_output_register(SM, GetPointer<port_o>(e_port)->get_port(p), circuit, reset_port,
1152  GetPointer<port_o>(port_out)->get_port(p),
1153  port_prefix + GetPointer<port_o>(port_out)->get_port(p)->get_id(), clock_port,
1154  register_library);
1155  }
1156  }
1157  else
1158  {
1159  add_output_register(SM, e_port, circuit, reset_port, port_out, port_prefix, clock_port, register_library);
1160  }
1161  }
1162 
1163  // get the wrapped circuit.
1165  std::list<std::string> hdl_files, aux_files;
1166  std::list<structural_objectRef> circuits;
1167  circuits.push_back(circuit);
1168  HDL->hdl_gen(fu_name, circuits, hdl_files, aux_files, false);
1169  int PipelineDepth = -1;
1170 #if HAVE_FLOPOCO
1171  if(n_pipe_parameters > 0 && NPF && NPF->exist_NP_functionality(NP_functionality::FLOPOCO_PROVIDED) &&
1172  HDL->get_flopocowrapper())
1173  {
1174  if(is_doubled_out)
1175  {
1176  PipelineDepth = static_cast<int>(HDL->get_flopocowrapper()->get_FUPipelineDepth(
1177  fu_base_name, prec, 2 * prec, pipe_parameters[stage_index]));
1178  }
1179  else if(is_halved_out)
1180  {
1181  PipelineDepth = static_cast<int>(HDL->get_flopocowrapper()->get_FUPipelineDepth(
1182  fu_base_name, prec, prec / 2, pipe_parameters[stage_index]));
1183  }
1184  else
1185  {
1186  PipelineDepth = static_cast<int>(
1187  HDL->get_flopocowrapper()->get_FUPipelineDepth(fu_base_name, prec, prec, pipe_parameters[stage_index]));
1188  }
1189  }
1190 #endif
1191  BackendFlowRef flow = BackendFlow::CreateFlow(parameters, "Characterization", device);
1193  flow->GenerateSynthesisScripts(fu->get_name(), SM, hdl_files, aux_files);
1194  PRINT_OUT_MEX(OUTPUT_LEVEL_VERBOSE, output_level, "Performing characterization of functional unit " + fu_name);
1195 #ifndef NDEBUG
1196  if(not dummy_synthesis)
1197 #endif
1198  {
1199  if(constPort < n_ports && is_commutative && constPort > has_first_synthesis_id && prev_area_characterization &&
1201  {
1203  }
1204  else
1205  {
1206  flow->ExecuteSynthesis();
1207  has_first_synthesis_id = constPort;
1210  fu->area_m = flow->get_used_resources();
1211  }
1212  }
1213 #ifndef NDEBUG
1214  else
1215  {
1217  }
1218 #endif
1221  for(const auto& op : ops)
1222  {
1223  auto* new_op = GetPointer<operation>(op);
1224  time_infoRef synthesis_results;
1225 #ifndef NDEBUG
1226  if(not dummy_synthesis)
1227 #endif
1228  {
1229  if(constPort < n_ports && is_commutative && constPort > has_first_synthesis_id &&
1231  {
1232  synthesis_results = prev_timing_characterization;
1233  }
1234  else
1235  {
1236  synthesis_results = flow->get_timing_results();
1237  }
1238  }
1239 #ifndef NDEBUG
1240  else
1241  {
1242  synthesis_results = time_info::factory(parameters);
1243  synthesis_results->set_execution_time(7.75);
1244  }
1245 #endif
1246  double exec_time = 0.0;
1247  if(synthesis_results)
1248  {
1249  exec_time = synthesis_results->get_execution_time();
1250  }
1251 
1252  if(!new_op->time_m)
1253  {
1254  new_op->time_m = time_info::factory(parameters);
1255  }
1256 
1257  if(n_pipe_parameters > 0)
1258  {
1259  new_op->time_m->set_stage_period(time_info::stage_period_DEFAULT);
1260  new_op->time_m->set_execution_time(time_info::execution_time_DEFAULT, time_info::cycles_time_DEFAULT);
1261  const ControlStep ii_default(time_info::initiation_time_DEFAULT);
1262  new_op->time_m->set_initiation_time(ii_default);
1263 
1264  unsigned int n_cycles;
1265  n_cycles = static_cast<unsigned>(std::stoul(pipe_parameters[stage_index]));
1266  new_op->pipe_parameters = pipe_parameters[stage_index];
1267 
1268  if(n_cycles > 0 && PipelineDepth != 0)
1269  {
1270  new_op->time_m->set_stage_period(exec_time);
1271  const ControlStep ii(1u);
1272  new_op->time_m->set_initiation_time(ii);
1273  if(PipelineDepth == -1)
1274  {
1275  new_op->time_m->set_execution_time(exec_time, n_cycles + 1);
1276  }
1277  else
1278  {
1279  new_op->time_m->set_execution_time(exec_time, static_cast<unsigned int>(PipelineDepth) + 1);
1280  }
1281  }
1282  else if(PipelineDepth == 0)
1283  {
1284  new_op->time_m->set_execution_time(exec_time);
1285  }
1286  else
1287  {
1288  new_op->time_m->set_execution_time(exec_time, n_cycles);
1289  }
1290  }
1291  else if(new_op->time_m->get_cycles() == 0)
1292  {
1293  new_op->time_m->set_execution_time(exec_time, time_info::cycles_time_DEFAULT);
1294  }
1295  else
1296  {
1297  new_op->time_m->set_stage_period(exec_time);
1298  }
1299  }
1300 
1301 #ifndef NDEBUG
1302  if(not dummy_synthesis)
1303 #endif
1304  {
1305  if(constPort < n_ports && is_commutative && constPort == has_first_synthesis_id &&
1306  flow->get_used_resources() && flow->get_timing_results())
1307  {
1310  THROW_ASSERT(prev_area_characterization, "expected a previous synthesis result");
1311  THROW_ASSERT(prev_timing_characterization, "expected a previous synthesis result");
1312  }
1313  }
1314  completed.insert(fu->functional_unit_name);
1315  }
1316  else
1317  {
1320  }
1321 }
1322 
1323 const std::string RTLCharacterization::ComputeComponent(const std::string& input) const
1324 {
1325  std::vector<std::string> component_cell = SplitString(input, ",");
1326  THROW_ASSERT(component_cell.size() > 0, input);
1327  std::vector<std::string> component_or_cell = SplitString(component_cell[0], "-");
1328  THROW_ASSERT(component_or_cell.size() == 2, component_or_cell[0]);
1329  return component_or_cell[0];
1330 }
1331 
1333 {
1335  std::vector<std::string> component_cells = SplitString(input, ",");
1336  for(const auto& component_cell : component_cells)
1337  {
1338  std::vector<std::string> component_or_cell = SplitString(component_cell, "-");
1339  ;
1340  THROW_ASSERT(component_or_cell.size() == 2, component_cell);
1341  THROW_ASSERT(component_or_cell[0] == component, component_or_cell[0] + " vs " + component);
1342  ret.insert(component_or_cell[1]);
1343  }
1344  return ret;
1345 }
Input function used to read the technology data structures.
void add_connection(structural_objectRef src, structural_objectRef dest)
Create a connection between a source structural object and a destination structural object...
#define MEMORY_CTRL_TYPE_DPROXY
#define CHANNELS_TYPE_MEM_ACC_N1
#define register_AR_NORETIME_INT
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
TVMValue param[3]
Collect information about resource area.
const fu_map_type & get_library_fu() const
Return the list of the resources contained into the given library.
refcount< structural_type_descriptor > structural_type_descriptorRef
RefCount type definition of the structural_type_descriptor class structure.
#define register_AR_NORETIME_UINT
#define CHANNELS_TYPE_MEM_ACC_NN
#define START_PORT_NAME
technology_nodeRef get_fu(const std::string &fu_name, const std::string &Library) const
Return the reference to a component given its name.
void resize_port(const structural_objectRef &port, unsigned int prec)
resize the port w.r.t a given precision
Structure representing the most relevant information about the type of a structural object...
const std::string & get_id() const
Return the identifier associated with the structural_object.
void xwrite_characterization(xml_element *nodeRoot)
Add the characterization to the output file.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
#define LUT_EXPR_STD
std::string fu_template_parameters
Template parameters.
void add_output_register(structural_managerRef SM, structural_objectRef e_port, structural_objectRef circuit, structural_objectRef reset_port, structural_objectRef port_out, const std::string &port_prefix, structural_objectRef clock_port, const std::string &register_library)
const structural_objectRef get_circ() const
Get a reference to circ field.
const int output_level
The output level.
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.
technology_nodeRef get_fu(const std::string &name) const
int input[SIZE]
Definition: hash.h:1
DesignFlowStep_Status Exec() override
Perform RTL characterization of the modules with respect to the target device.
unsigned int get_out_port_size() const
Return the number of output ports.
RelationshipType
The relationship type.
DesignFlowStepFactoryConstRef CGetDesignFlowStepFactory() const override
Return the factory to create this type of steps.
Source must be executed to satisfy target.
area_infoRef prev_area_characterization
The area model of the last characterization.
The base class for design step.
std::string functional_unit_name
name of the functional unit.
void add_input_register(structural_objectRef port_in, const std::string &register_library, const std::string &port_prefix, structural_objectRef reset_port, structural_objectRef circuit, structural_objectRef clock_port, structural_objectRef e_port, structural_managerRef SM)
This class manages the circuit structures.
refcount< area_info > area_infoRef
refcount definition of the class
Definition: area_info.hpp:121
Collect information about resource performance.
const structural_objectRef get_in_port(unsigned int n) const
Return the ith input port.
virtual structural_objectRef find_member(const std::string &id, so_kind type, const structural_objectRef owner) const =0
Return the object named id of a given type which belongs to or it is associated with the object...
Definition of hash function for EdgeDescriptor.
Definition: graph.hpp:1321
const std::string & get_name() const override
Return the name of the operation.
#define MEMORY_TYPE_SYNCHRONOUS_SDS_BUS
#define LIBRARY_STD_FU
standard library where all standard HLS resources are defined
xml_text_node * add_child_text(const std::string &content)
Append a new text node.
Definition: xml_node.cpp:68
Class specification of the manager of the technology library data structures.
std::string characterizing_constant_value
Value used during the characterization of this instance.
This class specifies the characteristic of a particular functional unit.
const CustomSet< std::string > cells
The cells to be characterized.
#define MEMORY_TYPE_ASYNCHRONOUS
#define MEMORY_CTRL_TYPE_PROXY
std::string channels_type
Specify the type of the channel the functional unit is compliant with.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define MEMORY_CTRL_TYPE_SPROXY
#define max
Definition: backprop.h:17
s_type type
The type of the port or the signal.
#define CLOCK_PORT_NAME
standard name for ports
static std::string GetCurrentTimeStamp()
Return a timestamp of the current time.
Definition: utility.cpp:55
#define MEMORY_TYPE_SYNCHRONOUS_UNALIGNED
time_infoRef prev_timing_characterization
The time model of the last characterization.
const CustomSet< std::string > ComputeCells(const std::string &input) const
Extract the cell lists.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
virtual std::string GenerateSynthesisScripts(const std::string &fu_name, const structural_managerRef SM, const std::list< std::string > &hdl_files, const std::list< std::string > &aux_files)
Generates the synthesis scripts for the specified design.
unsigned int has_first_synthesis_id
The id of the first analyzed cell of a sequence of cells which differ for the position of the constan...
area_infoRef area_m
This variable stores the resource information of the component.
void fix_proxies_execution_time_std()
Fix execution/stage period value for proxies and bounded memory controllers.
void set_top_info(const std::string &id, const technology_managerRef &LM, const std::string &Library="")
CustomOrderedSet< std::string > completed
set of units completed with success
static const double stage_period_DEFAULT
zero means that the operation last in ceil(execution_time/clock_period)
Definition: time_info.hpp:106
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
Class specification of the data structures used to manage technology information. ...
RTLCharacterization(const generic_deviceRef _device, const std::string &_cells, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
static structural_objectRef add_port(const std::string &id, port_o::port_direction pdir, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port.
static bool resize_if_busport(unsigned long long bus_size_bitsize, unsigned long long bus_addr_bitsize, unsigned long long bus_data_bitsize, unsigned long long bus_tag_bitsize, structural_objectRef port)
auxiliary function used to resize the bus ports with respect to their associated bus size ...
const structural_objectRef get_out_port(unsigned int n) const
Return the ith output port.
Classes to describe design flow graph.
#define PORT_VECTOR_N_PORTS
Autoheader includes.
void write_to_file_formatted(const std::filesystem::path &filename)
Write the document to a file.
static const std::string ComputeSignature(const TechnologyFlowStep_Type technology_flow_step_type)
Compute the signature of a technology flow step.
static const unsigned int cycles_time_DEFAULT
zero means that the operation is not pipelined
Definition: time_info.hpp:105
#define ARRAY_1D_STD_BRAM_NN
#define LIBRARY_STD
standard library where all built-in ports are defined.
xml_element * create_root_node(const std::string &_name)
Creates the root node.
#define ARRAY_1D_STD_BRAM
refcount< HDL_manager > HDL_managerRef
refcount definition of the class
Factory for technology flow step.
const operation_vec & get_operations() const
Return the operations that the functional unit can handle.
#define MEMORY_TYPE_SYNCHRONOUS_SDS
#define PIPE_PARAMETER
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
utility function used to read files.
const std::string component
The component to be characterized.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
refcount< HLS_manager > HLS_managerRef
refcount definition of the class
static BackendFlowRef CreateFlow(const ParameterConstRef Param, const std::string &flow_name, const generic_deviceRef _device)
Creates the flow specification based on the given parameters.
virtual void ExecuteSynthesis()
Executes the synthesis with the implemented flow.
void SetParameter(const std::string &name, const std::string &value)
Set a parameter value.
#define LIBRARY_PC
standard library for parallel controller
#define register_AR_NORETIME
register with asynchronous reset no retime
virtual enum so_kind get_kind() const =0
Virtual function used to find the real type of a structural_object instance.
Class for performing RTL characterization.
#define MEMLOAD_STD
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This package is used by all HLS packages to manage resource constraints and characteristics.
#define MEMSTORE_STD
#define GET_CLASS_NAME(meth)
Macro returning the name of a class.
Definition: utility.hpp:102
#define TEST_MUL_MUX_8
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
Wrapper of design_flow.
refcount< structural_manager > structural_managerRef
RefCount type definition of the structural_manager class structure.
void type_resize(unsigned long long new_bit_size)
Just resize the size of the bits of the object.
static const double execution_time_DEFAULT
Definition: time_info.hpp:103
#define BMEMORY_STD
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
void fix_execution_time_std()
Fix the execution time by removing set/hold/pad timings.
#define MEMORY_CTRL_TYPE_PROXYN
structural_objectRef add_constant(std::string id, structural_objectRef owner, structural_type_descriptorRef type, std::string value, unsigned int treenode=0)
Create a new constant;.
structural_objectRef add_module_from_technology_library(const std::string &id, const std::string &fu_name, const std::string &library_name, const structural_objectRef owner, const technology_managerConstRef TM)
Create a new object starting from a library component.
static const ControlStep initiation_time_DEFAULT
Definition: time_info.hpp:104
std::map< std::string, technology_nodeRef > fu_map_type
typedef for the identification of the functional units contained into the library ...
#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
unsigned int get_in_port_size() const
Return the number of input ports.
This file contains the definition of the configurable flow for generating and executing synthesis scr...
void fix_muxes()
fix the estimation of mux timing
const technology_managerRef TM
Technology manager.
#define GET_TYPE_SIZE(structural_obj)
Macro returning the size of the type of a structural object.
refcount< T > lock() const
Definition: refcount.hpp:212
This class describes all classes used to represent a structural object.
const structural_type_descriptorRef & get_typeRef() const
Return the type descriptor of the structural_object.
static area_infoRef factory(const ParameterConstRef &Param)
Factory method.
Definition: area_info.cpp:52
library_managerRef LM
Library manager.
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
#define register_AR_NORETIME_REAL
#define ASSIGN
constant string identifying the operation performed by an assignment.
Definition: op_graph.hpp:224
~RTLCharacterization() override
Destructor.
static structural_objectRef add_sign(std::string id, structural_objectRef owner, structural_type_descriptorRef sign_type, unsigned int treenode=0)
Create a new signal.
#define MEMORY_CTRL_TYPE_DPROXYN
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
std::string GetName() const override
Return the name of this design step.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
const bool dummy_synthesis
True if we are performing dummy synthesis.
#define BMEMORY_STDN
std::string memory_type
Specify the type of memory the functional unit is compliant with.
const generic_deviceRef device
device information
std::string GetSignature() const override
Return a unified identifier of this design step.
#define MEMORY_CTRL_TYPE_SPROXYN
this class is used to manage the command-line or XML options.
Wrapper to FloPoCo for VHDL code generation.
#define MUX_GATE_STD
#define ASSIGN_VECTOR_BOOL_STD
Some macro used to interface with the XML library.
Not parsed functionality manager.
virtual void AnalyzeFu(const technology_nodeRef f_unit)
Analyze all the cells built starting from a template.
void specialize_fu(const module *mod, unsigned int prec, unsigned int bus_data_bitsize, unsigned int bus_addr_bitsize, unsigned int bus_size_bitsize, unsigned int bus_tag_bitsize, size_t portsize_value)
Performing the specialization of the given object.
#define RESET_PORT_NAME
refcount< time_info > time_infoRef
refcount definition of the class
Definition: time_info.hpp:110
Class implementation of the structural_manager.
time_infoRef get_timing_results() const
Returns the timing information.
unsigned counter[N_THREADS]
Definition: data.c:3
Generic device description.
std::string get_library_name() const
void AnalyzeCell(functional_unit *fu, const unsigned int prec, const std::vector< std::string > &portsize_parameters, const size_t portsize_index, const std::vector< std::string > &pipe_parameters, const size_t stage_index, const unsigned int constPort, const bool is_commutative, size_t max_lut_size) override
Analyze the single cell.
Class specification of the manager for each library.
static void resize_std_port(unsigned long long bitsize_variable, unsigned long long n_elements, int debug_level, structural_objectRef port)
auxiliary function used to resize the standard ports
void xwrite_device_file()
Generate the output file.
int debug_level
The debug level.
#define CHANNELS_TYPE_MEM_ACC_11
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
#define PRINT_OUT_MEX(profLevel, curprofLevel, mex)
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
std::vector< technology_nodeRef > operation_vec
Type definition of a vector of functional_unit.
bool exist_NP_functionality(NP_functionaly_type type) const
Return true in case there exist a functionaly of the given type.
#define MULTIPLIER_STD
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
area_infoRef get_used_resources() const
Returns the list of used resources.
This class describes a generic module.
static structural_objectRef add_port_vector(std::string id, port_o::port_direction pdir, unsigned int n_ports, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port_vector.
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
const std::string ComputeComponent(const std::string &input) const
Extract the component name from list of cells.
library_managerRef get_library_manager(const std::string &Name) const
Return the library data structure corresponding to the given library id.
Base class for technology flow steps.
std::string get_library(const std::string &Name) const
Return the higher priority library where the given component is stored.
void get_library_parameters(std::vector< std::string > &parameters) const
fill a vector with the library parameters in case it there exists a LIBRARY based description...
Step which loads device dependent technology information.
#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