63 #include <boost/graph/random_spanning_tree.hpp> 71 const DesignFlowManagerConstRef _design_flow_manager)
83 switch(relationship_type)
89 if(
HLSMgr->GetFunctionBehavior(
funId)->is_simple_pipeline())
96 ret.insert(std::make_tuple(
HLSMgr->get_HLS(
funId)->module_binding_algorithm,
101 if(
HLSMgr->GetFunctionBehavior(
funId)->is_simple_pipeline())
131 std::vector<PSVSet>& vset)
140 while(vset.size() < num_vertices_g)
142 for(
const auto& i : spt_edges)
144 for(
const auto j : vset)
148 set.level = j.level + 1;
154 for(
const auto lvl : vset)
163 if(
set.
level % 2 == 0)
182 std::vector<PSVSet>& vset)
194 for(
const auto& i : spt_edges)
196 for(
const auto& j : vset)
200 set.level = j.level + 1;
204 distance =
set.level + 1;
210 else if(j.v == i.second)
212 set.level = j.level + 1;
216 distance =
set.level + 1;
223 for(
const auto& lvl : vset)
244 long unsigned int max = 0;
246 for(
const auto& e : dSet)
259 auto g2_vertices = boost::vertices(g2);
260 for(
auto iterator = g2_vertices.first; iterator != g2_vertices.second; ++iterator)
262 dSet.insert(std::make_pair(*iterator, boost::out_degree(*iterator, g2)));
268 for(
const auto& ed : e)
274 else if(v == ed.first)
288 std::random_device rd;
289 std::mt19937 generator(rd());
290 generator.seed(
parameters->getOption<
long unsigned int>(OPT_seed));
291 std::vector<PSVertex> p(num_vertices(g));
293 std::vector<PSVertex> component(boost::num_vertices(g));
294 size_t num_components = boost::connected_components(g, &component[0]);
295 PSVertex connection_ver_1 = *vertices(g).first;
296 for(
size_t count = 1; count < num_components; count++)
298 for(
size_t i = 0; i < num_vertices_g; i++)
300 if(component[i] == count)
302 auto connection_ver_2 =
PSVertex(i);
303 add_edge(connection_ver_1, connection_ver_2, g);
304 connection_ver_1 = connection_ver_2;
310 boost::random_spanning_tree(g, generator,
311 boost::root_vertex(root).predecessor_map(
312 boost::make_iterator_property_map(p.begin(), boost::get(boost::vertex_index, g))));
318 auto vertices_g = boost::vertices(g);
319 std::vector<PSE> spt_edges;
321 for(
auto iterator = vertices_g.first; iterator != vertices_g.second; ++iterator)
325 if(v > num_vertices_g)
330 spt_edges.push_back(
PSE(v, u));
334 std::vector<PSE> g_edges;
335 for(
auto iterator = edge.first; iterator != edge.second; ++iterator)
337 g_edges.push_back(
PSE(source(*iterator, g),
target(*iterator, g)));
345 std::vector<PSVSet> vset;
348 std::vector<PSE> co_tree_edges;
349 for(
auto e : g_edges)
351 if(find(spt_edges.begin(), spt_edges.end(),
PSE(source(e, g),
target(e, g))) != spt_edges.end() ||
352 find(spt_edges.begin(), spt_edges.end(),
PSE(
target(e, g), source(e, g))) != spt_edges.end())
358 co_tree_edges.push_back(
PSE(source(e, g),
target(e, g)));
365 std::vector<PSVSet> loop_size;
366 std::vector<PSE> odd_co_tree_edges;
367 for(
auto e : co_tree_edges)
372 odd_co_tree_edges.push_back(e);
377 for(
auto e : odd_co_tree_edges)
379 add_edge(e.first, e.second, g2);
384 auto g2_vertices = boost::vertices(g2);
388 for(
auto iterator = g2_vertices.first; iterator != g2_vertices.second; ++iterator)
390 if(out_degree(*iterator, g2) == 1)
393 cover_set.insert(u1);
394 clear_vertex(u1, g2);
396 else if(out_degree(*iterator, g2) > 1)
399 cover_set.insert(u2);
400 clear_vertex(u2, g2);
406 long unsigned int abCardinality = 0;
407 std::vector<PSVSet> temp_set;
411 temp_set.push_back(vs);
416 for(
auto set : temp_set)
418 if(find(cover_set.begin(), cover_set.end(),
set.v) != cover_set.end())
434 run.cardinality = abCardinality;
435 run.spt_vector_edges = spt_edges;
436 run.co_tree_vector_edges = co_tree_edges;
437 run.odd_co_tree_vector_edges = odd_co_tree_edges;
438 vector_sets.push_back(run);
445 auto g_vertices = vertices(g);
446 std::vector<PSMultiStart> vector_sets;
447 for(
auto iterator = g_vertices.first; iterator != g_vertices.second; ++iterator)
451 long unsigned int max = boost::num_vertices(g);
453 for(
const auto& vset : vector_sets)
455 if(vset.cardinality < max)
457 max = vset.cardinality;
458 best_candidate = vset;
462 std::vector<std::pair<PSVertex, unsigned int>> return_values;
463 for(
auto vertex_set : best_candidate.vset)
465 return_values.push_back(std::make_pair(vertex_set.v, vertex_set.belongs));
467 return return_values;
481 for(
auto res : results)
483 if(res.first == operand)
498 using Operands =
struct 505 std::map<std::pair<unsigned int, unsigned int>, std::vector<vertex>> fu_map;
506 std::map<std::tuple<unsigned int, unsigned int, unsigned int>,
PSVertex> op_vertex_map;
507 std::tuple<unsigned int, unsigned int, unsigned int> key_value;
508 std::vector<PSVertex> vertices_in_op;
509 std::vector<Operands> operands;
510 std::vector<std::pair<PSVertex, unsigned int>> results;
511 bool changed =
false;
513 vertices_in_op.resize(2);
519 for(boost::tie(op, opend) = boost::vertices(*data); op != opend; op++)
526 auto fu_key = std::make_pair(fu, idx);
527 fu_map[fu_key].push_back(*op);
531 for(
const auto& fu : fu_map)
536 for(
const auto& fu_operation : fu.second)
539 "---Operation: " +
GET_NAME(data, fu_operation) +
" (" +
541 std::vector<HLS_manager::io_binding_type> var_read =
543 THROW_ASSERT(var_read.size() == 2,
STR(var_read.size()) +
" Vertices in op has wrong size!");
544 for(
unsigned int var_num = 0; var_num < var_read.size(); var_num++)
547 unsigned int tree_var = std::get<0>(var_read[var_num]);
551 "---Constant: " +
STR(std::get<1>(var_read[var_num])));
552 key_value = std::make_tuple(0, 0, std::get<1>(var_read[var_num]));
559 for(
const auto state : running_states)
564 key_value = std::make_tuple(1, 0, tree_var);
572 if(def_op_ending_states.find(state) != def_op_ending_states.end())
581 key_value = std::make_tuple(2, 0, tree_var);
586 unsigned int storage_value =
590 key_value = std::make_tuple(3, 0, r_index);
599 unsigned int storage_value =
603 key_value = std::make_tuple(3, 0, r_index);
612 if(op_vertex_map.find(key_value) == op_vertex_map.end())
614 v_input = boost::add_vertex(g);
616 op_vertex_map[key_value] = v_input;
618 vertices_in_op[var_num] = op_vertex_map.at(key_value);
621 if(vertices_in_op[0] != vertices_in_op[1])
624 add_edge(vertices_in_op[0], vertices_in_op[1], g);
625 tmp_op.op = fu_operation;
626 tmp_op.first_op = vertices_in_op[0];
627 tmp_op.second_op = vertices_in_op[1];
629 operands.push_back(tmp_op);
637 "_" +
STR(fu.first.second) +
".dot"));
638 boost::write_graphviz(file, g);
645 for(
auto res : results)
648 "---Vertex: " +
STR(res.first) +
" Belongs To: " +
STR(res.second));
654 for(
const auto& opt : operands)
656 unsigned int op1, op2;
659 if((op1 == op2) && (op1 ==
SET_B || op1 ==
SET_A))
672 "--> Swap ports in operation: " +
GET_NAME(data, opt.op));
674 "--- Vertices swapped: " +
STR(opt.first_op) +
" and " +
STR(opt.second_op));
683 op_vertex_map.clear();
690 "-->Port swapping: number of operations swapped= " +
STR(n_swaps));
Class specification to contain liveness information.
unsigned int get_register(unsigned int sv) const
return the register index where the storage value is stored
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
const HLS_managerRef HLSMgr
information about all the HLS synthesis
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
PSVertex find_max_degree(const CustomOrderedSet< std::pair< PSVertex, unsigned int >> &dSet)
This function finds the maximum degree (out_edges) of a vertex.
File containing functions and utilities to support the printing of debug messagges.
#define STOK(token)
Macro used to convert a token symbol into the corresponding string.
const CustomOrderedSet< vertex > & get_state_where_end(vertex op) const
return in which support vertex the operation is ending
Step successfully executed.
~port_swapping() override
Destructor.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
bool has_op_where_defined(unsigned int var) const
return true in case there exist an operation defining it
const int output_level
The output level.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
unsigned int get_assign(const vertex &v) const
Returns the functional unit assigned to the vertex.
const unsigned int funId
identifier of the function to be processed (0 means that it is a global step)
#define GET_NAME(data, vertex_index)
Helper macro returning the name associated with a node.
static bool is_parameter(const tree_managerConstRef &TM, const unsigned int index)
return true in case the index corresponds to a parameter in ssa form or not
AllocationInformationRef allocation_information
Store the technology information.
A simple interface to token object of the raw files.
#define TYPE_PHI
constant string identifying an operation node of type PHI
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
struct { PSVertex v PSVSet
struct { std::vector< PSVSet > vset PSMultiStart
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
DesignFlowStep_Status InternalExec() override
Execute the step.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
fu_bindingRef Rfu
Store the refcounted functional unit binding of the operations.
port_swapping(const ParameterConstRef Param, const HLS_managerRef HLSMgr, unsigned int funId, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
Data structure used to store the register binding of variables.
StorageValueInformationRef storage_value_information
data-structure for storage values
boost::graph_traits< PSGraph >::vertex_descriptor PSVertex
This class specifies the characteristic of a particular operation working on a given functional unit...
std::pair< unsigned int, unsigned int > PSE
unsigned int get_results(PSVertex operand, const std::vector< std::pair< PSVertex, unsigned int >> &results)
This function returns the belonging set of a given vertex.
Target must be reexecuted.
std::vector< std::pair< PSVertex, unsigned int > > p_swap(PSGraph &g)
This function is the wrapper that executes port_swapping_algorithms and extracts the best solution...
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
utility function used to read files.
bool is_commutative_op(const std::string &operation)
This function checks if an operation is commutative or not.
const BehavioralHelperConstRef CGetBehavioralHelper() const
Returns the helper associated with the function.
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This file collects some utility functions and macros.
PSVertex get_co_tree_vertex(PSVertex vertex, const std::vector< PSE > &edges)
This function selects the right vertex from the co_tree_edges vector.
reg_bindingRef Rreg
Store the refcounted register binding of the variables.
std::string PrintVariable(unsigned int var) const
Print the name of the variable associated to the index.
boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::property< boost::edge_color_t, boost::default_color_type > > PSGraph
const CustomUnorderedSet< std::tuple< HLSFlowStep_Type, HLSFlowStepSpecializationConstRef, HLSFlowStep_Relationship > > ComputeHLSRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Compute the relationship of this step.
livenessRef Rliv
data-structure containing the variable liveness
This file collects some utility functions.
void set_ports_are_swapped(vertex v, bool condition)
specify if vertex v have or not its ports swapped
std::string GetPath(std::filesystem::path path)
Data flow graph with feedback.
int vertex_distance(const std::vector< PSE > &spt_edges, PSVertex root, PSVertex dest, std::vector< PSVSet > &vset)
This function calculates the distances between two vertices in a spanning tree.
Data structure used to store the functional-unit binding of the vertexes.
const OpGraphConstRef CGetOpGraph(FunctionBehavior::graph_type gt) const
This method returns the operation graphs.
#define INFINITE_UINT
UNSIGNED INT representing infinite.
const CustomOrderedSet< vertex > & get_state_where_run(vertex op) const
return in which support vertex the operation is running
hlsRef HLS
HLS data structure of the function to be analyzed.
TYPE distance(TYPE position_x[nAtoms], TYPE position_y[nAtoms], TYPE position_z[nAtoms], int i, int j)
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
void update_degree(PSGraph g2, CustomOrderedSet< std::pair< PSVertex, unsigned int >> &dSet)
This function updates the degree of all the vertices.
this class is used to manage the command-line or XML options.
unsigned int functionId
this is the identifier of the function to be implemented
int debug_level
The debug level.
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
refcount< const HLSFlowStepSpecialization > HLSFlowStepSpecializationConstRef
const refcount definition of the class
vertex get_op_where_defined(unsigned int var) const
return which operation defines the variable
Implementation of the port swapping algorithm described in the following paper: Hao Cong...
Data structure definition for high-level synthesis flow.
unsigned int get_index(const vertex &v) const
Returns the index of functional unit assigned to the vertex.
void vertex_levels(const std::vector< PSE > &spt_edges, PSVertex root, size_t num_vertices_g, std::vector< PSVSet > &vset)
This function calculates the levels of all te vertices starting from root.
A brief description of the C++ Header File.
void port_swapping_algorithm(PSGraph &g, std::vector< PSMultiStart > &vector_sets, size_t num_vertices_g, PSVertex root)
This function computes the port_swapping.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...