45 #include "config_HAVE_FROM_PRAGMA_BUILT.hpp" 46 #include "config_HAVE_PRAGMA_BUILT.hpp" 77 #include <boost/range/adaptor/reversed.hpp> 80 const DesignFlowManagerConstRef _design_flow_manager,
92 switch(relationship_type)
97 const auto frontend_flow_step_factory = GetPointer<const FrontendFlowStepFactory>(
101 const auto design_flow_step =
102 frontend_flow_step ? design_flow_graph->CGetDesignFlowStepInfo(frontend_flow_step)->design_flow_step :
103 frontend_flow_step_factory->CreateApplicationFrontendFlowStep(BAMBU_FRONTEND_FLOW);
104 relationship.insert(design_flow_step);
106 const auto technology_flow_step_factory = GetPointer<const TechnologyFlowStepFactory>(
108 const auto technology_flow_signature =
111 const auto technology_design_flow_step =
112 technology_flow_step ?
113 design_flow_graph->CGetDesignFlowStepInfo(technology_flow_step)->design_flow_step :
115 relationship.insert(technology_design_flow_step);
133 "__builtin_llabs",
"labs",
"__builtin_labs"};
143 const auto CGM =
HLSMgr->GetCallGraphManager();
144 const auto HLS_D =
HLSMgr->get_HLS_device();
145 const auto TechM = HLS_D->get_technology_manager();
146 const auto io_proxies_only =
147 parameters->isOption(OPT_disable_function_proxy) &&
parameters->getOption<
bool>(OPT_disable_function_proxy);
149 auto root_functions = CGM->GetRootFunctions();
152 const auto top_rtldesign_function =
153 HLSMgr->get_tree_manager()->GetFunction(
parameters->getOption<std::string>(OPT_top_design_name));
154 if(top_rtldesign_function && root_functions.count(top_rtldesign_function->index))
156 root_functions.clear();
157 root_functions.insert(top_rtldesign_function->index);
162 for(
const auto f_id : root_functions)
164 for(
const auto reached_f_id : CGM->GetReachedFunctionsFrom(f_id,
false))
166 reached_from_all.insert(reached_f_id);
172 if(
parameters->isOption(OPT_constraints_functions))
174 auto tmp_string =
parameters->getOption<std::string>(OPT_constraints_functions);
175 const auto funcs_values = string_to_container<std::vector<std::string>>(tmp_string,
",");
176 for(
auto fun_resources : funcs_values)
178 if(!fun_resources.empty() && fun_resources.at(0) ==
'=')
180 fun_resources = fun_resources.substr(1);
182 const auto splitted =
SplitString(fun_resources,
"=");
183 auto TM =
HLSMgr->get_tree_manager();
184 for(
auto funid : reached_from_all)
186 auto*
decl_node = GetPointer<function_decl>(TM->GetTreeNode(funid));
194 if(!splitted.empty() && (fu_name == splitted.at(0) || splitted.at(0) ==
"*" ||
195 (splitted.at(0).max_size() > 1 && splitted.at(0).at(0) ==
'*' &&
196 fu_name.find(splitted.at(0).substr(1)) == 0)))
198 functions_constrained.insert(funid);
199 unsigned num_resources = 0;
200 if(splitted.size() == 1)
204 else if(splitted.size() == 2)
206 auto res_num = splitted.at(1);
207 std::transform(res_num.begin(), res_num.end(), res_num.begin(),
208 [](
unsigned char c) {
return std::tolower(c); });
209 if(splitted.at(1) ==
"u")
213 num_resources =
static_cast<unsigned>(std::stoul(res_num));
220 std::make_pair(num_resources, 1);
223 "Constraining function " + fu_name +
" with " +
STR(num_resources) +
" resources");
228 if(!
parameters->isOption(OPT_top_functions_names))
231 "---@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
232 for(
const auto f_id : root_functions)
234 const auto function_behavior =
HLSMgr->CGetFunctionBehavior(f_id);
235 const auto BH = function_behavior->CGetBehavioralHelper();
236 const auto fname = BH->get_function_name();
238 "---The top function inferred from the specification is: " + fname);
241 "---@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
250 for(
const auto& funID : reached_from_all)
252 const auto function_behavior =
HLSMgr->CGetFunctionBehavior(funID);
253 const auto BH = function_behavior->CGetBehavioralHelper();
254 const auto fname = BH->get_function_name();
256 GetPointerS<const function_decl>(
HLSMgr->get_tree_manager()->CGetTreeNode(funID))))
259 "---Warning: " + fname +
" is empty or the compiler killed all the statements");
261 if(BH->has_implementation())
265 if(functions_constrained.find(funID) != functions_constrained.end())
276 for(
const auto& top_fid : root_functions)
279 "-->Allocation thread: " +
280 HLSMgr->CGetFunctionBehavior(top_fid)->CGetBehavioralHelper()->get_function_name());
281 const auto top_vertex = CGM->GetVertex(top_fid);
282 const auto reached_from_top = CGM->GetReachedFunctionsFrom(top_fid,
false);
283 const auto subgraph = [&]() {
285 subset.insert(top_vertex);
286 std::transform(reached_from_top.begin(), reached_from_top.end(), std::inserter(subset, subset.end()),
287 [&](
unsigned int fid) {
return CGM->GetVertex(fid); });
288 return CGM->CGetCallSubGraph(subset);
291 if(boost::num_vertices(*subgraph) < 2)
298 const auto cg_dominators =
301 const auto& cg_dominator_map = cg_dominators->get_dominator_map();
306 std::list<vertex> topology_sorted_vertex;
307 subgraph->TopologicalSort(topology_sorted_vertex);
308 for(
const auto& current_vertex : topology_sorted_vertex)
311 if(boost::in_degree(current_vertex, *subgraph) != 1)
313 vert_dominator = cg_dominator_map.at(current_vertex);
317 vert_dominator = current_vertex;
319 if(boost::out_degree(current_vertex, *subgraph))
321 const auto current_id = CGM->get_function(current_vertex);
323 "Missing HLS initialization for " +
324 HLSMgr->CGetFunctionBehavior(current_id)->CGetBehavioralHelper()->get_function_name());
325 const auto HLS_C =
HLSMgr->get_HLS(current_id)->HLS_C;
326 THROW_ASSERT(cg_dominator_map.find(current_vertex) != cg_dominator_map.end(),
327 "Dominator vertex not in the dominator tree: " +
328 HLSMgr->CGetFunctionBehavior(current_id)->CGetBehavioralHelper()->get_function_name());
329 BOOST_FOREACH(
EdgeDescriptor eo, boost::out_edges(current_vertex, *subgraph))
331 auto called_fu_id = CGM->get_function(
boost::target(eo, *subgraph));
333 unsigned multiplicity = 1;
335 if(
HLSMgr->global_resource_constraints.find(std::make_pair(called_fu_name,
WORK_LIBRARY)) !=
336 HLSMgr->global_resource_constraints.end())
338 auto c =
HLSMgr->global_resource_constraints.at(std::make_pair(called_fu_name,
WORK_LIBRARY));
339 auto curr_res_n = HLS_C->get_number_fu(called_fu_name,
WORK_LIBRARY);
340 if(curr_res_n != c.first)
344 "---Upgraded function constraints for " +
345 HLSMgr->CGetFunctionBehavior(current_id)->CGetBehavioralHelper()->get_function_name() +
346 " with " +
STR(c.first) +
" resources of " + called_fu_name +
", before was " +
348 HLS_C->set_number_fu(called_fu_name,
WORK_LIBRARY, c.first);
350 multiplicity = c.second;
353 HLSMgr->global_resource_constraints.end())
361 "---Upgraded function constraints for " +
362 HLSMgr->CGetFunctionBehavior(current_id)->CGetBehavioralHelper()->get_function_name() +
363 " with " +
STR(c.first) +
" resources of " + called_fu_name);
365 multiplicity = c.second;
374 functions_constrained.find(called_fu_id) == functions_constrained.end() &&
377 HLS_C->get_number_fu(called_fu_name,
WORK_LIBRARY) / multiplicity ==
383 fun_dom_map[called_fu_name].insert(vert_dominator);
384 const auto info = Cget_edge_info<FunctionEdgeInfo, const CallGraph>(eo, *subgraph);
386 if(info->direct_call_points.size())
388 where_used[called_fu_name].insert(current_id);
392 where_used[called_fu_name];
395 if(info->indirect_call_points.size() || info->function_addresses.size())
397 indirectlyCalled[called_fu_name] =
true;
401 indirectlyCalled[called_fu_name] =
false;
405 "---Dominator vertex: " +
406 HLSMgr->CGetFunctionBehavior(CGM->get_function(vert_dominator))
407 ->CGetBehavioralHelper()
408 ->get_function_name() +
409 " => " + called_fu_name);
417 for(
const auto& cur : topology_sorted_vertex)
419 const auto cur_id = CGM->get_function(cur);
420 if(reached_from_top.find(cur_id) != reached_from_top.end())
424 "missing number of instances of function " +
425 HLSMgr->CGetFunctionBehavior(cur_id)->CGetBehavioralHelper()->get_function_name());
426 function_allocation_map[cur_id];
427 const auto cur_instances = num_instances.at(cur_fu_name);
428 BOOST_FOREACH(
EdgeDescriptor eo, boost::out_edges(cur, *subgraph))
432 const auto n_call_points =
static_cast<unsigned int>(
433 Cget_edge_info<FunctionEdgeInfo, const CallGraph>(eo, *subgraph)->direct_call_points.size());
434 if(num_instances.find(tgt_fu_name) == num_instances.end())
436 num_instances[tgt_fu_name] = cur_instances * n_call_points;
440 num_instances[tgt_fu_name] += cur_instances * n_call_points;
447 "top function cannot be called from some other function");
449 for(
const auto& dom_map : fun_dom_map)
451 unsigned int cur_id = 0;
452 if(dom_map.second.size() == 1)
454 auto cur = *dom_map.second.begin();
457 cur = cg_dominator_map.at(cur);
459 cur_id = CGM->get_function(cur);
463 if(dom_map.second.count(top_vertex))
469 auto vert_it = dom_map.second.begin();
470 const auto vert_it_end = dom_map.second.end();
471 std::list<vertex> dominator_list1;
473 dominator_list1.push_front(cur);
477 cur = cg_dominator_map.at(cur);
478 dominator_list1.push_front(cur);
479 }
while(cur != top_vertex);
481 auto last = dominator_list1.end();
482 for(; vert_it != vert_it_end; ++vert_it)
484 std::list<vertex> dominator_list2;
486 dominator_list2.push_front(cur);
490 cur = cg_dominator_map.at(cur);
491 dominator_list2.push_front(cur);
492 }
while(cur != top_vertex);
494 auto dl1_it = dominator_list1.begin(), dl2_it = dominator_list2.begin(),
495 dl2_it_end = dominator_list2.end(), cur_last = dominator_list1.begin();
496 while(dl1_it != last && dl2_it != dl2_it_end && *dl1_it == *dl2_it &&
505 cur_id = CGM->get_function(cur);
506 if(cur == top_vertex)
513 THROW_ASSERT(cur_id,
"null function id index unexpected");
516 HLSMgr->CGetFunctionBehavior(cur_id)->CGetBehavioralHelper()->get_function_name());
517 function_allocation_map[cur_id].push_back(dom_map.first);
521 for(
const auto& funID : reached_from_top)
523 THROW_ASSERT(function_allocation_map.find(funID) != function_allocation_map.end(),
524 "Expected function allocation map for function " +
525 HLSMgr->CGetFunctionBehavior(funID)->CGetBehavioralHelper()->get_function_name());
526 for(
const auto& fu_name : function_allocation_map.at(funID))
533 if(functions_constrained.find(funID) != functions_constrained.end())
539 "Allocating " + fu_name +
" in " +
540 HLSMgr->CGetFunctionBehavior(funID)->CGetBehavioralHelper()->get_function_name());
541 THROW_ASSERT(where_used.at(fu_name).size() > 0 || indirectlyCalled.at(fu_name),
542 fu_name +
" not used anywhere");
543 if(where_used.at(fu_name).size() == 1)
546 "---Skipped because called only by one other function");
549 const auto fnode =
HLSMgr->get_tree_manager()->GetFunction(fu_name);
550 if(fnode &&
HLSMgr->hasToBeInterfaced(fnode->index))
555 const auto library_name = TechM->get_library(fu_name);
556 if(library_name !=
"")
558 const auto libraryManager = TechM->get_library_manager(library_name);
559 const auto techNode_obj = libraryManager->get_fu(fu_name);
560 if(GetPointer<functional_unit_template>(techNode_obj))
566 HLSMgr->Rfuns->map_shared_function(funID, fu_name);
568 const auto cur_function_behavior =
HLSMgr->CGetFunctionBehavior(funID);
569 const auto cur_BH = cur_function_behavior->CGetBehavioralHelper();
571 "---Adding proxy wrapper in function " + cur_BH->get_function_name());
573 for(
const auto& wu_id : where_used.at(fu_name))
577 const auto wiu_function_behavior =
HLSMgr->CGetFunctionBehavior(wu_id);
578 const auto wiu_BH = wiu_function_behavior->CGetBehavioralHelper();
580 "---Adding proxy function in function " + wiu_BH->get_function_name());
581 HLSMgr->Rfuns->add_shared_function_proxy(wu_id, fu_name);
bool already_executed
True if this step has yet been executed.
const HLS_managerRef HLSMgr
information about all the HLS synthesis
static bool is_a_nop_function_decl(const function_decl *fd)
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;.
Dominator o post-dominator data structure.
#define STR_CST_interface_parameter_keyword
interface_parameter_keyword
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
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.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
CustomOrderedMap< T, U > CustomMap
DesignFlowStep_Status Exec() override
Execute the step.
Class specification of the manager of the technology library data structures.
#define INTERFACE_LIBRARY
interface library
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
Include a set of utilities used to manage CPU time measures.
static std::string GetMangledFunctionName(const function_decl *fd)
Return the mangled function name.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Class specification of the data structures used to manage technology information. ...
Class to allocate function in HLS based on dominators.
Classes to describe design flow graph.
Target must be reexecuted.
static const std::string ComputeSignature(const TechnologyFlowStep_Type technology_flow_step_type)
Compute the signature of a technology flow step.
Datastructure to describe functions allocation in high-level synthesis.
Factory for technology flow step.
static const std::string ComputeSignature(const FrontendFlowStepType frontend_flow_step_type)
Compute the signature of a function frontend flow step.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
static std::string GetFUName(const std::string &fname, const HLS_managerRef HLSMgr)
Return FU used to implement given function.
fun_dominator_allocation(const ParameterConstRef _parameters, const HLS_managerRef HLSMgr, const DesignFlowManagerConstRef design_flow_manager, const HLSFlowStep_Type hls_flow_step_type=HLSFlowStep_Type::DOMINATOR_FUNCTION_ALLOCATION)
Constructor.
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This file collects some utility functions and macros.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Data structure definition for HLS constraints.
This file collects some utility functions.
void ComputeRelationships(DesignFlowStepSet &design_flow_step_set, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
refcount< T > lock() const
#define OUTPUT_LEVEL_PEDANTIC
verbose debugging print is performed.
static const std::set< std::string > simple_functions
list of trivial function that does not require to be proxied
#define WORK_LIBRARY
working library.
#define INFINITE_UINT
UNSIGNED INT representing infinite.
This class contains the methods to create a frontend flow step.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
this class is used to manage the command-line or XML options.
~fun_dominator_allocation() override
Destructor.
Class specification of the manager for each library.
int debug_level
The debug level.
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
Data structure definition for high-level synthesis flow.
This class contains the base representation for a generic frontend flow step which works on the whole...
#define NULL_VERTEX
null vertex definition
struct definition of the declaration node structures.
Class specification of the manager of the tree structures extracted from the raw file.
Base class for technology flow steps.
HLS specialization of generic_device.
A brief description of the C++ Header File.
Allocation function class.
boost::graph_traits< graph >::edge_descriptor EdgeDescriptor
edge definition.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...