PandA-2024.02
liveness.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  */
46 #include "liveness.hpp"
48 
50 #include "Parameter.hpp"
51 #include "constant_strings.hpp"
52 
54 #include "basic_block.hpp"
55 
57 #include "hls.hpp"
58 #include "hls_manager.hpp"
59 
61 #include "tree_manager.hpp"
62 #include "tree_node.hpp"
63 
64 #include "loop.hpp"
65 #include "loops.hpp"
66 
69 
71  : TreeM(_HLSMgr->get_tree_manager()), Param(_Param), null_vertex_string("NULL_VERTEX"), HLSMgr(_HLSMgr)
72 
73 {
74 }
75 
76 liveness::~liveness() = default;
77 
78 bool liveness::is_defined(unsigned int var) const
79 {
80  if(var_op_definition.find(var) != var_op_definition.end())
81  {
82  return true;
83  }
84 
85  return false;
86 }
87 
88 void liveness::set_live_in(const vertex& v, unsigned int var)
89 {
90  live_in[v].insert(var);
91 }
92 
94 {
95  live_in[v].insert(live_set.begin(), live_set.end());
96 }
97 
100 {
101  live_in[v].insert(first, last);
102 }
103 
104 void liveness::erase_el_live_in(const vertex& v, unsigned int var)
105 {
106  live_in[v].erase(var);
107 }
108 
110 {
111  if(live_in.find(v) != live_in.end())
112  {
113  return live_in.find(v)->second;
114  }
115  else
116  {
117  return empty_set;
118  }
119 }
120 
121 void liveness::set_live_out(const vertex& v, unsigned int var)
122 {
123  live_out[v].insert(var);
124 }
125 
127 {
128  live_out[v].insert(vars.begin(), vars.end());
129 }
130 
133 {
134  live_out[v].insert(first, last);
135 }
136 
137 void liveness::erase_el_live_out(const vertex& v, unsigned int var)
138 {
139  live_out[v].erase(var);
140 }
141 
143 {
144  if(live_out.find(v) != live_out.end())
145  {
146  return live_out.find(v)->second;
147  }
148  else
149  {
150  return empty_set;
151  }
152 }
153 
154 vertex liveness::get_op_where_defined(unsigned int var) const
155 {
157  "var never defined " + TreeM->get_tree_node_const(var)->ToString());
158  return var_op_definition.find(var)->second;
159 }
160 
161 bool liveness::has_op_where_defined(unsigned int var) const
162 {
163  return (var_op_definition.find(var) != var_op_definition.end());
164 }
165 
166 const CustomOrderedSet<vertex>& liveness::get_state_in(vertex state, vertex op, unsigned int var) const
167 {
168  THROW_ASSERT(state_in_definitions.find(state) != state_in_definitions.end(), "state never used " + get_name(state));
169  THROW_ASSERT(state_in_definitions.find(state)->second.find(op) != state_in_definitions.find(state)->second.end(),
170  "op never used in state " + get_name(state));
171  THROW_ASSERT(state_in_definitions.find(state)->second.find(op)->second.find(var) !=
172  state_in_definitions.find(state)->second.find(op)->second.end(),
173  "var never used in the given state. Var: " + std::to_string(var));
174  return state_in_definitions.find(state)->second.find(op)->second.find(var)->second;
175 }
176 
177 bool liveness::has_state_in(vertex state, vertex op, unsigned int var) const
178 {
179  if(state_in_definitions.find(state) == state_in_definitions.end())
180  {
181  return false;
182  }
183  if(state_in_definitions.find(state)->second.find(op) == state_in_definitions.find(state)->second.end())
184  {
185  return false;
186  }
187  if(state_in_definitions.find(state)->second.find(op)->second.find(var) ==
188  state_in_definitions.find(state)->second.find(op)->second.end())
189  {
190  return false;
191  }
192  return true;
193 }
194 
195 void liveness::add_state_in_for_var(unsigned int var, vertex op, vertex state, vertex state_in)
196 {
197  state_in_definitions[state][op][var].insert(state_in);
198 }
199 
200 const CustomOrderedSet<vertex>& liveness::get_state_out(vertex state, vertex op, unsigned int var) const
201 {
203  "state never used " + get_name(state));
204  THROW_ASSERT(state_out_definitions.find(state)->second.find(op) != state_out_definitions.find(state)->second.end(),
205  "op never used in state " + get_name(state));
206  THROW_ASSERT(state_out_definitions.find(state)->second.find(op)->second.find(var) !=
207  state_out_definitions.find(state)->second.find(op)->second.end(),
208  "var never used in the given state. Var: " + std::to_string(var));
209  return state_out_definitions.find(state)->second.find(op)->second.find(var)->second;
210 }
211 
212 bool liveness::has_state_out(vertex state, vertex op, unsigned int var) const
213 {
214  if(state_out_definitions.find(state) == state_out_definitions.end())
215  {
216  return false;
217  }
218  if(state_out_definitions.find(state)->second.find(op) == state_out_definitions.find(state)->second.end())
219  {
220  return false;
221  }
222  if(state_out_definitions.find(state)->second.find(op)->second.find(var) ==
223  state_out_definitions.find(state)->second.find(op)->second.end())
224  {
225  return false;
226  }
227  return true;
228 }
229 
230 void liveness::add_state_out_for_var(unsigned int var, vertex op, vertex state, vertex state_in)
231 {
232  state_out_definitions[state][op][var].insert(state_in);
233 }
234 
236 {
237  THROW_ASSERT(ending_operations.find(op) != ending_operations.end(), "op never ending in a state ");
238  return ending_operations.find(op)->second;
239 }
240 
242 {
243  THROW_ASSERT(running_operations.find(op) != running_operations.end(), "op never running in a state ");
244  return running_operations.find(op)->second;
245 }
246 
247 const std::string& liveness::get_name(vertex v) const
248 {
249  if(v == NULL_VERTEX)
250  {
251  return null_vertex_string;
252  }
253  THROW_ASSERT(names.find(v) != names.end(), "state without a name");
254  return names.find(v)->second;
255 }
256 
258 {
259  // if(!HLS)
260  const CustomOrderedSet<vertex>& op1_run = get_state_where_run(op1);
261  const CustomOrderedSet<vertex>& op2_run = get_state_where_run(op2);
262 
263  auto FB = HLSMgr->GetFunctionBehavior(HLS->functionId);
264  if(FB->is_pipeline_enabled() && !FB->is_simple_pipeline())
265  {
266  const OpGraphConstRef dfg = FB->CGetOpGraph(FunctionBehavior::DFG);
267  unsigned int bb_index1 = GET_BB_INDEX(dfg, op1);
268  unsigned int bb_index2 = GET_BB_INDEX(dfg, op2);
269  const CustomUnorderedMap<unsigned int, vertex>& bb_index_map =
270  FB->CGetBBGraph(FunctionBehavior::FBB)->CGetBBGraphInfo()->bb_index_map;
271  vertex bb_1 = bb_index_map.find(bb_index1)->second;
272  vertex bb_2 = bb_index_map.find(bb_index2)->second;
273 
274  auto loops = HLSMgr->GetFunctionBehavior(HLS->functionId)->GetLoops()->GetList();
275  for(const auto& loop : loops)
276  {
277  int initiation_time = FB->get_initiation_time();
278  THROW_ASSERT(loop->num_blocks() != 1, "The loop has more than one basic block");
279  auto bbs = loop->get_blocks();
280  for(auto bb : bbs)
281  {
282  for(auto s_pair : HLS->STG->GetAstg()->GetStateTransitionGraphInfo()->vertex_to_state_id)
283  {
284  auto ids = HLS->STG->CGetAstg()->CGetStateInfo(std::get<0>(s_pair))->BB_ids;
285  for(auto id : ids)
286  {
287  if(id ==
288  HLSMgr->CGetFunctionBehavior(HLS->functionId)->CGetBBGraph()->CGetBBNodeInfo(bb)->get_bb_index())
289  {
290  if(HLS->STG->GetAstg()->GetStateInfo(std::get<0>(s_pair))->loopId != 0 &&
291  HLS->STG->GetAstg()->GetStateInfo(std::get<0>(s_pair))->loopId !=
292  HLSMgr->CGetFunctionBehavior(HLS->functionId)->CGetBBGraph()->CGetBBNodeInfo(bb)->loop_id)
293  {
294  THROW_ERROR("Attempting to change the loopId of state " +
295  HLS->STG->GetAstg()->GetStateInfo(std::get<0>(s_pair))->name);
296  }
297  HLS->STG->GetAstg()->GetStateInfo(std::get<0>(s_pair))->loopId =
298  HLSMgr->CGetFunctionBehavior(HLS->functionId)->CGetBBGraph()->CGetBBNodeInfo(bb)->loop_id;
299  }
300  }
301  }
302  }
303 
304  bool cond1 = false;
305  bool cond2 = false;
306  if(bbs.find(bb_1) != bbs.end())
307  {
308  cond1 = true;
309  for(const auto s1 : op1_run)
310  {
311  auto info = HLS->STG->GetAstg()->GetStateInfo(s1);
312  THROW_ASSERT(info->loopId == 0 || info->loopId == loop->GetId(),
313  "The same operation is performed in multiple loops");
314  }
315  }
316  if(bbs.find(bb_2) != bbs.end())
317  {
318  cond2 = true;
319  for(const auto s2 : op2_run)
320  {
321  auto info = HLS->STG->GetAstg()->GetStateInfo(s2);
322  THROW_ASSERT(info->loopId == 0 || info->loopId == loop->GetId(),
323  "The same operation is performed in multiple loops");
324  }
325  }
326 
327  if(cond1 && cond2)
328  {
329  auto stg = HLS->STG->GetAstg();
330  for(const auto s1 : op1_run)
331  {
332  std::queue<vertex> to_analyze;
333  std::set<vertex> analyzed;
334  std::queue<vertex> next_frontier;
335  to_analyze.push(s1);
336  vertex src;
337  int distance = 1;
338  graph::out_edge_iterator out_edge, out_edge_end;
339  while(to_analyze.size() > 0)
340  {
341  src = to_analyze.front();
342  to_analyze.pop();
343  analyzed.insert(src);
344  for(boost::tie(out_edge, out_edge_end) = boost::out_edges(src, *stg); out_edge != out_edge_end;
345  ++out_edge)
346  {
347  vertex tgt = boost::target(*out_edge, *stg);
348  if(op1_run.find(tgt) != op1_run.end())
349  {
350  continue;
351  }
352 
353  if(op2_run.find(tgt) != op2_run.end())
354  {
355  if(distance % initiation_time == 0)
356  {
357  return false;
358  }
359  continue;
360  }
361 
362  if(analyzed.find(tgt) != analyzed.end())
363  {
364  next_frontier.push(tgt);
365  }
366  }
367  if(to_analyze.size() == 0)
368  {
369  to_analyze = next_frontier;
370  distance++;
371  }
372  }
373  }
374  }
375  }
376  }
377 
378  {
379  for(const auto s1 : op1_run)
380  {
381  if(op2_run.find(s1) != op2_run.end())
382  {
383  return true;
384  }
385  }
386  return false;
387  }
388  return false;
389 }
390 
392 {
393  THROW_ASSERT(start_op.find(state) != start_op.end(),
394  "start_op map does not have this chained vertex " + get_name(state));
395  return start_op.find(state)->second;
396 }
397 
399 {
400  start_op[state] = op;
401 }
402 
404 {
405  if(cdg->CGetBBNodeInfo(v1)->cer == cdg->CGetBBNodeInfo(v2)->cer)
406  {
407  return v1 == v2;
408  }
409  else if(cdg->CGetBBNodeInfo(v1)->cer > cdg->CGetBBNodeInfo(v2)->cer)
410  {
411  InEdgeIterator ie_it, ie_it_end;
412  for(boost::tie(ie_it, ie_it_end) = boost::in_edges(v1, *cdg); ie_it != ie_it_end; ++ie_it)
413  {
414  vertex cer0_v1 = boost::source(*ie_it, *cdg);
415  bool current_res = non_in_parallel(cer0_v1, v2, cdg);
416  if(!current_res)
417  {
418  return current_res;
419  }
420  }
421  return true;
422  }
423  else
424  {
425  InEdgeIterator ie_it, ie_it_end;
426  for(boost::tie(ie_it, ie_it_end) = boost::in_edges(v2, *cdg); ie_it != ie_it_end; ++ie_it)
427  {
428  vertex cer0_v2 = boost::source(*ie_it, *cdg);
429  bool current_res = non_in_parallel(v1, cer0_v2, cdg);
430  if(!current_res)
431  {
432  return current_res;
433  }
434  }
435  return true;
436  }
437 }
void add_state_in_for_var(unsigned int var, vertex op, vertex state, vertex state_in)
put into relation for a given variable used in a state the state from which the variable comes ...
Definition: liveness.cpp:195
Class specification to contain liveness information.
hlsRef HLS
Definition: liveness.hpp:114
Data structure representing the entire HLS information.
void add_state_out_for_var(unsigned int var, vertex op, vertex state, vertex state_in)
put into relation for a given variable defined in a state the state to which the variable goes ...
Definition: liveness.cpp:230
std::map< vertex, std::map< vertex, std::map< unsigned int, CustomOrderedSet< vertex > > > > state_out_definitions
store along which transitions the variable has to be stored
Definition: liveness.hpp:109
~liveness()
Destructor.
std::string ToString() const
Print this node as string in gimple format.
This file contains the structures needed to manage a graph that will represent the state transition g...
const CustomOrderedSet< vertex > & get_state_where_end(vertex op) const
return in which support vertex the operation is ending
Definition: liveness.cpp:235
std::map< vertex, std::map< vertex, std::map< unsigned int, CustomOrderedSet< vertex > > > > state_in_definitions
store where a variable comes from given a support state and an operation
Definition: liveness.hpp:106
const tree_managerRef TreeM
The tree manager.
Definition: liveness.hpp:76
string target
Definition: lenet_tvm.py:16
bool has_op_where_defined(unsigned int var) const
return true in case there exist an operation defining it
Definition: liveness.cpp:161
void erase_el_live_out(const vertex &v, unsigned int var)
erase a variable from the live out
Definition: liveness.cpp:137
const CustomOrderedSet< unsigned int > empty_set
used to return a reference to an empty set
Definition: liveness.hpp:91
std::map< vertex, CustomOrderedSet< vertex > > running_operations
store where an operation run and need its input
Definition: liveness.hpp:103
StateTransitionGraphRef GetAstg()
Returns pointer to state transition graph created.
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
Definition: graph.hpp:1310
#define GET_BB_INDEX(data, vertex_index)
Macro returning the index of the basic block which the node belongs to.
Definition: op_graph.hpp:435
const CustomOrderedSet< vertex > & get_state_in(vertex state, vertex op, unsigned int var) const
given a variable and a state it returns the set of states from which the variable may come ...
Definition: liveness.cpp:166
bool has_state_out(vertex state, vertex op, unsigned int var) const
return true in case the variable for a given op and a given state has a state out ...
Definition: liveness.cpp:212
vertex get_start_op(vertex state) const
Return the operation from which the computation start.
Definition: liveness.cpp:391
void set_live_in(const vertex &v, unsigned int var)
Store a variable alive at the input of the given vertex.
Definition: liveness.cpp:88
std::map< vertex, vertex > start_op
map a chained vertex with one of the starting operation
Definition: liveness.hpp:207
bool are_in_conflict(vertex op1, vertex op2) const
states if two operations are in conflict (i.e.
Definition: liveness.cpp:257
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
bool non_in_parallel(vertex v1, vertex v2, const BBGraphConstRef cdg) const
Definition: liveness.cpp:403
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
std::map< vertex, CustomOrderedSet< unsigned int > > live_in
This is the map from each vertex to the set of variables live at the input of vertex.
Definition: liveness.hpp:82
std::map< unsigned int, vertex > var_op_definition
store which operation defines the variable
Definition: liveness.hpp:97
liveness(const HLS_managerRef HLSMgr, const ParameterConstRef Param)
Constructor.
Definition: liveness.cpp:70
Basic block control flow graph with feedback.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
This file contains the structures needed to manage a graph that will represent the state transition g...
const HLS_managerRef HLSMgr
Definition: liveness.hpp:115
const CustomOrderedSet< unsigned int > & get_live_out(const vertex &v) const
Get the set of variables live at the output of a vertex.
Definition: liveness.cpp:142
Classes specification of the tree_node data structures.
void erase_el_live_in(const vertex &v, unsigned int var)
erase a variable from the live in
Definition: liveness.cpp:104
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
std::map< vertex, CustomOrderedSet< unsigned int > > live_out
This is the map from each vertex to the set of variables live at the output of vertex.
Definition: liveness.hpp:85
const StateTransitionGraphConstRef CGetAstg() const
Returns pointer to state transition graph created.
const CustomOrderedSet< vertex > & get_state_out(vertex state, vertex op, unsigned int var) const
given a variable and a state it returns the set of destination states where the variable may be used ...
Definition: liveness.cpp:200
std::map< vertex, std::string > names
store the name of each state
Definition: liveness.hpp:112
void set_start_op(vertex state, vertex op)
Set the starting operation for a specified chained state.
Definition: liveness.cpp:398
bool has_state_in(vertex state, vertex op, unsigned int var) const
return true in case the variable for a given op and a given state has a state in
Definition: liveness.cpp:177
void set_live_out(const vertex &v, const CustomOrderedSet< unsigned int > &vars)
Store the variables alive at the output of the given vertex.
Definition: liveness.cpp:126
std::map< vertex, CustomOrderedSet< vertex > > ending_operations
store where an operation is terminating its execution
Definition: liveness.hpp:100
Class specification of the basic_block structure.
const CustomOrderedSet< vertex > & get_state_where_run(vertex op) const
return in which support vertex the operation is running
Definition: liveness.cpp:241
interface of a loop
TYPE distance(TYPE position_x[nAtoms], TYPE position_y[nAtoms], TYPE position_z[nAtoms], int i, int j)
Definition: md_kernel_test.c:3
const BBNodeInfoConstRef CGetBBNodeInfo(const vertex node) const
Return the info associated with a basic block.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
interface of loops finding algorithm
this class is used to manage the command-line or XML options.
const std::string null_vertex_string
null vertex string
Definition: liveness.hpp:88
constant strings
unsigned int functionId
this is the identifier of the function to be implemented
Definition: hls.hpp:87
StateTransitionGraphManagerRef STG
Store the refcounted state transition graph.
Definition: hls.hpp:124
vertex get_op_where_defined(unsigned int var) const
return which operation defines the variable
Definition: liveness.cpp:154
Data structure definition for high-level synthesis flow.
bool is_defined(unsigned int var) const
return true in case the variable var for a given opoeration v has been defined
Definition: liveness.cpp:78
#define NULL_VERTEX
null vertex definition
Definition: graph.hpp:1305
const std::string & get_name(vertex v) const
return the name of the given state
Definition: liveness.cpp:247
Class specification of the manager of the tree structures extracted from the raw file.
const CustomOrderedSet< unsigned int > & get_live_in(const vertex &v) const
Get the set of variables live at the input of a vertex.
Definition: liveness.cpp:109
#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