80 #include <boost/foreach.hpp> 81 #include <boost/graph/depth_first_search.hpp> 82 #include <boost/graph/graph_traits.hpp> 83 #include <boost/graph/incremental_components.hpp> 109 return sch->get_cstep(x) < sch->get_cstep(y);
114 const DesignFlowManagerConstRef _design_flow_manager)
124 switch(relationship_type)
164 long int step_time = 0;
172 THROW_ASSERT(STG_builder,
"STG constructor not properly initialized");
186 const auto bb_entry = fbb->CGetBBGraphInfo()->entry_vertex;
187 const auto bb_exit = fbb->CGetBBGraphInfo()->exit_vertex;
192 std::map<vertex, std::list<vertex>> call_states;
193 std::map<vertex, std::list<vertex>> call_operations;
197 const auto is_pipelined =
HLSMgr->CGetFunctionBehavior(
funId)->is_simple_pipeline();
200 std::map<vertex, std::list<vertex>> global_executing_ops, global_starting_ops, global_ending_ops, global_onfly_ops;
202 const auto CGM =
HLSMgr->CGetCallGraphManager();
203 const auto top_functions = CGM->GetRootFunctions();
204 const auto needMemoryMappedRegisters = top_functions.count(
funId) ?
205 parameters->getOption<
bool>(OPT_memory_mapped_top) :
208 if(top_functions.count(
funId) &&
parameters->getOption<std::string>(OPT_registered_inputs) ==
"top")
210 has_registered_inputs =
true;
214 if(
parameters->getOption<std::string>(OPT_registered_inputs) !=
"no")
216 has_registered_inputs =
true;
219 else if(
parameters->getOption<std::string>(OPT_registered_inputs) ==
"yes" && !needMemoryMappedRegisters)
221 has_registered_inputs =
true;
223 if(
parameters->getOption<std::string>(OPT_registered_inputs) !=
"no" && !has_registered_inputs &&
224 !needMemoryMappedRegisters)
228 const auto sort_list = CGM->GetReachedBodyFunctions();
230 for(
auto cvertex : sort_list)
232 vertex_subset.insert(CGM->GetVertex(cvertex));
234 const auto subgraph = CGM->CGetCallSubGraph(vertex_subset);
236 const auto current_vertex = CGM->GetVertex(
funId);
237 size_t n_call_sites = 0;
238 for(boost::tie(ie_it, ie_it_end) = boost::in_edges(current_vertex, *subgraph); ie_it != ie_it_end; ++ie_it)
240 const auto* info = Cget_edge_info<FunctionEdgeInfo, const CallGraph>(*ie_it, *subgraph);
241 n_call_sites +=
static_cast<size_t>(info->direct_call_points.size()) +
242 static_cast<size_t>(info->indirect_call_points.size());
246 unsigned int n_levels = 0;
248 for(; n_call_sites > (1u << n_levels); ++n_levels)
252 double mux_time_estimation =
256 has_registered_inputs =
true;
259 auto omp_functions = GetPointer<OmpFunctions>(
HLSMgr->Rfuns);
260 if(
HLS->
Param->isOption(OPT_context_switch))
262 if(omp_functions->kernel_functions.count(
funId))
264 has_registered_inputs =
true;
270 for(boost::tie(vit, vend) = boost::vertices(*fbb); vit != vend; ++vit)
277 else if(*vit == bb_exit)
283 "-->Building STG of BB" +
STR(fbb->CGetBBNodeInfo(*vit)->block->number));
284 const auto operations = fbb->CGetBBNodeInfo(*vit);
286 std::multiset<vertex, OpVertexSchedSorter> ordered_operations(schSorter);
287 for(
auto ops : operations->statements_list)
289 ordered_operations.insert(ops);
291 if(boost::in_degree(*vit, *fbb) == 1)
295 boost::tie(ie, iend) = boost::in_edges(*vit, *fbb);
296 const auto bb_src = boost::source(*ie, *fbb);
297 if(bb_src == bb_entry)
299 for(
auto stmt : ordered_operations)
304 const auto entry_operations = fbb->CGetBBNodeInfo(bb_src);
306 BB_ids.insert(entry_operations->get_bb_index());
308 STG_builder->create_state(entry_operations->statements_list, entry_operations->statements_list,
309 entry_operations->statements_list, BB_ids);
310 STG_builder->connect_state(last_state[bb_src], s_cur,
311 TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
312 last_state[bb_src] = s_cur;
319 first_state_p =
true;
320 have_previous =
false;
321 std::map<ControlStep, std::list<vertex>> executing_ops, starting_ops, ending_ops, onfly_ops;
322 auto max_cstep = ControlStep(0u);
325 for(
auto op : ordered_operations)
335 bool can_be_removed =
true;
337 for(boost::tie(oe, oend) = boost::out_edges(*vit, *fbb); oe != oend && can_be_removed; ++oe)
344 const auto out_bb_operations = fbb->CGetBBNodeInfo(tgt);
345 auto obo_it_end = out_bb_operations->statements_list.end();
346 for(
auto obo_it = out_bb_operations->statements_list.begin(); obo_it_end != obo_it && can_be_removed;
351 for(
const auto& def_edge :
352 GetPointer<const gimple_phi>(
HLSMgr->get_tree_manager()->get_tree_node_const(
353 dfgRef->CGetOpNodeInfo(*obo_it)->GetNodeId()))
354 ->CGetDefEdgesList())
360 if(def_edge.second == operations->get_bb_index())
362 can_be_removed =
false;
374 if(already_analyzed.find(op) != already_analyzed.end())
377 "<--Already Analyzed operation " +
GET_NAME(dfgRef, op));
380 const auto cstep = sch->get_cstep(op).second;
382 THROW_ASSERT(sch->get_cstep_end(op) >= sch->get_cstep(op),
"unexpected condition");
383 const auto delay = sch->get_cstep_end(op).second - sch->get_cstep(op).second;
384 const auto end_step = cstep +
delay;
385 max_cstep =
std::max(max_cstep, end_step);
386 min_cstep =
std::min(min_cstep, cstep);
387 executing_ops[cstep].push_back(op);
388 starting_ops[cstep].push_back(op);
391 if(initiation_time == 0 || initiation_time > delay)
393 for(
auto c = cstep + 1u; c <= end_step; c++)
395 executing_ops[c].push_back(op);
398 for(
auto c = cstep + 1u; c <= end_step; c++)
400 onfly_ops[c].push_back(op);
402 ending_ops[end_step].push_back(op);
406 for(
auto l = min_cstep; l <= max_cstep; l++)
409 std::list<vertex> exec_ops, start_ops, end_ops, onf_ops;
410 if(executing_ops.find(l) != executing_ops.end())
412 exec_ops = executing_ops[l];
414 if(starting_ops.find(l) != starting_ops.end())
416 start_ops = starting_ops[l];
418 if(ending_ops.find(l) != ending_ops.end())
420 end_ops = ending_ops[l];
422 if(onfly_ops.find(l) != onfly_ops.end())
424 onf_ops = onfly_ops[l];
427 BB_ids.insert(operations->get_bb_index());
428 s_cur = STG_builder->create_state(exec_ops, start_ops, end_ops, BB_ids);
430 global_executing_ops[s_cur] = exec_ops;
431 global_starting_ops[s_cur] = start_ops;
432 global_ending_ops[s_cur] = end_ops;
433 global_onfly_ops.insert({s_cur, onf_ops});
435 for(
auto exec_op : exec_ops)
438 const auto op_tn = GetPointer<functional_unit>(tn)->get_operation(
441 "Time model not available for operation: " +
GET_NAME(dfgRef, exec_op));
442 if(!GetPointer<operation>(op_tn)->is_bounded())
445 "---" +
GET_NAME(dfgRef, exec_op) +
" is unbounded");
446 call_operations[s_cur].push_back(exec_op);
452 if(call_operations.find(s_cur) != call_operations.end() && call_operations.find(s_cur)->second.size())
454 THROW_ASSERT(call_operations.find(s_cur) != call_operations.end() &&
455 call_operations.find(s_cur)->second.begin() != call_operations.find(s_cur)->second.end(),
456 "unexpected condition");
457 const auto& call_ops = call_operations.at(s_cur);
459 call_BB_ids.insert(operations->get_bb_index());
460 vertex s_call = STG_builder->create_state(call_ops, std::list<vertex>(), call_ops, call_BB_ids);
461 HLS->
STG->
GetStg()->GetStateInfo(s_call)->is_dummy =
true;
462 call_states[s_cur].push_back(s_call);
464 ops.insert(call_ops.begin(), call_ops.end());
473 if(call_states.find(previous) == call_states.end())
475 STG_builder->connect_state(previous, s_cur, TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
479 THROW_ASSERT(call_operations.find(previous) != call_operations.end() &&
480 call_operations.find(previous)->second.begin() !=
481 call_operations.find(previous)->second.end(),
482 "unexpected condition");
483 THROW_ASSERT(call_states.count(previous),
"unexpected condition");
485 ops.insert(call_operations.at(previous).begin(), call_operations.at(previous).end());
486 for(
auto& call_set : call_states.at(previous))
489 STG_builder->connect_state(call_set, s_cur, TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
490 STG_builder->set_unbounded_condition(s_e,
ALL_FINISHED, ops, previous);
493 STG_builder->connect_state(previous, s_cur, TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
494 STG_builder->set_unbounded_condition(s_e,
ALL_FINISHED, ops, previous);
499 have_previous =
true;
504 first_state[*vit] = s_cur;
505 first_state_p =
false;
507 if(call_states.count(s_cur))
509 THROW_ASSERT(call_operations.find(s_cur) != call_operations.end() &&
510 call_operations.find(s_cur)->second.begin() != call_operations.find(s_cur)->second.end(),
511 "unexpected condition");
512 THROW_ASSERT(call_states.find(s_cur) != call_states.end() &&
513 call_states.find(s_cur)->second.begin() != call_states.find(s_cur)->second.end(),
514 "unexpected condition");
515 const auto waiting_state = call_states.at(s_cur).front();
517 STG_builder->connect_state(s_cur, waiting_state, TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
520 ops.insert(call_operations.at(s_cur).begin(), call_operations.at(s_cur).end());
523 s_e = STG_builder->connect_state(waiting_state, waiting_state,
524 TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK);
527 last_state[*vit] = s_cur;
531 "<--Built STG of BB" +
STR(fbb->CGetBBNodeInfo(*vit)->block->number));
538 const auto bb_src = boost::source(e, *fbb);
539 if(last_state.find(bb_src) == last_state.end())
545 if(bb_src == bb_entry && bb_tgt == bb_exit)
550 "-->Analyzing BB" +
STR(fbb->CGetBBNodeInfo(bb_src)->block->number) +
"-->" +
551 STR(fbb->CGetBBNodeInfo(bb_tgt)->block->number));
553 if(bb_src == bb_exit)
559 THROW_ASSERT(last_state.count(bb_src),
"missing a state vertex");
560 s_src = last_state.at(bb_src);
562 if(bb_tgt == bb_entry)
566 else if(bb_tgt == bb_exit)
572 while(first_state.find(bb_tgt) == first_state.end())
574 THROW_ASSERT(boost::out_degree(bb_tgt, *fbb) == 1,
"unexpected pattern");
576 boost::tie(oe, oend) = boost::out_edges(bb_tgt, *fbb);
579 s_tgt = first_state.at(bb_tgt);
586 s_e = STG_builder->connect_state(s_src, s_tgt, TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK);
587 if(call_states.count(s_src))
589 const auto& call_sets = call_states.at(s_src);
591 ops.insert(call_operations[s_src].begin(), call_operations[s_src].end());
592 if(call_sets.begin() != call_sets.end())
594 STG_builder->set_unbounded_condition(s_e,
ALL_FINISHED, ops, s_src);
596 for(
auto call_set : call_sets)
599 STG_builder->connect_state(call_set, s_tgt, TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK);
600 STG_builder->set_unbounded_condition(s_e1,
ALL_FINISHED, ops, s_src);
606 if(call_states.find(s_src) == call_states.end())
608 s_e = STG_builder->connect_state(s_src, s_tgt, TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
612 THROW_ASSERT(call_operations.find(s_src) != call_operations.end() &&
613 call_operations.find(s_src)->second.size() != 0,
615 const auto& call_sets = call_states.at(s_src);
617 ops.insert(call_operations.at(s_src).begin(), call_operations.at(s_src).end());
618 for(
auto& call_set : call_sets)
621 STG_builder->connect_state(call_set, s_tgt, TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
622 STG_builder->set_unbounded_condition(s_edge,
ALL_FINISHED, ops, s_src);
625 s_e = STG_builder->connect_state(s_src, s_tgt, TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
626 STG_builder->set_unbounded_condition(s_e,
ALL_FINISHED, ops, s_src);
631 const auto bb_node_info = fbb->CGetBBNodeInfo(bb_src);
632 THROW_ASSERT(bb_node_info->statements_list.size(),
"at least one operation should belong to this basic block");
633 const auto last_operation = *(bb_node_info->statements_list.rbegin());
636 if(cfg_edge_ids.size())
638 auto edgeType = *cfg_edge_ids.begin();
646 else if(edgeType ==
F_COND)
650 STG_builder->set_condition(s_e, t, last_operation);
655 bool has_default =
false;
656 for(
auto label : cfg_edge_ids)
664 labels.insert(label);
667 STG_builder->set_switch_condition(s_e, last_operation, labels, has_default);
671 "<--Analyzed BB" +
STR(fbb->CGetBBNodeInfo(bb_src)->block->number) +
"-->" +
672 STR(fbb->CGetBBNodeInfo(bb_tgt)->block->number));
680 if(!
parameters->IsParameter(
"fsm-duplication") ||
parameters->GetParameter<
bool>(
"fsm-duplication"))
682 unsigned int instance = 0;
689 "-->Analyzing cycle starting from " +
690 STR(fbb->CGetBBNodeInfo(boost::source(fbbei, *fbb))->block->number) +
"-->" +
692 const auto bbEndingCycle = boost::source(fbbei, *fbb);
694 optimize_cycles(bbEndingCycle, first_state, last_state, global_starting_ops, global_ending_ops,
695 global_executing_ops, global_onfly_ops);
703 "<--Analyzed cycle starting from " +
704 STR(fbb->CGetBBNodeInfo(boost::source(fbbei, *fbb))->block->number) +
"-->" +
715 if(
HLS->
STG->
CGetStg()->CGetStateTransitionGraphInfo()->min_cycles != 1 && !is_pipelined)
722 const auto src_state = boost::source(ie, *
HLS->
STG->
CGetStg());
737 "-->State Transition Graph Information of function " +
738 HLSMgr->CGetFunctionBehavior(
funId)->CGetBehavioralHelper()->get_function_name() +
":");
741 "---Number of operations: " +
745 "---Number of basic blocks: " +
748 if(has_registered_inputs)
758 if(
parameters->getOption<
bool>(OPT_print_dot))
771 "---Time to perform creation of STG: " +
print_cpu_time(step_time) +
" seconds");
782 BOOST_FOREACH(
vertex state, boost::vertices(*st_graph))
784 const auto state_info = st_graph->CGetStateInfo(state);
785 for(
const auto BB_id : state_info->BB_ids)
787 if(stg_length.find(BB_id) != stg_length.end())
789 stg_length.at(BB_id)++;
797 const auto bb_cfg =
HLSMgr->CGetFunctionBehavior(
funId)->CGetBBGraph();
798 BOOST_FOREACH(
vertex bb, boost::vertices(*bb_cfg))
800 const auto bb_node_info = bb_cfg->CGetBBNodeInfo(bb);
802 auto bb_ending = ControlStep(0u);
803 for(
const auto op : bb_node_info->statements_list)
818 for(
const auto& basic_block : bb_length)
821 "---BB" +
STR(basic_block.first) +
": " +
822 STR(from_strongtype_cast<unsigned int>(basic_block.second)) +
" vs. " +
823 STR(from_strongtype_cast<unsigned int>(stg_length.find(basic_block.first)->second)));
837 const auto stg = STG->
GetStg();
839 THROW_ASSERT(boost::out_degree(entry_state, *stg) == 1,
"entry state has not 1 successor");
841 THROW_ASSERT(boost::in_degree(exit_state, *stg),
"exit state has no predecessors");
849 BOOST_FOREACH(
const vertex v, boost::vertices(*stg))
851 if(stg->CGetStateInfo(v)->is_dummy)
858 if(stg->GetSelector(oe) & TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK)
860 epp_edges_to_add.insert(std::make_pair(v, exit_state));
864 if(stg->GetSelector(ie) & TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK)
866 epp_edges_to_add.insert(std::make_pair(entry_state, v));
869 for(
const auto& e : epp_edges_to_add)
871 STG->
STG_builder->connect_state(e.first, e.second, TransitionInfo::StateTransitionType::ST_EDGE_EPP);
889 std::deque<vertex> reverse_v_list;
890 epp_stg->ReverseTopologicalSort(reverse_v_list);
891 for(
const auto v : reverse_v_list)
893 if(epp_stg->CGetStateInfo(v)->is_dummy)
898 if(boost::out_degree(v, *epp_stg) == 0)
907 const auto selector = epp_stg->GetSelector(e);
909 if(epp_stg->CGetStateInfo(dst)->is_dummy)
915 case TransitionInfo::StateTransitionType::ST_EDGE_EPP:
916 case TransitionInfo::StateTransitionType::ST_EDGE_NORMAL:
917 epp_stg->GetTransitionInfo(e)->set_epp_increment(n);
918 n += NumPaths.at(dst);
926 res =
std::max(res, NumPaths.at(v));
933 const auto discr_info =
HLSMgr->RDiscr->hw_discrepancy_info;
935 "-->Computing Efficient Path Profiling edge increments for HW discrepancy analysis");
942 "<--Computed EPP edge increments: max_path_val = " +
STR(max_path_val));
945 size_t epp_trace_bitsize = 0;
950 }
while(max_path_val);
951 discr_info->fu_id_control_flow_skip.erase(
funId);
953 "---fun id " +
STR(
funId) +
"EPP path bits " +
STR(epp_trace_bitsize));
954 discr_info->fu_id_to_epp_trace_bitsize[
funId] = epp_trace_bitsize;
955 discr_info->fu_id_to_max_epp_path_val[
funId] = max_path_val;
959 discr_info->fu_id_control_flow_skip.insert(
funId);
960 discr_info->fu_id_to_epp_trace_bitsize[
funId] = 0;
961 discr_info->fu_id_to_max_epp_path_val[
funId] = 0;
965 auto& state_id_to_check = discr_info->fu_id_to_states_to_check[
funId];
966 state_id_to_check.clear();
967 auto& state_id_to_check_on_feedback = discr_info->fu_id_to_feedback_states_to_check[
funId];
968 state_id_to_check_on_feedback.clear();
969 auto& reset_edges = discr_info->fu_id_to_reset_edges[
funId];
972 const auto& stg_info = stg->CGetStateTransitionGraphInfo();
974 for(
const auto& state_to_op : starting_ops)
976 for(
const auto& op : state_to_op.second)
980 const auto op_tn = GetPointer<const functional_unit>(tn)->get_operation(op_id);
981 if(!GetPointer<const operation>(op_tn)->is_bounded())
983 const auto state_id = stg_info->vertex_to_state_id.at(state_to_op.first);
985 "state: S_" +
STR(state_id) +
986 " is always to check because it contains an unbounded operation");
987 state_id_to_check.insert(state_id);
993 if(stg->GetSelector(e) & TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK)
995 #if HAVE_ASSERTS || !defined(NDEBUG) 996 const auto src = boost::source(e, *stg);
999 const bool dst_dummy = stg->CGetStateInfo(dst)->is_dummy;
1002 const auto dst_state_id = stg_info->vertex_to_state_id.at(dst);
1004 "state: S_" +
STR(dst_state_id) +
1005 " is to check on feedback because it is the destination of a feedback edge");
1006 state_id_to_check_on_feedback.insert(dst_state_id);
1008 "edge from state: S_" +
STR(stg_info->vertex_to_state_id.at(src)) +
" to state: S_" +
1009 STR(dst_state_id) +
" is to reset");
1010 reset_edges.insert(e);
1014 THROW_ASSERT(stg->CGetStateInfo(src)->is_dummy and (src == dst),
"");
1018 const auto exit_state = stg_info->exit_node;
1019 BOOST_FOREACH(
const EdgeDescriptor in_e, boost::in_edges(exit_state, *stg))
1021 const auto src = boost::source(in_e, *stg);
1022 const bool src_dummy = stg->CGetStateInfo(src)->is_dummy;
1025 const auto state_id = stg_info->vertex_to_state_id.at(src);
1027 "state: S_" +
STR(state_id) +
" is always to check because it is before end state");
1028 state_id_to_check.insert(state_id);
1033 "<--Computed Efficient Path Profiling edge increments for HW discrepancy analysis");
1034 if(
parameters->getOption<
bool>(OPT_print_dot))
1036 stg->WriteDot(
"STG_EPP.dot");
1056 "Considering bbEndingCycle:" +
STR(fbb->CGetBBNodeInfo(bbEndingCycle)->block->number));
1057 std::list<vertex>::iterator it, findIter;
1060 const auto lastst = last_state[bbEndingCycle];
1062 if(stg->CGetStateInfo(lastst)->is_duplicated)
1066 if(boost::in_degree(lastst, *stg) != 1)
1076 const auto secondLastState = boost::source(*(boost::in_edges(lastst, *stg).first), *stg);
1077 if(stg->CGetStateInfo(secondLastState)->is_dummy)
1082 "Second last state computed " + stg->CGetStateInfo(secondLastState)->name);
1084 BOOST_FOREACH(
EdgeDescriptor oedge, boost::out_edges(lastst, *stg))
1087 if(stg->CGetStateInfo(cstate)->is_duplicated)
1094 std::list<vertex> lastStateStartingOpList = global_starting_ops[lastst];
1096 std::list<vertex> lastStateExecutingOpList = global_executing_ops[lastst];
1098 std::list<vertex> lastStateEndingOpList = global_ending_ops[lastst];
1100 std::list<vertex> lastStateOnFlyOpList = global_onfly_ops[lastst];
1102 std::list<vertex> lastStateConditionalOpList;
1104 if(lastStateEndingOpList.size() == 1)
1109 if(first_state[bbEndingCycle] == last_state[bbEndingCycle])
1119 for(it = lastStateStartingOpList.begin(); it != lastStateStartingOpList.end(); ++it)
1121 findIter = std::find(lastStateEndingOpList.begin(), lastStateEndingOpList.end(), *it);
1122 if(findIter == lastStateEndingOpList.end())
1127 for(it = lastStateExecutingOpList.begin(); it != lastStateExecutingOpList.end(); ++it)
1129 findIter = std::find(lastStateEndingOpList.begin(), lastStateEndingOpList.end(), *it);
1130 if(findIter == lastStateEndingOpList.end())
1135 for(it = lastStateOnFlyOpList.begin(); it != lastStateOnFlyOpList.end(); ++it)
1137 findIter = std::find(lastStateEndingOpList.begin(), lastStateEndingOpList.end(), *it);
1138 if(findIter == lastStateEndingOpList.end())
1155 bool has_STOREs =
false;
1157 for(it = lastStateEndingOpList.begin(); it != lastStateEndingOpList.end(); ++it)
1174 lastStateConditionalOpList.push_back(*it);
1192 if(
parameters->getOption<
bool>(OPT_disable_function_proxy) &&
1198 const auto op_tn = GetPointer<functional_unit>(tn)->get_operation(
1200 if(!GetPointer<operation>(op_tn)->is_bounded())
1206 if(GetPointer<operation>(op_tn)->time_m->get_cycles() > 1)
1221 "Resource constraints limit on operation " + dfgRef->CGetOpNodeInfo(*it)->GetOperation());
1233 if(std::find(lastStateExecutingOpList.begin(), lastStateExecutingOpList.end(), tgt_op) ==
1234 lastStateExecutingOpList.end())
1261 std::list<vertex> followingBb;
1264 BOOST_FOREACH(
EdgeDescriptor ei, boost::out_edges(bbEndingCycle, *fbb))
1271 if(tempBb == fbb->CGetBBGraphInfo()->exit_vertex)
1275 if(bbEndingCycle == tempBb)
1277 followingBb.push_back(tempBb);
1281 followingBb.push_front(tempBb);
1285 for(
auto next_ops : global_starting_ops[first_state[tempBb]])
1287 const auto operation = dfgRef->CGetOpNodeInfo(next_ops);
1288 auto curr_vertex_type =
GET_TYPE(dfgRef, next_ops);
1301 for(
auto next_ops : global_starting_ops[first_state[tempBb]])
1317 for(
auto bbVertex : followingBb)
1319 if(!
can_be_moved(lastStateEndingOpList, lastStateConditionalOpList, first_state[bbVertex], global_starting_ops,
1320 global_executing_ops))
1332 compute_use_def(lastStateEndingOpList, lastStateExecutingOpList, lastStateConditionalOpList, useSet, defSet, dfgRef);
1338 bool is_dest_first_st_equal_to_second =
false;
1339 for(
auto bbVertex : followingBb)
1341 vertex dest_first_state = first_state[bbVertex];
1342 if(dest_first_state == secondLastState)
1344 is_dest_first_st_equal_to_second =
true;
1348 if(is_dest_first_st_equal_to_second)
1352 for(
auto bbVertex : followingBb)
1354 vertex dest_first_state = first_state[bbVertex];
1355 bool skip_phi =
true;
1356 if(boost::in_degree(dest_first_state, *stg) > 1)
1358 if(!is_dest_first_st_equal_to_second)
1360 BOOST_FOREACH(
EdgeDescriptor prev_edge, boost::out_edges(dest_first_state, *stg))
1363 if(next_state == dest_first_state)
1372 if(dest_first_state != secondLastState)
1382 for(
auto stmt : global_ending_ops[dest_first_state])
1394 if(not scalar_defs.empty())
1396 for(
auto tree_var : scalar_defs)
1398 if(
HLSMgr->is_register_compatible(tree_var) && useSet.find(tree_var) != useSet.end())
1406 std::map<vertex, std::size_t> in_degree_following_Bb;
1408 for(
auto bbVertex : followingBb)
1410 in_degree_following_Bb[bbVertex] = boost::in_degree(first_state[bbVertex], *stg);
1411 if(in_degree_following_Bb[bbVertex] > 2)
1416 if(in_degree_following_Bb[bbVertex] > 1)
1419 "src state:" + stg->CGetStateInfo(first_state[bbVertex])->name);
1420 BOOST_FOREACH(
EdgeDescriptor oedge, boost::out_edges(first_state[bbVertex], *stg))
1424 if(stg->CGetStateInfo(cstate)->is_dummy)
1432 for(
auto bbVertex : followingBb)
1435 "analyzing BB:" +
STR(fbb->CGetBBNodeInfo(bbVertex)->block->number));
1437 "first state:" + stg->CGetStateInfo(first_state[bbVertex])->name);
1439 "last state:" + stg->CGetStateInfo(last_state[bbVertex])->name);
1440 if(last_state[bbVertex] == first_state[bbVertex])
1442 BOOST_FOREACH(
EdgeDescriptor ei, boost::out_edges(bbVertex, *fbb))
1446 "target BB:" +
STR(fbb->CGetBBNodeInfo(tgtBB)->block->number));
1447 if(boost::in_degree(first_state[tgtBB], *stg) > 1)
1467 for(
auto ops : lastStateConditionalOpList)
1470 global_starting_ops[lastst].remove(ops);
1471 global_executing_ops[lastst].remove(ops);
1472 global_ending_ops[lastst].remove(ops);
1473 global_starting_ops[secondLastState].push_back(ops);
1474 global_executing_ops[secondLastState].push_back(ops);
1475 global_ending_ops[secondLastState].push_back(ops);
1477 wstg->GetStateInfo(secondLastState)->starting_operations.push_back(ops);
1478 wstg->GetStateInfo(secondLastState)->executing_operations.push_back(ops);
1479 wstg->GetStateInfo(secondLastState)->ending_operations.push_back(ops);
1485 for(
auto bbVertex : followingBb)
1488 "analyzing BB:" +
STR(fbb->CGetBBNodeInfo(bbVertex)->block->number));
1489 if(in_degree_following_Bb[bbVertex] > 1)
1492 global_executing_ops, global_ending_ops, defSet, useSet);
1497 global_executing_ops, global_ending_ops, defSet, useSet);
1509 last_state[bbEndingCycle] = secondLastState;
1519 std::list<vertex> linkedStates;
1520 BOOST_FOREACH(
EdgeDescriptor oedge, boost::out_edges(lastst, *stg))
1523 linkedStates.push_back(cstate);
1525 for(
auto cstate : linkedStates)
1554 std::list<vertex>::iterator it, findIter;
1556 for(it = lastStateEndingOp.begin(); it != lastStateEndingOp.end(); ++it)
1558 findIter = std::find(lastStateConditionalOpList.begin(), lastStateConditionalOpList.end(), *it);
1563 if(findIter == lastStateConditionalOpList.end())
1569 tempDependentOp =
check_data_dependency(*it, firstStateNextBb, global_starting_ops, global_executing_ops);
1570 if(tempDependentOp ==
nullptr)
1603 std::list<vertex> StartingOpList = global_starting_ops[state];
1604 std::list<vertex> ExecutingOpList = global_executing_ops[state];
1605 std::list<vertex>::iterator it;
1606 vertex dependentOperation;
1608 for(it = StartingOpList.begin(); it != StartingOpList.end(); ++it)
1615 if(dependentOperation !=
nullptr)
1617 return dependentOperation;
1624 for(it = ExecutingOpList.begin(); it != ExecutingOpList.end(); ++it)
1631 if(dependentOperation !=
nullptr)
1633 return dependentOperation;
1655 const auto op = dfgRef->CGetOpNodeInfo(operation)->GetOperation();
1681 unsigned int currentlyNeededUnit = 0;
1683 for(
auto tempOp : lastStateExecutingOpList)
1687 currentlyNeededUnit++;
1691 BOOST_FOREACH(
EdgeDescriptor oedge, boost::out_edges(lastst, *stg))
1694 unsigned int tempNeededUnit = 0;
1695 for(
auto tempOp :
HLS->
STG->
GetStg()->GetStateInfo(tempSt)->executing_operations)
1733 for(
const auto cur_op : opEndingList)
1735 if(std::find(ignoreList.begin(), ignoreList.end(), cur_op) != ignoreList.end())
1743 for(
auto tree_var : scalar_defs)
1745 if(
HLSMgr->is_register_compatible(tree_var))
1747 defSet.insert(tree_var);
1752 for(
const auto cur_op : opRuningList)
1754 if(std::find(ignoreList.begin(), ignoreList.end(), cur_op) != ignoreList.end())
1762 for(
auto tree_var : scalar_uses)
1764 if(
HLSMgr->is_register_compatible(tree_var) and defSet.find(tree_var) == defSet.end())
1766 useSet.insert(tree_var);
1780 const vertex destinationState,
1788 const auto STGMan =
HLS->
STG;
1789 const auto stg = STGMan->
GetStg();
1791 "moving operations from state: " + STGMan->get_state_name(stateToMove));
1793 "moving operations to state: " + STGMan->get_state_name(destinationState));
1795 "second last state: " + STGMan->get_state_name(secondLastState));
1796 const auto dstStateInfo = stg->GetStateInfo(destinationState);
1797 dstStateInfo->moved_op_use_set = useSet;
1798 dstStateInfo->moved_op_def_set = defSet;
1804 const auto op_it = global_executing_ops.find(stateToMove);
1805 if(op_it != global_executing_ops.end())
1809 dstStateInfo->executing_operations.push_front(operation);
1810 dstStateInfo->moved_exec_op.push_front(operation);
1815 const auto op_it = global_starting_ops.find(stateToMove);
1816 if(op_it != global_starting_ops.end())
1820 dstStateInfo->starting_operations.push_front(operation);
1825 const auto op_it = global_ending_ops.find(stateToMove);
1826 if(op_it != global_ending_ops.end())
1830 dstStateInfo->ending_operations.push_front(operation);
1831 dstStateInfo->moved_ending_op.push_front(operation);
1838 EdgeDescriptor linkingEdge = stg->CGetEdge(stateToMove, destinationState);
1840 "existing edge: " + STGMan->get_state_name(stateToMove) +
"->" +
1841 STGMan->get_state_name(destinationState));
1843 HLS->
STG->
STG_builder->connect_state(secondLastState, destinationState, stg->GetSelector(linkingEdge));
1846 "new edge: " + STGMan->get_state_name(secondLastState) +
"->" +
1847 STGMan->get_state_name(destinationState));
1861 const vertex stateToClone,
1870 const auto toMoveStateInfo = stg->GetStateInfo(stateToMove);
1871 const auto toCloneStateInfo = stg->GetStateInfo(stateToClone);
1872 const auto secondLastStateInfo = stg->GetStateInfo(secondLastState);
1875 "moving operations to state: " + toCloneStateInfo->name +
" that will be cloned");
1877 unsigned int currentBbID = *toMoveStateInfo->BB_ids.begin();
1882 toCloneStateInfo->executing_operations, toCloneStateInfo->starting_operations,
1883 toCloneStateInfo->ending_operations, toCloneStateInfo->BB_ids);
1885 const auto clonedStateInfo = stg->GetStateInfo(clonedState);
1886 clonedStateInfo->is_duplicated =
true;
1887 clonedStateInfo->sourceBb = currentBbID;
1888 clonedStateInfo->clonedState = stateToClone;
1889 clonedStateInfo->moved_op_def_set = defSet;
1890 clonedStateInfo->moved_op_use_set = useSet;
1891 toCloneStateInfo->is_duplicated =
true;
1892 toCloneStateInfo->isOriginalState =
true;
1893 toCloneStateInfo->sourceBb = currentBbID;
1896 "cloned state: " + toCloneStateInfo->name +
" new clone: " + clonedStateInfo->name);
1899 const auto op_it = global_executing_ops.find(stateToMove);
1900 if(op_it != global_executing_ops.end())
1904 clonedStateInfo->executing_operations.push_front(operation);
1905 clonedStateInfo->moved_exec_op.push_front(operation);
1910 const auto op_it = global_starting_ops.find(stateToMove);
1911 if(op_it != global_starting_ops.end())
1915 clonedStateInfo->starting_operations.push_front(operation);
1920 const auto op_it = global_ending_ops.find(stateToMove);
1921 if(op_it != global_ending_ops.end())
1925 clonedStateInfo->ending_operations.push_front(operation);
1926 clonedStateInfo->moved_ending_op.push_front(operation);
1934 EdgeDescriptor linkingEdge = stg->CGetEdge(stateToMove, stateToClone);
1936 "existing edge: " + toMoveStateInfo->name +
"->" + toCloneStateInfo->name);
1938 secondLastState, clonedState,
1939 stateToClone != secondLastState ? stg->GetSelector(linkingEdge) :
1940 TransitionInfo::StateTransitionType::ST_EDGE_NORMAL);
1943 "new edge: " + secondLastStateInfo->name +
"->" + clonedStateInfo->name);
1950 if(stateToClone != secondLastState)
1954 BOOST_FOREACH(
EdgeDescriptor oe, boost::out_edges(stateToClone, *stg))
1958 THROW_ASSERT(successor != stateToMove,
"unexpected case");
1959 const auto new_successor = ((successor == stateToMove) ? clonedState : successor);
1961 "new successor: " + stg->CGetStateInfo(new_successor)->name);
1963 HLS->
STG->
STG_builder->connect_state(clonedState, new_successor, stg->GetSelector(oe));
1966 "new edge: " + clonedStateInfo->name +
"->" + stg->CGetStateInfo(new_successor)->name);
1967 if(successor == stateToClone)
1972 "all path for " + stg->CGetStateInfo(successor)->name +
" set to true");
1973 stg->GetStateInfo(successor)->all_paths =
true;
1983 BOOST_FOREACH(
EdgeDescriptor oe, boost::out_edges(stateToClone, *stg))
1987 if(successor == stateToMove)
1993 successor != clonedState ? stg->GetSelector(oe) : TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK;
1997 "new edge: " + clonedStateInfo->name +
"->" + stg->GetStateInfo(successor)->name);
#define TYPE_SWITCH
constant identifying the node type of a SWITCH operation.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
const HLS_managerRef HLSMgr
information about all the HLS synthesis
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
Basic block control flow graph.
File containing functions and utilities to support the printing of debug messagges.
refcount< StateTransitionGraphManager > StateTransitionGraphManagerRef
refcount definition to allocate the class
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
const StateTransitionGraph_constructorRef STG_builder
reference to the class for building the graph
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
This file contains the structures needed to manage a graph that will represent the state transition g...
const ParameterConstRef Param
class containing all the parameters
#define TYPE_MULTIIF
constant identifying the a multi-way if
#define TYPE_VPHI
constant string identifying an operation node of type virtual phi-nodes
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void move_without_duplication(const vertex stateToMove, const vertex secondLastState, const vertex destinationState, const std::map< vertex, std::list< vertex >> &global_starting_ops, const std::map< vertex, std::list< vertex >> &global_executing_ops, const std::map< vertex, std::list< vertex >> &global_ending_ops, const CustomOrderedSet< unsigned int > &defSet, const CustomOrderedSet< unsigned int > &useSet)
Copies all the operations of the state to move in the following.
Generic class managing all the stg creation algorithms.
#define TYPE_IF
constant identifying the node type of an IF operation.
const StateTransitionGraphConstRef CGetEPPStg() const
Returns pointer to acyclic STG with additional edges for Efficient Path Profiling.
const int output_level
The output level.
void move_with_duplication(const vertex stateToMove, const vertex secondLastState, const vertex stateToClone, const std::map< vertex, std::list< vertex >> &global_starting_ops, const std::map< vertex, std::list< vertex >> &global_executing_ops, const std::map< vertex, std::list< vertex >> &global_ending_ops, const CustomOrderedSet< unsigned int > &defSet, const CustomOrderedSet< unsigned int > &useSet)
Duplicates the first state of the destination bb and copies all the operations of the state to move i...
vertex get_entry_state() const
Gets vertex that represents state that contains entry node.
RelationshipType
The relationship type.
DesignFlowStep_Status InternalExec() override
Execute the step.
Source must be executed to satisfy target.
AbsControlStep get_cstep(const vertex &op) const
Returns the clock cycle where the given operation has been scheduled.
#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.
CustomOrderedMap< T, U > CustomMap
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
AbsControlStep get_cstep_end(const vertex &op) const
Return the last clock cycle in which the operation execute.
void ComputeCyclesCount(bool is_pipelined)
Compute minimum and maximum number of cycles for bounded scheduling.
AllocationInformationRef allocation_information
Store the technology information.
vertex get_exit_state() const
Gets vertex that represents state that contains exit node.
Collect information about resource performance.
Class specification of the manager of the technology library data structures.
Class used to manage a graph into finite state machine representation; it contains methods to build t...
Data structure describing a basic block at tree level.
#define INTERFACE_LIBRARY
interface library
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
redefinition of map to manage ordered/unordered structures
Include a set of utilities used to manage CPU time measures.
#define TYPE_LOAD
Constant string identifying a memory load operation.
StateTransitionGraphRef GetEPPStg()
Returns pointer to acyclic STG with additional edges for Efficient Path Profiling.
#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.
#define FB_CFG_SELECTOR
Feedback control flow edge selector.
void print_statistics() const
bool registered_inputs
true when the module has registered inputs
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
#define START_TIME(time_var)
Macro used to store the start time into time_var.
#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.
const CustomUnorderedSet< std::tuple< HLSFlowStep_Type, HLSFlowStepSpecializationConstRef, HLSFlowStep_Relationship > > ComputeHLSRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
ScheduleRef Rsch
Store the refcounted scheduling of the operations.
OpVertexSchedSorter(const ScheduleConstRef _sch)
Constructor.
bool is_instantaneous_operation(vertex operation)
returns true if the operation takes no time
#define TYPE_GOTO
A vertex is of type TYPE_GOTO when it is associated with a goto expression.
This class specifies the characteristic of a particular operation working on a given functional unit...
unsigned map[NUM_VERTICES]
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Data structure used to store the schedule of the operations.
File contanining the structures necessary to manage a graph that will represent a state transition gr...
Class specification of the data structures used to manage technology information. ...
#define TYPE_EXTERNAL
constant identifying the node type of a EXTERNAL operation (a function call)
vertex check_data_dependency(vertex operation, vertex state, std::map< vertex, std::list< vertex >> &global_starting_ops, std::map< vertex, std::list< vertex >> &global_executing_ops)
This method takes as parameters an operation and a state of the STG graph, and returns the operation ...
#define default_COND
constant used to represent label "default" of a switch construct
Basic block control flow graph with feedback.
Target must be reexecuted.
redefinition of set to manage ordered/unordered structures
#define STOP_TIME(time_var)
Macro used to store the elapsed time into time_var.
Datastructure to describe functions allocation in high-level synthesis.
const ScheduleConstRef sch
reference to the scheduling
#define TYPE_STORE
Constant string identifying a memory store operation.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
#define T_COND
constant used to represent control edges representing a true edge of a conditional statement...
This file contains the structures needed to manage a graph that will represent the state transition g...
static std::string GetFUName(const std::string &fname, const HLS_managerRef HLSMgr)
Return FU used to implement given function.
#define TYPE_RW
Constant identifying if a TYPE_EXTERNAL write or read memory.
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
static std::string NormalizeTypename(const std::string &id)
Return normalized name of types and variables.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
#define VIEW_CONVERT_EXPR
constant string identifying view convert expressions
bool can_be_moved(std::list< vertex > &lastStateEndingOp, std::list< vertex > &lastStateConditionalOpList, vertex firstStateNextBb, std::map< vertex, std::list< vertex >> &global_starting_ops, std::map< vertex, std::list< vertex >> &global_executing_ops)
Returns true if all the operations in the list can be moved to the state specified.
bool res_const_operation(vertex &operation, std::list< vertex > &lastStateExecutingOpList, vertex lastSt)
returns true if the number of fu available prevents us from moving that operation in the next state ...
Data structure definition for HLS constraints.
bool operator()(const vertex x, const vertex y) const
Compare scheduling of two vertices.
This file collects some utility functions.
std::string print_cpu_time(long int t)
massage a long which represents a time interval in milliseconds, into a string suitable for output ...
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
bool registered_done_port
true when the done port is registered
#define OUTPUT_LEVEL_PEDANTIC
verbose debugging print is performed.
static size_t compute_edge_increments(const StateTransitionGraphManagerRef &STG)
void optimize_cycles(vertex bbEndingCycle, CustomUnorderedMap< vertex, vertex > &first_state, CustomUnorderedMap< vertex, vertex > &last_state, std::map< vertex, std::list< vertex >> &global_starting_ops, std::map< vertex, std::list< vertex >> &global_ending_ops, std::map< vertex, std::list< vertex >> &global_executing_ops, std::map< vertex, std::list< vertex >> &global_onfly_ops)
Given two bb linked by a forwarding edge, this method tries to move overlap the execution of the last...
#define ASSIGN
constant string identifying the operation performed by an assignment.
Data structure used to store the functional-unit binding of the vertexes.
#define WORK_LIBRARY
working library.
BB_based_stg(const ParameterConstRef _parameters, const HLS_managerRef HLSMgr, unsigned int funId, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
#define INFINITE_UINT
UNSIGNED INT representing infinite.
Class specification of the basic_block structure.
hlsRef HLS
HLS data structure of the function to be analyzed.
static void add_EPP_edges(const StateTransitionGraphManagerRef &STG)
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
interface of loops finding algorithm
void compute_EPP_edge_increments(const std::map< vertex, std::list< vertex >> &starting_ops) const
If hardware discrepancy analysis is activated, use this function to compute the edge increments for t...
this class is used to manage the command-line or XML options.
#define F_COND
constant used to represent control edges representing a false edge of a conditional statement...
StateTransitionGraphRef GetStg()
Returns pointer to state transition graph created.
Class implementation of the structural_manager.
StateTransitionGraphManagerRef STG
Store the refcounted state transition graph.
x
Return the smallest n such that 2^n >= _x.
void compute_use_def(const std::list< vertex > &opEndingList, const std::list< vertex > &opRuningList, const std::list< vertex > &ignoreList, CustomOrderedSet< unsigned int > &useSet, CustomOrderedSet< unsigned int > &defSet, const OpGraphConstRef data)
computes the variables used and defined in the by the given list of operations, and saves them in the...
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
#define TYPE_RET
constant string identifying an operation node of type return expr
Datastructure to describe functions allocation in high-level synthesis.
#define NOP_EXPR
constant string identifying some conversion expressions
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
#define CFG_SELECTOR
Control flow graph edge selector.
Data structure definition for high-level synthesis flow.
const StateTransitionGraphConstRef CGetStg() const
Returns pointer to state transition graph created.
Datastructure to represent memory information in high-level synthesis.
void add_multi_unbounded_obj(vertex s, const CustomOrderedSet< vertex > &ops)
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
#define CONVERT_EXPR
constant string identifying some conversion expressions
std::string get_state_name(vertex state) const
Get the name of a state.
size_t call_sites_number
The number of call points to this function.
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 ...