PandA-2024.02
module_binding_check.hpp
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  */
38 #ifndef MODULE_BINDING_CHECK_HPP
39 #define MODULE_BINDING_CHECK_HPP
41 #include "check_clique.hpp"
42 #include "custom_map.hpp"
43 #include "custom_set.hpp"
44 #include "hls.hpp"
45 
46 #include <boost/property_map/property_map.hpp>
47 
48 #include <algorithm>
49 #include <limits>
50 #include <utility>
51 #include <vector>
52 
53 class fu_binding;
55 {
56  private:
59  using tree_index_rank_map_t = boost::associative_property_map<tree_index_rank_t>;
60  using tree_index_parent_map_t = boost::associative_property_map<tree_index_parent_t>;
61  using tree_index_dsets_t = boost::disjoint_sets<tree_index_rank_map_t, tree_index_parent_map_t>;
62 
67 
68  public:
70 
72  : tree_index_rank_pmap(tree_index_rank_map),
73  tree_index_parent_pmap(tree_index_parent_map),
74  binding(tree_index_rank_pmap, tree_index_parent_pmap)
75  {
76  }
77 };
78 
79 template <typename vertex_type>
80 struct module_binding_check : public check_clique<vertex_type>
81 {
82  private:
87 
95 
97  unsigned long long fu_prec;
98 
101 
104 
106  const hlsRef HLS;
107 
110 
113 
116 
119 
125  std::vector<CustomOrderedSet<unsigned int>> getOperationVariablesAtPort(vertex& operationVertex) const
126  {
127  std::vector<CustomOrderedSet<unsigned int>> variableVector;
128 
129  std::vector<HLS_manager::io_binding_type> vars_read =
130  HLSMgr->get_required_values(HLS->functionId, operationVertex);
131  for(auto& port_index : vars_read)
132  {
133  unsigned int tree_var = std::get<0>(port_index);
134  CustomOrderedSet<unsigned int> variablesAtPort;
135  if(tree_var != 0)
136  {
137  variablesAtPort.insert(tree_var);
138  }
139  variableVector.push_back(variablesAtPort);
140  }
141 
142  return variableVector;
143  }
144 
145  protected:
151  virtual double getOpSlack(vertex& operationVertex) const
152  {
153  if(starting_time.find(operationVertex)->second > controller_delay)
154  {
155  return slack_time.find(operationVertex)->second;
156  }
157  else if(controller_delay - starting_time.find(operationVertex)->second > slack_time.find(operationVertex)->second)
158  {
159  return 0;
160  }
161  else
162  {
163  return (slack_time.find(operationVertex)->second -
164  (controller_delay - starting_time.find(operationVertex)->second));
165  }
166  }
167 
169 
170  public:
171  //-----------------------------------------------------------------------------------------------
172  // methods
173 
174  module_binding_check(unsigned long long _fu_prec, double _area_resource, const hlsRef _HLS,
175  const HLS_managerRef _HLSMgr, const CustomUnorderedMap<vertex, double>& _slack_time,
176  const CustomUnorderedMap<vertex, double>& _starting_time, double _controller_delay,
177  module_register_binding_spec& _tree_index_dsets)
178  : fu_prec(_fu_prec),
179  area_resource(_area_resource),
180  tree_index_dsets(_tree_index_dsets),
181  HLS(_HLS),
182  HLSMgr(_HLSMgr),
183  slack_time(_slack_time),
184  starting_time(_starting_time),
185  controller_delay(_controller_delay),
186  is_disabled_slack_based_binding(false)
187  {
188  }
189 
191  : opSlacks(original.opSlacks),
192  input_variables(original.input_variables),
193  fu_prec(original.fu_prec),
194  area_resource(original.area_resource),
195  tree_index_dsets(original.tree_index_dsets),
196  HLS(original.HLS),
197  HLSMgr(original.HLSMgr),
198  slack_time(original.slack_time),
199  starting_time(original.starting_time),
200  controller_delay(original.controller_delay),
201  is_disabled_slack_based_binding(original.is_disabled_slack_based_binding)
202  {
203  }
204 
205  module_binding_check* clone() const override
206  {
207  return new module_binding_check(*this);
208  }
209 
210  module_binding_check& operator=(const module_binding_check&) = delete;
211 
212  ~module_binding_check() override = default;
213 
216  {
217  BOOST_FOREACH(C_vertex tempVertex, boost::vertices(graph))
218  {
219  opSlacks[tempVertex] = getOpSlack(Ruv2v[tempVertex]);
220  input_variables[tempVertex] = getOperationVariablesAtPort(Ruv2v[tempVertex]);
221  }
222 
223  CustomOrderedSet<unsigned int> tree_index_set;
224  CustomUnorderedMap<std::pair<unsigned int, unsigned int>, unsigned int> tree_var_resource_relation;
225  for(const auto& input_var : input_variables)
226  {
227  for(const auto& vars : input_var.second)
228  {
229  for(auto tree_var : vars)
230  {
231  tree_index_set.insert(tree_var);
232  tree_index_dsets.binding.make_set(tree_var);
233  if(HLS->Rliv->has_op_where_defined(tree_var))
234  {
235  vertex def_op = HLS->Rliv->get_op_where_defined(tree_var);
236  if(HLS->Rfu->is_assigned(def_op))
237  {
238  unsigned int fu_name = HLS->Rfu->get_assign(def_op);
239  unsigned int fu_index = HLS->Rfu->get_index(def_op);
241  {
242  if(tree_var_resource_relation.find(std::make_pair(fu_name, fu_index)) !=
243  tree_var_resource_relation.end())
244  {
245  tree_index_dsets.binding.union_set(
246  tree_var, tree_var_resource_relation.find(std::make_pair(fu_name, fu_index))->second);
247  }
248  else
249  {
250  tree_var_resource_relation[std::make_pair(fu_name, fu_index)] = tree_var;
251  }
252  }
253  }
254  }
255  }
256  }
257  }
258  }
259 
260  double cost(size_t clique_count) override
261  {
262  double area_muxes = 0;
263  for(const auto& input_var : input_variables)
264  {
265  for(const auto& vars : input_var.second)
266  {
267  if(vars.size() > 1)
268  {
269  area_muxes +=
270  HLS->allocation_information->estimate_muxNto1_area(fu_prec, static_cast<unsigned int>(vars.size()));
271  }
272  }
273  }
274  // std::cerr << "n_muxes " << n_muxes << " area_mux " << area_mux << " area_resource " << area_resource << "
275  // clique_count " << clique_count << " Area " << n_muxes*area_mux+area_resource*static_cast<double>(clique_count)
276  // << std::endl;
277  return area_muxes + area_resource * static_cast<double>(clique_count);
278  }
279 
280  size_t num_mux() override
281  {
282  size_t n_muxes = 0;
283  for(const auto& input_var : input_variables)
284  {
285  for(const auto& vars : input_var.second)
286  {
287  if(vars.size() > 1)
288  {
289  n_muxes += static_cast<size_t>(vars.size()) - 1;
290  }
291  }
292  }
293  return n_muxes;
294  }
295 
296  void update_after_join(C_vertex& rep, C_vertex& child) override
297  {
298  // aggiungo tutte le variabili in ingresso a child all'ingresso di rep
299 
300  // PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, 11, "prima di definizione di port number");
301  size_t port_number = input_variables[child].size();
302  // PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, 11, "definita port number");
303  std::vector<CustomOrderedSet<unsigned int>>& input_at_port = input_variables[rep];
304  std::vector<CustomOrderedSet<unsigned int>>& input_at_child = input_variables[child];
305  for(size_t i = 0; i < port_number; i++)
306  {
307  // PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, 11, "considero nuova porta");
308  BOOST_FOREACH(unsigned int temp_var, input_at_child[i])
309  {
310  // PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, 11, "considero nuova variabile di porta");
311  temp_var = tree_index_dsets.binding.find_set(temp_var);
312  (input_at_port[i]).insert(temp_var);
313  }
314  input_at_child[i].clear();
315  }
316  // PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, 11, "uscito dal doppio ciclo");
317  // imposto R_opSlacks di rep al minimo tra quelle di rep e di child
318  opSlacks[rep] = std::min(opSlacks[rep], opSlacks[child]);
319  // PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, 11, "impostato anche max multiplexer");
320  }
321 
322  /*
323  returns false if the two vertex are not compatible, true if the
324  two vertex can be inserted in the same clique
325  */
326  bool check_edge_compatibility(C_vertex& rep, C_vertex& other) override
327  {
328  double minSlack = std::min(opSlacks[rep], opSlacks[other]);
329  THROW_ASSERT(input_variables.find(rep) != input_variables.end(), "unexpected case");
330 
331  size_t port_number = input_variables[rep].size();
332  CustomOrderedSet<unsigned int> port_inputs;
333  CustomOrderedSet<unsigned int> port_inputs_rep, port_inputs_other;
334  double total_area_muxes_rep = 0, total_area_muxes_other = 0, total_area_muxes = 0;
335 
336  for(decltype(port_number) i = 0; i < port_number; i++)
337  {
338  for(auto temp_var : input_variables[rep][i])
339  {
340  temp_var = tree_index_dsets.binding.find_set(temp_var);
341  port_inputs.insert(temp_var);
342  port_inputs_rep.insert(temp_var);
343  }
344  for(auto temp_var : input_variables[other][i])
345  {
346  temp_var = tree_index_dsets.binding.find_set(temp_var);
347  port_inputs.insert(temp_var);
348  port_inputs_other.insert(temp_var);
349  }
350  auto n_mux_inputs = static_cast<size_t>(port_inputs.size());
351 
352  total_area_muxes +=
353  HLS->allocation_information->estimate_muxNto1_area(fu_prec, static_cast<unsigned int>(n_mux_inputs));
354  total_area_muxes_rep += HLS->allocation_information->estimate_muxNto1_area(
355  fu_prec, static_cast<unsigned int>(port_inputs_rep.size()));
356  total_area_muxes_other += HLS->allocation_information->estimate_muxNto1_area(
357  fu_prec, static_cast<unsigned int>(port_inputs_other.size()));
358 
359  if(!is_disabled_slack_based_binding && n_mux_inputs > 1 &&
360  HLS->allocation_information->estimate_muxNto1_area(fu_prec, static_cast<unsigned int>(n_mux_inputs)) >
361  area_resource)
362  {
363  return false;
364  }
365 
366  if(n_mux_inputs > 1 && HLS->allocation_information->estimate_muxNto1_delay(
367  fu_prec, static_cast<unsigned int>(n_mux_inputs)) > minSlack)
368  {
369  return false;
370  }
371 
372  port_inputs.clear();
373  port_inputs_rep.clear();
374  port_inputs_other.clear();
375  }
376  // if(total_area_muxes>0)
377  // std::cerr << "total_area_muxes " << total_area_muxes << " total_area_muxes_rep " << total_area_muxes_rep << "
378  // total_area_muxes_other " << total_area_muxes_other << std::endl;
379  if(!is_disabled_slack_based_binding &&
380  ((total_area_muxes + area_resource) >
381  (total_area_muxes_rep + area_resource + total_area_muxes_other + area_resource)))
382  {
383  return false;
384  }
385 
386  return true;
387  }
388 
389  bool check_no_mux_needed(C_vertex& rep, C_vertex& other) override
390  {
391  size_t port_number = input_variables[other].size();
392  CustomOrderedSet<size_t> port_inputs;
393 
394  for(decltype(port_number) i = 0; i < port_number; i++)
395  {
396  for(auto temp_var : input_variables[rep][i])
397  {
398  temp_var = tree_index_dsets.binding.find_set(temp_var);
399  port_inputs.insert(temp_var);
400  }
401  for(auto temp_var : input_variables[other][i])
402  {
403  temp_var = tree_index_dsets.binding.find_set(temp_var);
404  port_inputs.insert(temp_var);
405  }
406  if(port_inputs.size() > 1)
407  {
408  return false;
409  }
410 
411  port_inputs.clear();
412  }
413 
414  return true;
415  }
416 };
417 
418 template <typename vertex_type>
420 {
421  module_binding_check_no_filter(unsigned int _fu_prec, double _area_resource, const hlsRef _HLS,
422  const HLS_managerRef _HLSMgr, const CustomUnorderedMap<vertex, double>& _slack_time,
423  const CustomUnorderedMap<vertex, double>& _starting_time, double _controller_delay,
424  module_register_binding_spec& _tree_index_dsets)
425  : module_binding_check<vertex_type>(_fu_prec, _area_resource, _HLS, _HLSMgr, _slack_time, _starting_time,
426  _controller_delay, _tree_index_dsets)
427  {
429  }
430 
432  : module_binding_check<vertex_type>(original)
433  {
434  }
435 
436  protected:
437  double getOpSlack(vertex&) const override
438  {
440  }
441 };
442 
443 #endif // MODULE_BINDING_CHECK_HPP
boost::associative_property_map< tree_index_parent_t > tree_index_parent_map_t
boost::associative_property_map< tree_index_rank_t > tree_index_rank_map_t
module_binding_check_no_filter(const module_binding_check_no_filter &original)
bool has_op_where_defined(unsigned int var) const
return true in case there exist an operation defining it
Definition: liveness.cpp:161
CustomUnorderedMap< unsigned int, std::size_t > tree_index_rank_t
unsigned int get_assign(const vertex &v) const
Returns the functional unit assigned to the vertex.
Definition: fu_binding.cpp:242
const CustomUnorderedMap< vertex, double > & slack_time
reference to the vertex slack
double controller_delay
controller delay
tree_index_parent_t tree_index_parent_map
module_binding_check(unsigned long long _fu_prec, double _area_resource, const hlsRef _HLS, const HLS_managerRef _HLSMgr, const CustomUnorderedMap< vertex, double > &_slack_time, const CustomUnorderedMap< vertex, double > &_starting_time, double _controller_delay, module_register_binding_spec &_tree_index_dsets)
const HLS_managerRef HLSMgr
reference to the HLS Manager
double estimate_muxNto1_area(unsigned long long fu_prec, unsigned int mux_ins) const
Return the area due to mux with n-inputs.
AllocationInformationRef allocation_information
Store the technology information.
Definition: hls.hpp:115
module_binding_check(const module_binding_check &original)
void insert(node_tree **tree, int val)
Definition: tree.c:121
#define min(x, y)
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMapUnstable
Definition: custom_map.hpp:156
double area_resource
area resource
redefinition of map to manage ordered/unordered structures
unsigned long long fu_prec
resource precision
#define max
Definition: backprop.h:17
bool is_assigned(const vertex &v) const
return true in case the vertex has been previously assigned
Definition: fu_binding.cpp:210
boost::adjacency_matrix< boost::undirectedS, boost::property< boost::vertex_index_t, std::size_t >, edge_compatibility_selector > boost_cc_compatibility_graph
bulk compatibility graph
CustomUnorderedMap< C_vertex, double > opSlacks
slack associated with the Op
fu_bindingRef Rfu
Store the refcounted functional unit binding of the operations.
Definition: hls.hpp:121
module_register_binding_spec & tree_index_dsets
store the current state for binding
double estimate_muxNto1_delay(unsigned long long fu_prec, unsigned int mux_ins) const
Return the delay due to mux with n-inputs.
double cost(size_t clique_count) override
virtual double getOpSlack(vertex &operationVertex) const
Takes as input the node representing the operation and returns the maximum number of muxes that can b...
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
tree_index_parent_map_t tree_index_parent_pmap
CustomUnorderedMapUnstable< unsigned int, unsigned int > tree_index_parent_t
double getOpSlack(vertex &) const override
Takes as input the node representing the operation and returns the maximum number of muxes that can b...
redefinition of set to manage ordered/unordered structures
bool check_no_mux_needed(C_vertex &rep, C_vertex &other) override
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
General class used to describe a graph in PandA.
Definition: graph.hpp:771
This package is used by all HLS packages to manage resource constraints and characteristics.
void update_after_join(C_vertex &rep, C_vertex &child) override
livenessRef Rliv
data-structure containing the variable liveness
Definition: hls.hpp:127
module_binding_check * clone() const override
std::vector< CustomOrderedSet< unsigned int > > getOperationVariablesAtPort(vertex &operationVertex) const
Takes as input the vertex of an operation, and returns a vertex.
boost::disjoint_sets< tree_index_rank_map_t, tree_index_parent_map_t > tree_index_dsets_t
tree_index_rank_map_t tree_index_rank_pmap
void initialize_structures(boost_cc_compatibility_graph &graph, CustomUnorderedMap< C_vertex, vertex_type > &Ruv2v) override
bool check_edge_compatibility(C_vertex &rep, C_vertex &other) override
const hlsRef HLS
reference to HLS data structure
int original[DIMENSION_Y][DIMENSION_X]
Definition: boxfilter.h:1
module_binding_check_no_filter(unsigned int _fu_prec, double _area_resource, const hlsRef _HLS, const HLS_managerRef _HLSMgr, const CustomUnorderedMap< vertex, double > &_slack_time, const CustomUnorderedMap< vertex, double > &_starting_time, double _controller_delay, module_register_binding_spec &_tree_index_dsets)
unsigned int functionId
this is the identifier of the function to be implemented
Definition: hls.hpp:87
Class managing the functional-unit binding.
Definition: fu_binding.hpp:90
vertex get_op_where_defined(unsigned int var) const
return which operation defines the variable
Definition: liveness.cpp:154
boost::graph_traits< cc_compatibility_graph >::vertex_descriptor C_vertex
cc_compatibility_graph vertex
Data structure definition for high-level synthesis flow.
const CustomUnorderedMap< vertex, double > & starting_time
reference to the vertex starting time
unsigned int get_index(const vertex &v) const
Returns the index of functional unit assigned to the vertex.
Definition: fu_binding.cpp:261
CustomUnorderedMap< C_vertex, std::vector< CustomOrderedSet< unsigned int > > > input_variables
the set of input to every port of every clique.
#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:53 for PandA-2024.02 by doxygen 1.8.13