43 #include "config_PANDA_DATA_INSTALLDIR.hpp" 83 #define EPSILON 0.000000001 84 #define ENCODE_FDNAME(arg_name, MODE, interface_type) \ 85 ((arg_name) + STR_CST_interface_parameter_keyword + (MODE) + (interface_type)) 116 interface_info(
const std::string& _arg_id,
const std::string& _interface_fname,
bool fixed_size,
118 : _fixed_size(fixed_size),
121 interface_fname(_interface_fname),
126 parm_attrs(_parm_attrs),
127 iface_attrs(_iface_attrs)
135 bool is_signed, is_fixed;
136 const auto type_name =
137 std::regex_replace(_type_name, std::regex(
"(ac_channel|stream|hls::stream)<(.*)>"),
"$2");
140 unsigned long long _bitwidth = 0;
143 _bitwidth = ac_bitwidth;
147 else if(_type_name.empty())
163 THROW_ERROR(
"Struct type not supported for interfacing: " +
STR(elt_type));
182 alignment =
std::max(alignment, _alignment);
185 if(_fixed_size && bitwidth && bitwidth != _bitwidth)
187 THROW_ERROR(
"Unaligned access not allowed for required interface!");
189 bitwidth =
std::max(bitwidth, _bitwidth);
201 return GetPointer<const identifier_node>(
GET_CONST_NODE(dn->name))->strg;
206 std::vector<unsigned int> sorted_roots;
208 const auto CG = CGM->CGetCallGraph();
209 std::vector<vertex> sorted_cg;
210 sorted_cg.reserve(boost::num_vertices(*CG));
211 boost::topological_sort(*CG, std::back_inserter(sorted_cg));
212 auto root_fid = CGM->GetRootFunctions();
213 for(
auto v : sorted_cg)
215 const auto fid = CGM->get_function(v);
216 auto r_it = root_fid.find(fid);
217 if(r_it != root_fid.end())
219 root_fid.erase(r_it);
220 sorted_roots.push_back(fid);
229 const auto fv = CGM->GetVertex(fid);
230 const auto CG = CGM->CGetCallGraph();
231 const auto [calls, calls_end] = boost::in_edges(fv, *CG);
234 const auto edge_info = CG->CGetFunctionEdgeInfo(*calls);
235 if(edge_info->direct_call_points.size() == 1)
237 const auto call_id = *edge_info->direct_call_points.begin();
238 return {CGM->get_function(boost::source(*calls, *CG)), call_id};
246 if(
const auto ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(stmt)))
248 const auto ce = GetPointer<const call_expr>(
GET_CONST_NODE(ga->op1));
251 else if(
const auto gc = GetPointer<const gimple_call>(
GET_CONST_NODE(stmt)))
256 return std::vector<tree_nodeRef>();
263 if(
const auto pd = GetPointer<const parm_decl>(
GET_CONST_NODE(base_var)))
265 const auto [caller_id, call_id] =
GetCallStmt(CGM, fid);
268 const auto fd = GetPointer<const function_decl>(TM->
CGetTreeNode(fid));
269 const auto parm_idx =
static_cast<size_t>(
271 std::find_if(fd->list_of_args.begin(), fd->list_of_args.end(), [&](
const auto& tn) {
274 THROW_ASSERT(parm_idx < fd->list_of_args.size(),
"Parameter not found.");
276 THROW_ASSERT(call_args.size() == fd->list_of_args.size(),
277 "Expected formal and actual parameters' count match.");
297 switch(relationship_type)
301 relationships.insert(std::make_pair(DATAFLOW_CG_EXT,
ALL_FUNCTIONS));
303 relationships.insert(std::make_pair(IR_LOWERING,
ALL_FUNCTIONS));
304 relationships.insert(std::make_pair(PARM2SSA,
ALL_FUNCTIONS));
305 relationships.insert(std::make_pair(USE_COUNTING,
ALL_FUNCTIONS));
321 return relationships;
327 switch(relationship_type)
336 const auto technology_flow_step_factory = GetPointer<const TechnologyFlowStepFactory>(
338 const auto technology_flow_signature =
341 const auto technology_design_flow_step =
342 technology_flow_step ?
343 design_flow_graph->CGetDesignFlowStepInfo(technology_flow_step)->design_flow_step :
345 relationship.insert(technology_design_flow_step);
365 const auto HLSMgr = GetPointer<HLS_manager>(
AppM);
367 const auto TM =
AppM->get_tree_manager();
368 const auto CGM =
AppM->CGetCallGraphManager();
369 const auto CG = CGM->CGetCallGraph();
372 std::set<unsigned int> modified;
373 const auto add_to_modified = [&](
const tree_nodeRef& tn) {
377 for(
const auto root_id : sorted_roots)
379 const auto fnode = TM->CGetTreeReindex(root_id);
380 const auto fd = GetPointer<const function_decl>(
GET_CONST_NODE(fnode));
385 auto func_arch = HLSMgr->module_arch->GetArchitecture(fsymbol);
390 const auto fsign = [&]() {
392 if(cxa_fname.empty())
400 size_t parm_index = 0;
402 func_arch->attrs[FunctionArchitecture::func_symbol] = fsymbol;
406 for(
const auto&
arg : fd->list_of_args)
409 const auto parm_name = [&]() {
410 std::stringstream ss;
414 auto& iface_attrs = func_arch->ifaces[parm_name];
415 iface_attrs[FunctionArchitecture::iface_name] = parm_name;
416 iface_attrs[FunctionArchitecture::iface_mode] =
"default";
417 auto& parm_attrs = func_arch->parms[parm_name];
418 const std::string tname(*typename_it);
420 parm_attrs[FunctionArchitecture::parm_port] = parm_name;
421 parm_attrs[FunctionArchitecture::parm_typename] = parm_attrs[FunctionArchitecture::parm_original_typename] =
423 parm_attrs[FunctionArchitecture::parm_index] = std::to_string(parm_index);
424 parm_attrs[FunctionArchitecture::parm_bundle] = parm_name;
425 if(tname.find(
"_fixed<") != std::string::npos)
427 parm_attrs[FunctionArchitecture::parm_includes] +=
428 STR(
";" PANDA_DATA_INSTALLDIR
"/panda/ac_types/include/" + tname.substr(0, 2) +
"_fixed.h");
430 if(tname.find(
"_int<") != std::string::npos)
432 parm_attrs[FunctionArchitecture::parm_includes] +=
433 STR(
";" PANDA_DATA_INSTALLDIR
"/panda/ac_types/include/" + tname.substr(0, 2) +
"_int.h");
435 if(tname.find(
"ac_channel<") != std::string::npos)
437 parm_attrs[FunctionArchitecture::parm_includes] +=
438 STR(
";" PANDA_DATA_INSTALLDIR
"/panda/ac_types/include/ac_channel.h");
444 HLSMgr->module_arch->AddArchitecture(fsymbol, func_arch);
449 const auto is_dataflow_module =
450 func_arch->attrs.find(FunctionArchitecture::func_dataflow) != func_arch->attrs.end() &&
451 func_arch->attrs.find(FunctionArchitecture::func_dataflow)->second ==
"module";
452 if(is_dataflow_module)
454 const auto [caller_id, call_id] =
GetCallStmt(CGM, root_id);
455 THROW_ASSERT(call_id,
"Expected unique call point for dataflow module " + fsymbol +
".");
456 const auto call_stmt = TM->CGetTreeReindex(call_id);
466 const auto parm_attr = std::find_if(func_arch->parms.begin(), func_arch->parms.end(), [&](
auto& it) {
467 return it.second.at(FunctionArchitecture::parm_index) == std::to_string(idx);
469 THROW_ASSERT(parm_attr != func_arch->parms.end(),
"Expected parameter index " + std::to_string(idx));
470 auto& current_bundle = parm_attr->second.at(FunctionArchitecture::parm_bundle);
471 std::string bundle_name;
474 func_arch->ifaces[current_bundle].at(FunctionArchitecture::iface_mode) =
"default";
476 "---Parameter " + parm_attr->second.at(FunctionArchitecture::parm_port) +
477 " forwarded from caller function");
484 "---Parameter " + parm_attr->second.at(FunctionArchitecture::parm_port) +
485 " is constant at this call point");
489 else if(
const auto dn = GetPointer<const decl_node>(
GET_CONST_NODE(base_var)))
497 func_arch->ifaces[bundle_name] = func_arch->ifaces.at(current_bundle);
498 func_arch->ifaces[bundle_name].at(FunctionArchitecture::iface_name) = bundle_name;
499 func_arch->ifaces.erase(current_bundle);
500 current_bundle = bundle_name;
501 THROW_ASSERT(fd->list_of_args.size() > idx,
"Unexpected function parameters count");
502 auto pd = GetPointerS<parm_decl>(
GET_NODE(fd->list_of_args.at(idx)));
505 "---Parameter " + parm_attr->second.at(FunctionArchitecture::parm_port) +
506 " renamed and bound to internal interface " +
STR(base_var) +
" - " + bundle_name);
507 parm_attr->second.at(FunctionArchitecture::parm_port) = bundle_name;
508 func_arch->parms[bundle_name] = parm_attr->second;
509 func_arch->parms.erase(parm_attr);
517 const auto sl = GetPointer<statement_list>(
GET_NODE(fd->body));
519 "Expected entry and exit basic blocks for function " + fsymbol);
520 const auto& bb_entry =
sl->list_of_bloc.at(
BB_ENTRY);
521 THROW_ASSERT(bb_entry->list_of_succ.size() == 1,
"Expected single entry basic block for function " + fsymbol);
522 const auto& bb_first =
sl->list_of_bloc.at(bb_entry->list_of_succ.front());
523 for(
auto& [bbi, bb] :
sl->list_of_bloc)
525 if(std::find(bb->list_of_succ.begin(), bb->list_of_succ.end(),
BB_EXIT) != bb->list_of_succ.end())
528 "---BB" + std::to_string(bbi) +
" loop-back to entry BB" +
529 std::to_string(bb_first->number));
530 bb->list_of_succ.clear();
531 bb->list_of_succ.push_back(bb_first->number);
532 bb_first->list_of_pred.push_back(bbi);
533 const auto return_stmt = bb->CGetStmtList().back();
535 "Expected return statement as last statement");
542 std::map<std::string, TreeNodeSet> bundle_vdefs;
543 for(
const auto&
arg : fd->list_of_args)
549 THROW_ASSERT(func_arch->parms.find(arg_name) != func_arch->parms.end(),
550 "Not matched parameter name: " + arg_name);
551 auto& parm_attrs = func_arch->parms.at(arg_name);
552 THROW_ASSERT(parm_attrs.find(FunctionArchitecture::parm_bundle) != parm_attrs.end(),
553 "Missing parameter bundle name");
554 parm_attrs.emplace(FunctionArchitecture::parm_offset,
"off");
558 const auto array_size =
560 parm_attrs.emplace(FunctionArchitecture::parm_size_in_bytes,
563 THROW_ASSERT(func_arch->ifaces.find(parm_attrs.at(FunctionArchitecture::parm_bundle)) !=
564 func_arch->ifaces.end(),
565 "Missing parameter bundle: " + parm_attrs.at(FunctionArchitecture::parm_bundle));
566 auto& iface_attrs = func_arch->ifaces.at(parm_attrs.at(FunctionArchitecture::parm_bundle));
567 iface_attrs[FunctionArchitecture::iface_direction] =
port_o::GetString(port_o::IN);
569 iface_attrs[FunctionArchitecture::iface_alignment] =
571 auto& interface_type = iface_attrs[FunctionArchitecture::iface_mode];
574 interface_type.size(),
575 "Expected interface type for parameter '" + arg_name +
"'");
578 interface_type ==
"bus")
580 interface_type =
"default";
582 else if(interface_type !=
"default")
584 const auto arg_ssa_id =
AppM->getSSAFromParm(root_id, arg_id);
585 const auto arg_ssa = TM->GetTreeReindex(arg_ssa_id);
587 if(GetPointerS<const ssa_name>(
GET_CONST_NODE(arg_ssa))->CGetUseStmts().empty())
589 THROW_WARNING(
"Parameter '" + arg_name +
"' not used by any statement");
594 interface_type =
"none";
598 THROW_ERROR(
"parameter not used: specified interface does not make sense - " + interface_type);
605 interface_info info(arg_name, fsymbol, interface_type !=
"m_axi", parm_attrs, iface_attrs);
606 info.
update(arg_ssa, parm_attrs.at(FunctionArchitecture::parm_typename),
parameters);
608 std::list<tree_nodeRef> writeStmt;
609 std::list<tree_nodeRef> readStmt;
611 const auto isRead = !readStmt.empty();
612 const auto isWrite = !writeStmt.empty();
614 if(!isRead && !isWrite)
616 if(interface_type ==
"m_axi")
620 THROW_ERROR(
"Parameter '" + arg_name +
"' cannot have interface type '" + interface_type +
621 "' since no load/store is associated with it");
626 (8ULL * std::stoull(parm_attrs.at(FunctionArchitecture::parm_size_in_bytes))) / info.
bitwidth :
629 info.
name = [&]() -> std::string {
630 if(isRead && isWrite)
632 iface_attrs[FunctionArchitecture::iface_direction] =
port_o::GetString(port_o::IO);
634 if(interface_type ==
"array")
638 parm_attrs[FunctionArchitecture::parm_elem_count] =
STR(info.
factor);
642 else if(interface_type ==
"ptrdefault")
646 parm_attrs[FunctionArchitecture::parm_elem_count] =
STR(info.
factor);
649 else if(
parameters->IsParameter(
"none-ptrdefault") &&
650 parameters->GetParameter<
int>(
"none-ptrdefault") == 1)
654 else if(
parameters->IsParameter(
"none-registered-ptrdefault") &&
655 parameters->GetParameter<
int>(
"none-registered-ptrdefault") == 1)
657 iface_attrs[FunctionArchitecture::iface_register] =
"";
662 else if(interface_type ==
"fifo" || interface_type ==
"axis")
664 THROW_ERROR(
"parameter " + arg_name +
" cannot have interface " + interface_type +
665 " because it cannot be read and written at the same time");
670 iface_attrs[FunctionArchitecture::iface_direction] =
port_o::GetString(port_o::IN);
672 if(interface_type ==
"array")
676 parm_attrs[FunctionArchitecture::parm_elem_count] =
STR(info.
factor);
680 else if(interface_type ==
"ptrdefault")
684 parm_attrs[FunctionArchitecture::parm_elem_count] =
STR(info.
factor);
689 else if(interface_type ==
"ovalid")
691 THROW_ERROR(
"parameter " + arg_name +
" cannot have interface " + interface_type +
692 " because it is read only");
697 iface_attrs[FunctionArchitecture::iface_direction] =
port_o::GetString(port_o::OUT);
699 if(interface_type ==
"array")
703 parm_attrs[FunctionArchitecture::parm_elem_count] = std::to_string(info.
factor);
707 else if(interface_type ==
"ptrdefault")
711 parm_attrs[FunctionArchitecture::parm_elem_count] = std::to_string(info.
factor);
714 else if(
parameters->IsParameter(
"none-ptrdefault") &&
715 parameters->GetParameter<
int>(
"none-ptrdefault") == 1)
719 else if(
parameters->IsParameter(
"none-registered-ptrdefault") &&
720 parameters->GetParameter<
int>(
"none-registered-ptrdefault") == 1)
722 iface_attrs[FunctionArchitecture::iface_register] =
"";
728 return interface_type;
730 iface_attrs[FunctionArchitecture::iface_bitwidth] = std::to_string(info.
bitwidth);
731 iface_attrs[FunctionArchitecture::iface_alignment] = std::to_string(info.
alignment);
732 if(interface_type ==
"fifo" || interface_type ==
"axis")
734 iface_attrs.emplace(FunctionArchitecture::iface_depth,
"0");
736 interface_type = info.
name;
740 std::set<std::string> operationsR, operationsW;
742 const auto commonRWSignature = interface_type ==
"array" || interface_type ==
"m_axi";
743 const auto& bundle_name = iface_attrs.at(FunctionArchitecture::iface_name);
744 const auto require_flush =
745 interface_type ==
"m_axi" &&
746 iface_attrs.find(FunctionArchitecture::iface_cache_line_count) != iface_attrs.end();
750 const auto& vdef = GetPointerS<const gimple_node>(
GET_CONST_NODE(stmt))->vdef;
753 bundle_vdefs[bundle_name].insert(vdef);
757 for(
const auto& stmt : readStmt)
759 setReadInterface(stmt, bundle_name, operationsR, commonRWSignature, interface_datatype, tree_man, TM);
760 add_to_modified(stmt);
763 for(
const auto& stmt : writeStmt)
765 setWriteInterface(stmt, bundle_name, operationsW, commonRWSignature, interface_datatype, tree_man,
767 add_to_modified(stmt);
772 else if(interface_type ==
"none")
774 THROW_ERROR(
"Interface type '" + interface_type +
"' for parameter '" + arg_name +
"' unexpected");
778 THROW_ERROR(
"Interface type '" + interface_type +
"' for parameter '" + arg_name +
"' is not supported");
785 "---Direction : " + iface_attrs.at(FunctionArchitecture::iface_direction));
787 "---Bundle : " + parm_attrs.at(FunctionArchitecture::parm_bundle));
789 "---Bitwidth : " + iface_attrs.at(FunctionArchitecture::iface_bitwidth));
790 if(parm_attrs.find(FunctionArchitecture::parm_elem_count) != parm_attrs.end())
793 "---Size : " + parm_attrs.at(FunctionArchitecture::parm_elem_count));
796 "---Alignment : " + iface_attrs.at(FunctionArchitecture::iface_alignment));
800 for(
const auto& bundle_vdef : bundle_vdefs)
802 const auto& bundle_name = bundle_vdef.first;
803 const auto& vdefs = bundle_vdef.second;
806 const auto generate_fini_call = [&]() {
807 const auto fini_fname =
ENCODE_FDNAME(bundle_name,
"_Flush_",
"m_axi");
808 std::vector<tree_nodeConstRef> argsT;
815 std::vector<tree_nodeRef>
args;
816 args.push_back(TM->CreateUniqueIntegerCst(1, argsT.at(0)));
817 args.push_back(TM->CreateUniqueIntegerCst(0, argsT.at(1)));
819 const auto fini_node = GetPointerS<gimple_node>(
GET_CONST_NODE(fini_call));
820 for(
const auto& vdef : vdefs)
822 fini_node->AddVuse(vdef);
827 const auto sl = GetPointerS<const statement_list>(
GET_CONST_NODE(fd->body));
828 for(
const auto& bbi_bb :
sl->list_of_bloc)
830 const auto& bb = bbi_bb.second;
831 const auto is_last = std::count(bb->list_of_succ.cbegin(), bb->list_of_succ.cend(),
BB_EXIT);
832 if(bb->number !=
BB_ENTRY && is_last)
834 const auto fini_call = generate_fini_call();
835 THROW_ASSERT(bb->CGetStmtList().size(),
"BB" +
STR(bb->number) +
" should not be empty");
836 const auto last_stmt = bb->CGetStmtList().back();
839 bb->PushBefore(fini_call, last_stmt,
AppM);
843 bb->PushBack(fini_call,
AppM);
846 "---Added function call " +
STR(fini_call) +
" to BB" +
STR(bb->number));
857 for(
auto it = HLSMgr->module_arch->cbegin(); it != HLSMgr->module_arch->cend();)
859 const auto fnode = TM->GetFunction(it->first);
860 if(!fnode || (it->second->attrs.size() <= 2 && std::find(sorted_roots.begin(), sorted_roots.end(),
864 "Erase function architecture for function " + it->first);
865 it = HLSMgr->module_arch->erase(it);
876 for(
const auto& f_id : modified)
878 AppM->GetFunctionBehavior(f_id)->UpdateBBVersion();
886 std::list<tree_nodeRef>& writeStmt, std::list<tree_nodeRef>& readStmt,
889 const auto TM =
AppM->get_tree_manager();
897 const std::vector<tree_nodeRef>& call_args,
tree_nodeRef& ssa_var) -> call_type {
898 THROW_ASSERT(arg_var && fd_node,
"unexpected condition");
900 const auto call_fd = [&]() {
903 if(fd_kind == addr_expr_K)
913 const auto called_fname = [&]() {
916 return demangled.size() ? demangled : fname;
923 const auto func_arch = GetPointer<HLS_manager>(
AppM)->module_arch->GetArchitecture(info.
interface_fname);
925 const auto bundle_id = func_arch->parms.at(arg_id).at(FunctionArchitecture::parm_bundle);
926 const auto info_bundle_id = func_arch->parms.at(info.
arg_id).at(FunctionArchitecture::parm_bundle);
927 if(bundle_id != info_bundle_id)
929 THROW_ERROR(
"Pattern not supported with required I/O interface: parameters '" + arg_id +
"' and '" +
930 info.
arg_id +
"' share a memory operation");
933 return call_type::ct_forward;
935 else if(called_fname.find(
"ac_channel") != std::string::npos)
937 if(called_fname.find(
"::_read") != std::string::npos)
939 if(call_fd->list_of_args.size() >= 1 && call_fd->list_of_args.size() <= 3)
942 if(ret_type->get_kind() == function_type_K || ret_type->get_kind() == method_type_K)
944 const auto ft = GetPointerS<const function_type>(ret_type);
951 THROW_ASSERT(call_fd->list_of_args.size() >= 2,
"unexpected condition");
952 THROW_ASSERT(call_args.size() >= 2,
"unexpected condition");
953 auto first_arg = call_args.at(0);
956 THROW_ASSERT(ssa_var != first_arg,
"unexpected condition");
968 return call_type::ct_read;
970 else if(called_fname.find(
"::_write") != std::string::npos)
972 if(call_fd->list_of_args.size() == 2)
975 if(ret_type->get_kind() == void_type_K)
981 auto second_arg = call_args.at(1);
983 THROW_ASSERT(ssa_var != second_arg,
"unexpected condition");
987 ssa_var = call_fd->list_of_args.at(1);
994 return call_type::ct_write;
998 THROW_UNREACHABLE(
"Hardware function " + called_fname +
" interfacing not supported.");
1001 size_t par_index = 0
U;
1002 for(
auto use_idx = 0
U; use_idx < use_count; ++use_idx, ++par_index)
1005 par_index = [&](
size_t start_idx) {
1006 for(
auto idx = start_idx; idx < call_args.size(); ++idx)
1014 return static_cast<size_t>(-1);
1016 THROW_ASSERT(call_fd->list_of_args.size() > par_index,
"unexpected condition");
1017 const auto called_param = call_fd->list_of_args.at(par_index);
1020 const auto call_arg_ssa = TM->CGetTreeReindex(call_arg_ssa_id);
1022 if(GetPointerS<const ssa_name>(
GET_CONST_NODE(call_arg_ssa))->CGetUseStmts().size())
1028 "-->Pointer forwarded as function argument " +
STR(par_index));
1033 return call_type::ct_forward;
1036 if(ct == call_type::ct_forward)
1040 if(ct == call_type::ct_read)
1042 readStmt.push_back(stmt);
1046 else if(ct == call_type::ct_write)
1048 writeStmt.push_back(stmt);
1056 "---SKIPPED FUNCTION: already visited through argument " + ssa_node->
ToString());
1060 std::queue<tree_nodeRef> chase_ssa;
1061 chase_ssa.push(ssa_node);
1062 while(chase_ssa.size())
1064 ssa_node = chase_ssa.front();
1065 const auto ssa_var = GetPointer<const ssa_name>(
GET_CONST_NODE(ssa_node));
1068 "-->SSA VARIABLE: " + ssa_var->ToString() +
" with " +
STR(ssa_var->CGetUseStmts().size()) +
1070 for(
const auto& stmt_count : ssa_var->CGetUseStmts())
1073 const auto& use_count = stmt_count.second;
1075 if(
const auto ga = GetPointer<const gimple_assign>(use_stmt))
1079 if(op0_kind == mem_ref_K)
1081 if(op1_kind == mem_ref_K)
1083 THROW_ERROR(
"Pattern currently not supported: *x=*y; " + use_stmt->ToString());
1088 "unexpected condition");
1092 push_stmt(stmt_count.first, call_type::ct_write, ga->op1);
1096 else if(op1_kind == mem_ref_K)
1098 push_stmt(stmt_count.first, call_type::ct_read, ga->op0);
1102 chase_ssa.push(ga->op0);
1105 else if(op1_kind == call_expr_K)
1107 const auto ce = GetPointerS<const call_expr>(
GET_CONST_NODE(ga->op1));
1114 const auto ct = propagate_arg_use(ssa_node, use_count, ce->fn, ce->args, ssa_val);
1115 push_stmt(stmt_count.first, ct, ssa_val);
1117 else if(op1_kind == eq_expr_K || op1_kind == ne_expr_K || op1_kind == gt_expr_K || op1_kind == lt_expr_K ||
1118 op1_kind == ge_expr_K || op1_kind == le_expr_K)
1120 THROW_WARNING(
"Pattern potentially not supported: pointer parameter is used in a compare statement: " +
1121 use_stmt->ToString() +
":" +
GET_CONST_NODE(ga->op1)->get_kind_text());
1127 THROW_WARNING(
"Pattern potentially not supported: parameter converted to non-pointer type: " +
1128 use_stmt->ToString() +
":" +
GET_CONST_NODE(ga->op1)->get_kind_text());
1130 else if(op1_kind != nop_expr_K && op1_kind != view_convert_expr_K && op1_kind != ssa_name_K &&
1131 op1_kind != pointer_plus_expr_K && op1_kind != cond_expr_K)
1133 THROW_WARNING(
"Pattern potentially not supported: parameter used in a non-supported statement: " +
1134 use_stmt->ToString() +
":" +
GET_CONST_NODE(ga->op1)->get_kind_text());
1139 else if(
const auto gc = GetPointer<const gimple_call>(use_stmt))
1143 if(fn_node->get_kind() == addr_expr_K)
1145 const auto ae = GetPointerS<const addr_expr>(fn_node);
1147 if(ae_op->get_kind() == function_decl_K)
1150 const auto ct = propagate_arg_use(ssa_node, use_count, ae->op, gc->args, ssa_val);
1151 push_stmt(stmt_count.first, ct, ssa_val);
1155 THROW_ERROR(
"unexpected pattern: " + ae_op->ToString());
1160 THROW_ERROR(
"unexpected pattern: " + fn_node->ToString());
1167 else if(
const auto gp = GetPointer<const gimple_phi>(use_stmt))
1170 THROW_ASSERT(!ssa_var->virtual_flag,
"unexpected condition");
1175 THROW_ERROR(
"USE PATTERN unexpected: " + use_stmt->ToString());
1194 const auto fd = GetPointer<const function_decl>(
GET_CONST_NODE(fnode));
1196 const auto func_arch = GetPointerS<HLS_manager>(
AppM)->module_arch->GetArchitecture(fsymbol);
1201 auto bname = func_arch->parms.at(pname).at(FunctionArchitecture::parm_bundle);
1205 func_arch->parms.erase(pname);
1206 THROW_ASSERT(ecount,
"Expected parameter information for parameter " + pname +
" in function " + fsymbol);
1207 const auto is_bundle_used =
1208 std::any_of(func_arch->parms.begin(), func_arch->parms.end(), [&](
const auto& name_attrs) {
1209 return name_attrs.second.at(FunctionArchitecture::parm_bundle) == bname;
1213 func_arch->ifaces.erase(bname);
1215 THROW_ASSERT(func_arch->parms.find(pname) == func_arch->parms.end(),
1216 "Duplicate parameter name " + pname +
" in " + fsymbol +
".");
1217 bname = info.
iface_attrs.at(FunctionArchitecture::iface_name);
1219 func_arch->parms[pname].at(FunctionArchitecture::parm_port) = pname;
1220 func_arch->parms[pname].at(FunctionArchitecture::parm_bundle) = bname;
1221 if(func_arch->ifaces.find(bname) == func_arch->ifaces.end())
1227 THROW_ASSERT(func_arch->ifaces.find(bname)->second.at(FunctionArchitecture::iface_mode) ==
1228 info.
iface_attrs.at(FunctionArchitecture::iface_mode),
1229 "Duplicate interface bundle name " + bname +
" in " + fsymbol +
".");
1235 std::set<std::string>& operationsR,
bool commonRWSignature,
1239 const auto gn = GetPointerS<gimple_node>(
GET_NODE(stmt));
1241 const auto fd = GetPointerS<function_decl>(
GET_CONST_NODE(gn->scpe));
1247 const auto sl = GetPointerS<statement_list>(
GET_NODE(fd->body));
1248 const auto curr_bb =
sl->list_of_bloc.at(gn->bb_index);
1249 const auto ret_call =
GET_NODE(stmt)->get_kind() == gimple_assign_K &&
1250 GET_NODE(GetPointerS<gimple_assign>(
GET_NODE(stmt))->op1)->get_kind() == call_expr_K;
1251 const auto ref_call =
GET_NODE(stmt)->get_kind() == gimple_call_K;
1252 if(ret_call || ref_call)
1261 const auto ga = GetPointerS<const gimple_assign>(
GET_CONST_NODE(stmt));
1263 const auto ce = GetPointerS<const call_expr>(
GET_CONST_NODE(ga->op1));
1264 valid_var = ce->args.size() == 2;
1268 valid_ptr = ce->args.at(1);
1272 THROW_ASSERT(ce->args.size() == 1,
"unexpected condition");
1277 const auto gc = GetPointerS<const gimple_call>(
GET_CONST_NODE(stmt));
1278 valid_var = gc->args.size() == 3;
1279 auto first_arg = gc->args.at(0);
1281 data_ptr = first_arg;
1283 THROW_ASSERT(data_obj != first_arg,
"unexpected condition");
1287 valid_ptr = gc->args.at(2);
1291 THROW_ASSERT(gc->args.size() == 2,
"unexpected condition");
1297 const auto vdef = gn->vdef;
1304 const auto fdecl_node = [&]() {
1305 const auto interface_fname =
ENCODE_FDNAME(arg_name, valid_var ?
"_ReadAsync" :
"_Read",
"Channel");
1306 operationsR.insert(interface_fname);
1307 std::vector<tree_nodeConstRef> argsT;
1308 argsT.push_back(sel_type);
1312 std::vector<tree_nodeRef>
args;
1316 curr_bb->PushBefore(new_call, stmt,
AppM);
1320 const auto retval = GetPointerS<const gimple_assign>(
GET_CONST_NODE(new_call))->op0;
1321 auto ga_mask = tree_man->
CreateNopExpr(retval, out_type,
nullptr,
nullptr, fd->index);
1322 curr_bb->PushBefore(ga_mask, stmt,
AppM);
1324 auto data_mask = GetPointerS<const gimple_assign>(
GET_CONST_NODE(ga_mask))->op0;
1329 curr_bb->PushBefore(ga_mask, stmt,
AppM);
1331 data_mask = GetPointerS<const gimple_assign>(
GET_CONST_NODE(ga_mask))->op0;
1339 last_stmt = ga_mask;
1351 GetPointerS<gimple_assign>(
GET_NODE(ga_store))->SetVdef(newSSAVdef);
1352 for(
const auto& vuse : GetPointerS<gimple_assign>(
GET_NODE(stmt))->vuses)
1354 if(GetPointerS<gimple_node>(
GET_NODE(ga_store))->AddVuse(vuse))
1356 GetPointerS<ssa_name>(
GET_NODE(vuse))->AddUseStmt(ga_store);
1360 auto vdef_ssa = GetPointerS<ssa_name>(
GET_NODE(vdef));
1361 for(
const auto& usingStmt : vdef_ssa->CGetUseStmts())
1363 if(GetPointerS<gimple_node>(
GET_NODE(usingStmt.first))->AddVuse(newSSAVdef))
1365 GetPointerS<ssa_name>(
GET_NODE(newSSAVdef))->AddUseStmt(usingStmt.first);
1368 curr_bb->PushBefore(ga_store, stmt,
AppM);
1372 curr_bb->Replace(stmt, ga_store,
true,
AppM);
1376 last_stmt = ga_store;
1384 const auto ga_vshift =
1386 curr_bb->PushBefore(ga_vshift, stmt,
AppM);
1388 const auto v_shift = GetPointerS<const gimple_assign>(
GET_CONST_NODE(ga_vshift))->op0;
1390 const auto valid_type = tree_man->
GetPointerType(valid_ptd_type);
1391 const auto ga_valid = tree_man->
CreateNopExpr(v_shift, valid_ptd_type,
nullptr,
nullptr, fd->index);
1392 curr_bb->PushBefore(ga_valid, stmt,
AppM);
1394 const auto valid_ref = GetPointerS<const gimple_assign>(
GET_CONST_NODE(ga_valid))->op0;
1397 const auto ga_valid_store =
1399 curr_bb->Replace(stmt, ga_valid_store,
true,
AppM);
1402 auto ssaDef = GetPointerS<gimple_assign>(
GET_NODE(last_stmt))->vdef;
1403 if(GetPointerS<gimple_node>(
GET_NODE(ga_valid_store))->AddVuse(ssaDef))
1405 GetPointerS<ssa_name>(
GET_NODE(ssaDef))->AddUseStmt(ga_valid_store);
1412 curr_bb->RemoveStmt(stmt,
AppM);
1418 const auto ga = GetPointerS<gimple_assign>(
GET_NODE(stmt));
1425 const auto fdecl_node = [&]() {
1426 const auto interface_fname =
ENCODE_FDNAME(arg_name,
"_Read",
"");
1427 operationsR.insert(interface_fname);
1428 std::vector<tree_nodeConstRef> argsT;
1429 if(commonRWSignature)
1431 argsT.push_back(boolean_type);
1432 argsT.push_back(bit_size_type);
1433 argsT.push_back(interface_datatype);
1439 std::vector<tree_nodeRef>
args;
1440 if(commonRWSignature)
1443 const auto size_value =
1447 args.push_back(sel_value);
1448 args.push_back(size_value);
1449 args.push_back(data_value);
1453 const auto mr = GetPointerS<const mem_ref>(
GET_CONST_NODE(ga->op1));
1454 args.push_back(mr->op0);
1464 GetPointer<HLS_manager>(
AppM)->design_interface_io[fname][ga->bb_index][arg_name].push_back(
1471 const auto tmp_type =
1473 const auto tmp_ssa = tree_man->
create_ssa_name(
nullptr, tmp_type,
nullptr,
nullptr);
1475 curr_bb->Replace(stmt, gc,
true,
AppM);
1477 is_real ? view_convert_expr_K : nop_expr_K);
1479 curr_bb->PushAfter(cast, gc,
AppM);
1480 GetPointer<HLS_manager>(
AppM)->design_interface_io[fname][curr_bb->number][arg_name].push_back(
1491 std::set<std::string>& operationsW,
bool commonRWSignature,
1495 const auto gn = GetPointerS<gimple_node>(
GET_NODE(stmt));
1497 const auto fd = GetPointerS<function_decl>(
GET_CONST_NODE(gn->scpe));
1503 const auto sl = GetPointerS<statement_list>(
GET_NODE(fd->body));
1504 const auto curr_bb =
sl->list_of_bloc.at(gn->bb_index);
1505 const auto ret_call =
GET_NODE(stmt)->get_kind() == gimple_assign_K &&
1506 GET_NODE(GetPointerS<gimple_assign>(
GET_NODE(stmt))->op1)->get_kind() == call_expr_K;
1507 const auto ref_call =
GET_NODE(stmt)->get_kind() == gimple_call_K;
1508 if(ret_call || ref_call)
1514 bool isAStruct =
false;
1517 const auto ga = GetPointerS<const gimple_assign>(
GET_CONST_NODE(stmt));
1518 const auto ce = GetPointerS<const call_expr>(
GET_CONST_NODE(ga->op1));
1519 THROW_ASSERT(ce->args.size() == 2,
"unexpected condition");
1520 data_obj = ce->args.at(1);
1523 data_ptr = data_obj;
1525 THROW_ASSERT(data_obj != data_ptr,
"unexpected condition");
1533 const auto gc = GetPointerS<const gimple_call>(
GET_CONST_NODE(stmt));
1534 THROW_ASSERT(gc->args.size() == 2,
"unexpected condition");
1535 data_obj = gc->args.at(1);
1538 data_ptr = data_obj;
1540 THROW_ASSERT(data_obj != data_ptr,
"unexpected condition");
1552 const auto fdecl_node = [&]() {
1553 const auto interface_fname =
ENCODE_FDNAME(arg_name, valid_var ?
"_WriteAsync" :
"_Write",
"Channel");
1554 operationsW.insert(interface_fname);
1555 std::vector<tree_nodeConstRef> argsT;
1556 argsT.push_back(sel_type);
1557 argsT.push_back(data_type);
1564 const auto ga_ptr = tree_man->
CreateNopExpr(data_ptr, out_ptr_type,
nullptr,
nullptr, fd->
index);
1565 curr_bb->PushBefore(ga_ptr, stmt,
AppM);
1567 const auto out_data_ptr = GetPointerS<const gimple_assign>(
GET_CONST_NODE(ga_ptr))->op0;
1570 const auto ga_load =
1572 curr_bb->Replace(stmt, ga_load,
true,
AppM);
1574 data_obj = GetPointerS<const gimple_assign>(
GET_CONST_NODE(ga_load))->op0;
1581 curr_bb->PushBefore(ga_vc, stmt,
AppM);
1583 data_obj = GetPointerS<const gimple_assign>(
GET_CONST_NODE(ga_vc))->op0;
1586 std::vector<tree_nodeRef>
args;
1588 args.push_back(data_obj);
1591 const auto ga_stmt = GetPointerS<const gimple_assign>(
GET_CONST_NODE(stmt));
1596 curr_bb->PushAfter(ga_call, lastStmt,
AppM);
1600 curr_bb->Replace(stmt, ga_call,
true,
AppM);
1609 curr_bb->PushAfter(gc, lastStmt,
AppM);
1613 curr_bb->Replace(stmt, gc,
true,
AppM);
1621 const auto ga = GetPointerS<gimple_assign>(
GET_NODE(stmt));
1624 auto value_node = ga->op1;
1633 value_node = tree_man->
create_ssa_name(
nullptr, int_type,
nullptr,
nullptr);
1638 nop = tree_man->
CreateNopExpr(value_node, interface_datatype,
nullptr,
nullptr,
1640 value_node = GetPointerS<const gimple_assign>(
GET_CONST_NODE(nop))->op0;
1642 curr_bb->PushBefore(nop, stmt,
AppM);
1649 const auto fdecl_node = [&]() {
1650 const auto interface_fname =
ENCODE_FDNAME(arg_name,
"_Write",
"");
1651 operationsW.insert(interface_fname);
1652 std::vector<tree_nodeConstRef> argsT;
1653 if(commonRWSignature)
1655 argsT.push_back(boolean_type);
1657 argsT.push_back(bit_size_type);
1658 argsT.push_back(interface_datatype);
1665 std::vector<tree_nodeRef>
args;
1666 if(commonRWSignature)
1671 args.push_back(value_node);
1672 const auto mr = GetPointerS<const mem_ref>(
GET_CONST_NODE(ga->op0));
1673 args.push_back(mr->op0);
1676 curr_bb->Replace(stmt, gc,
true,
AppM);
1677 GetPointer<HLS_manager>(
AppM)->design_interface_io[fname][curr_bb->number][arg_name].push_back(
1686 FunctionArchitectureRef func_arch,
bool IO_port)
const 1688 if(operations.empty())
1692 const auto& parm_attrs = func_arch->parms.at(info.
arg_id);
1693 const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
1694 const std::string ResourceName =
ENCODE_FDNAME(bundle_name,
"_Read_", info.
name);
1695 const auto HLSMgr = GetPointer<HLS_manager>(
AppM);
1696 const auto HLS_D = HLSMgr->get_HLS_device();
1697 const auto TechMan = HLS_D->get_technology_manager();
1706 const auto interface_top = CM->
get_circ();
1708 GetPointerS<module>(interface_top)->set_description(
"Interface module for function: " + ResourceName);
1710 GetPointerS<module>(interface_top)->set_authors(
"Component automatically generated by bambu");
1712 GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(1
U);
1713 const auto if_name = info.
name ==
"ovalid" ?
"none" : info.
name;
1714 const auto is_unbounded = if_name ==
"valid" || if_name ==
"handshake" || if_name ==
"fifo" || if_name ==
"axis";
1716 const auto address_bitsize = HLSMgr->get_address_bitsize();
1719 const auto out_bitsize = if_name ==
"fifo" ? (info.
bitwidth + 1
U) : info.
bitwidth;
1729 const auto addrPort = CM->
add_port(
"in1", port_o::IN, interface_top, addrType);
1730 GetPointerS<port_o>(addrPort)->set_is_addr_bus(
true);
1731 GetPointerS<port_o>(addrPort)->set_port_alignment(info.
alignment);
1732 CM->
add_port(
"out1", port_o::OUT, interface_top, outType);
1734 std::string port_data_name =
"_" + info.
arg_id;
1736 if(if_name ==
"axis")
1738 port_data_name =
"_s_axis_" + info.
arg_id +
"_TDATA";
1739 port_if = port_o::port_interface::PI_S_AXIS_TDATA;
1741 else if(if_name ==
"fifo")
1743 port_data_name +=
"_dout";
1744 port_if = port_o::port_interface::PI_FDOUT;
1748 port_data_name +=
"_i";
1750 const auto inPort = CM->
add_port(port_data_name, port_o::IN, interface_top, dataType);
1751 GetPointerS<port_o>(inPort)->set_port_interface(port_if);
1752 if(if_name ==
"acknowledge" || if_name ==
"handshake")
1754 const auto inPort_o_ack =
1755 CM->
add_port(
"_" + info.
arg_id + (IO_port ?
"_i" :
"") +
"_ack", port_o::OUT, interface_top, bool_type);
1756 GetPointerS<port_o>(inPort_o_ack)->set_port_interface(port_o::port_interface::PI_RACK);
1758 if(if_name ==
"valid" || if_name ==
"handshake")
1760 const auto inPort_o_vld =
1761 CM->
add_port(
"_" + info.
arg_id + (IO_port ?
"_i" :
"") +
"_vld", port_o::IN, interface_top, bool_type);
1762 GetPointerS<port_o>(inPort_o_vld)->set_port_interface(port_o::port_interface::PI_RVALID);
1764 if(if_name ==
"fifo")
1766 const auto inPort_empty_n = CM->
add_port(
"_" + info.
arg_id +
"_empty_n", port_o::IN, interface_top, bool_type);
1767 GetPointerS<port_o>(inPort_empty_n)->set_port_interface(port_o::port_interface::PI_EMPTY_N);
1768 const auto inPort_read = CM->
add_port(
"_" + info.
arg_id +
"_read", port_o::OUT, interface_top, bool_type);
1769 GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_READ);
1771 if(if_name ==
"axis")
1773 const auto inPort_empty_n =
1774 CM->
add_port(
"_s_axis_" + info.
arg_id +
"_TVALID", port_o::IN, interface_top, bool_type);
1775 GetPointerS<port_o>(inPort_empty_n)->set_port_interface(port_o::port_interface::PI_S_AXIS_TVALID);
1776 const auto inPort_read =
1777 CM->
add_port(
"_s_axis_" + info.
arg_id +
"_TREADY", port_o::OUT, interface_top, bool_type);
1778 GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_S_AXIS_TREADY);
1783 "Read_" + if_name +
"ModuleGenerator");
1785 for(
const auto& fdName : operations)
1789 auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName,
INTERFACE_LIBRARY));
1791 fu->area_m->set_area_value(0);
1794 fu->logical_type = functional_unit::COMBINATIONAL;
1797 for(
const auto& fdName : operations)
1799 const auto op = GetPointer<operation>(fu->get_operation(fdName));
1801 if(if_name ==
"fifo")
1803 op->bounded = fdName.find(
"Async") != std::string::npos;
1804 const auto exec_time =
1805 (!op->bounded ? HLS_D->get_technology_manager()->CGetSetupHoldTime() : 0.0) +
EPSILON;
1806 const auto cycles = op->bounded ? 1
U : 0
U;
1807 op->time_m->set_execution_time(exec_time, cycles);
1811 op->bounded = !is_unbounded;
1812 const auto exec_time =
1813 (is_unbounded ? HLS_D->get_technology_manager()->CGetSetupHoldTime() : 0.0) +
EPSILON;
1814 const auto cycles = if_name ==
"acknowledge" ? 1
U : 0
U;
1815 op->time_m->set_execution_time(exec_time, cycles);
1817 op->time_m->set_synthesis_dependent(
true);
1819 HLSMgr->global_resource_constraints[std::make_pair(ResourceName,
INTERFACE_LIBRARY)] = std::make_pair(1
U, 1
U);
1825 FunctionArchitectureRef func_arch,
bool IO_port)
const 1827 if(operations.empty())
1831 const auto& parm_attrs = func_arch->parms.at(info.
arg_id);
1832 const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
1833 const std::string ResourceName =
ENCODE_FDNAME(bundle_name,
"_Write_", info.
name);
1834 const auto HLSMgr = GetPointer<HLS_manager>(
AppM);
1835 const auto HLS_D = HLSMgr->get_HLS_device();
1836 const auto TechMan = HLS_D->get_technology_manager();
1845 const auto interface_top = CM->
get_circ();
1847 GetPointerS<module>(interface_top)->set_description(
"Interface module for function: " + ResourceName);
1849 GetPointerS<module>(interface_top)->set_authors(
"Component automatically generated by bambu");
1851 GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(1
U);
1852 const auto if_name = info.
name ==
"ovalid" ?
"valid" : info.
name;
1853 const auto is_unbounded =
1854 if_name ==
"acknowledge" || if_name ==
"handshake" || if_name ==
"fifo" || if_name ==
"axis";
1856 const auto address_bitsize = HLSMgr->get_address_bitsize();
1859 const auto nbitDataSize = 64u -
static_cast<unsigned>(__builtin_clzll(info.
bitwidth));
1871 CM->
add_port(
"in1", port_o::IN, interface_top, rwsize);
1872 CM->
add_port(
"in2", port_o::IN, interface_top, rwtype);
1873 const auto addrPort = CM->
add_port(
"in3", port_o::IN, interface_top, addrType);
1874 GetPointerS<port_o>(addrPort)->set_is_addr_bus(
true);
1875 GetPointerS<port_o>(addrPort)->set_port_alignment(info.
alignment);
1876 if(if_name ==
"fifo" || if_name ==
"axis")
1878 CM->
add_port(
"out1", port_o::OUT, interface_top, bool_type);
1880 std::string port_data_name =
"_" + info.
arg_id;
1882 if(if_name ==
"axis")
1884 port_data_name =
"_m_axis_" + info.
arg_id +
"_TDATA";
1885 port_if = port_o::port_interface::PI_M_AXIS_TDATA;
1887 else if(if_name ==
"fifo")
1889 port_data_name +=
"_din";
1890 port_if = port_o::port_interface::PI_FDIN;
1894 port_data_name +=
"_o";
1896 const auto inPort_o = CM->
add_port(port_data_name, port_o::OUT, interface_top, dataType);
1897 GetPointerS<port_o>(inPort_o)->set_port_interface(port_if);
1898 if(if_name ==
"acknowledge" || if_name ==
"handshake")
1900 const auto inPort_o_ack =
1901 CM->
add_port(
"_" + info.
arg_id + (IO_port ?
"_o" :
"") +
"_ack", port_o::IN, interface_top, bool_type);
1902 GetPointerS<port_o>(inPort_o_ack)->set_port_interface(port_o::port_interface::PI_WACK);
1904 if(if_name ==
"valid" || if_name ==
"handshake")
1906 const auto inPort_o_vld =
1907 CM->
add_port(
"_" + info.
arg_id + (IO_port ?
"_o" :
"") +
"_vld", port_o::OUT, interface_top, bool_type);
1908 GetPointerS<port_o>(inPort_o_vld)->set_port_interface(port_o::port_interface::PI_WVALID);
1910 if(if_name ==
"fifo")
1912 const auto inPort_full_n = CM->
add_port(
"_" + info.
arg_id +
"_full_n", port_o::IN, interface_top, bool_type);
1913 GetPointerS<port_o>(inPort_full_n)->set_port_interface(port_o::port_interface::PI_FULL_N);
1914 const auto inPort_read = CM->
add_port(
"_" + info.
arg_id +
"_write", port_o::OUT, interface_top, bool_type);
1915 GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_WRITE);
1917 if(if_name ==
"axis")
1919 const auto inPort_full_n =
1920 CM->
add_port(
"_m_axis_" + info.
arg_id +
"_TREADY", port_o::IN, interface_top, bool_type);
1921 GetPointerS<port_o>(inPort_full_n)->set_port_interface(port_o::port_interface::PI_M_AXIS_TREADY);
1922 const auto inPort_read =
1923 CM->
add_port(
"_m_axis_" + info.
arg_id +
"_TVALID", port_o::OUT, interface_top, bool_type);
1924 GetPointerS<port_o>(inPort_read)->set_port_interface(port_o::port_interface::PI_M_AXIS_TVALID);
1932 "Write_" + if_name +
"ModuleGenerator");
1937 "Write_" + if_name +
"ModuleGenerator");
1940 for(
const auto& fdName : operations)
1944 auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName,
INTERFACE_LIBRARY));
1946 fu->area_m->set_area_value(0);
1949 fu->logical_type = functional_unit::COMBINATIONAL;
1952 const auto& iface_attrs = func_arch->ifaces.at(bundle_name);
1953 const auto is_registered = iface_attrs.find(FunctionArchitecture::iface_register) != iface_attrs.end();
1954 for(
const auto& fdName : operations)
1956 const auto op_bounded = fdName.find(
"Async") != std::string::npos || !is_unbounded;
1957 const auto exec_time = (op_bounded ? 0.0 : HLS_D->get_technology_manager()->CGetSetupHoldTime()) +
EPSILON;
1958 const auto cycles = op_bounded ? (1
U + is_registered) : 0
U;
1960 const auto op = GetPointerS<operation>(fu->get_operation(fdName));
1962 op->bounded = op_bounded;
1963 op->time_m->set_execution_time(exec_time, cycles);
1964 if(op_bounded && is_registered)
1966 op->time_m->set_stage_period(HLS_D->get_technology_manager()->CGetSetupHoldTime() +
EPSILON);
1967 op->time_m->set_initiation_time(ControlStep(1
U));
1969 op->time_m->set_synthesis_dependent(
true);
1971 HLSMgr->global_resource_constraints[std::make_pair(ResourceName,
INTERFACE_LIBRARY)] = std::make_pair(1
U, 1
U);
1977 const std::set<std::string>& operationsW,
const interface_info& info,
1978 FunctionArchitectureRef func_arch)
const 1980 const auto n_channels =
parameters->getOption<
unsigned int>(OPT_channels_number);
1981 const auto isDP = n_channels == 2;
1982 const auto n_resources = isDP ? 2
U : 1
U;
1983 const auto read_write_string = (isDP ? std::string(
"ReadWriteDP_") : std::string(
"ReadWrite_"));
1984 const auto HLSMgr = GetPointerS<HLS_manager>(
AppM);
1986 "Missing parameter '" + info.
arg_id +
"' from function architecute.");
1987 const auto& parm_attrs = func_arch->parms.at(info.
arg_id);
1988 const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
1989 const auto ResourceName =
ENCODE_FDNAME(bundle_name,
"",
"");
1990 const auto HLS_D = HLSMgr->get_HLS_device();
1991 const auto TechMan = HLS_D->get_technology_manager();
1997 " (multi: " +
STR(n_resources) +
")");
2001 THROW_ASSERT(parm_attrs.find(FunctionArchitecture::parm_elem_count) != parm_attrs.end(),
2002 "Missing parameter element count for parameter '" + info.
arg_id +
"'.");
2003 const auto arraySize = std::stoull(parm_attrs.at(FunctionArchitecture::parm_elem_count));
2007 GetPointerS<module>(interface_top)->set_description(
"Interface module for function: " + ResourceName);
2009 GetPointerS<module>(interface_top)->set_authors(
"Component automatically generated by bambu");
2011 GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(n_resources);
2012 const auto address_bitsize = HLSMgr->get_address_bitsize();
2013 const auto nbit = 64u -
static_cast<unsigned long long>(__builtin_clzll(arraySize - 1
U));
2014 const auto nbitDataSize = 64u -
static_cast<unsigned long long>(__builtin_clzll(info.
bitwidth));
2031 const auto dataPort = CM->
add_port_vector(
"in3", port_o::IN, n_resources, interface_top,
2033 const auto addrPort = CM->
add_port_vector(
"in4", port_o::IN, n_resources, interface_top, addrType);
2034 GetPointerS<port_o>(addrPort)->set_is_addr_bus(
true);
2035 GetPointerS<port_o>(addrPort)->set_port_alignment(info.
alignment);
2037 CM->
add_port_vector(
"out1", port_o::OUT, n_resources, interface_top, rwtype);
2039 const auto inPort_address =
2040 CM->
add_port(
"_" + bundle_name +
"_address0", port_o::OUT, interface_top, address_interface_datatype);
2041 GetPointerS<port_o>(inPort_address)->set_port_interface(port_o::port_interface::PI_ADDRESS);
2044 const auto inPort_address1 =
2045 CM->
add_port(
"_" + bundle_name +
"_address1", port_o::OUT, interface_top, address_interface_datatype);
2046 GetPointerS<port_o>(inPort_address1)->set_port_interface(port_o::port_interface::PI_ADDRESS);
2049 const auto inPort_ce = CM->
add_port(
"_" + bundle_name +
"_ce0", port_o::OUT, interface_top, bool_type);
2050 GetPointerS<port_o>(inPort_ce)->set_port_interface(port_o::port_interface::PI_CHIPENABLE);
2053 const auto inPort_ce1 = CM->
add_port(
"_" + bundle_name +
"_ce1", port_o::OUT, interface_top, bool_type);
2054 GetPointerS<port_o>(inPort_ce1)->set_port_interface(port_o::port_interface::PI_CHIPENABLE);
2057 if(!operationsW.empty())
2059 const auto inPort_we = CM->
add_port(
"_" + bundle_name +
"_we0", port_o::OUT, interface_top, bool_type);
2060 GetPointerS<port_o>(inPort_we)->set_port_interface(port_o::port_interface::PI_WRITEENABLE);
2063 const auto inPort_we1 = CM->
add_port(
"_" + bundle_name +
"_we1", port_o::OUT, interface_top, bool_type);
2064 GetPointerS<port_o>(inPort_we1)->set_port_interface(port_o::port_interface::PI_WRITEENABLE);
2067 if(!operationsR.empty())
2069 const auto inPort_din = CM->
add_port(
"_" + bundle_name +
"_q0", port_o::IN, interface_top, dataType);
2070 GetPointerS<port_o>(inPort_din)->set_port_interface(port_o::port_interface::PI_DIN);
2073 const auto inPort_din1 = CM->
add_port(
"_" + bundle_name +
"_q1", port_o::IN, interface_top, dataType);
2074 GetPointerS<port_o>(inPort_din1)->set_port_interface(port_o::port_interface::PI_DIN);
2077 if(!operationsW.empty())
2079 const auto inPort_dout = CM->
add_port(
"_" + bundle_name +
"_d0", port_o::OUT, interface_top, dataType);
2080 GetPointerS<port_o>(inPort_dout)->set_port_interface(port_o::port_interface::PI_DOUT);
2083 const auto inPort_dout1 = CM->
add_port(
"_" + bundle_name +
"_d1", port_o::OUT, interface_top, dataType);
2084 GetPointerS<port_o>(inPort_dout1)->set_port_interface(port_o::port_interface::PI_DOUT);
2090 read_write_string + info.
name +
"ModuleGenerator");
2092 const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName,
INTERFACE_LIBRARY));
2094 fu->area_m->set_area_value(0);
2095 HLSMgr->global_resource_constraints[std::make_pair(ResourceName,
INTERFACE_LIBRARY)] =
2096 std::make_pair(n_resources, n_resources);
2099 for(
const auto& fdName : operationsR)
2103 for(
const auto& fdName : operationsW)
2107 const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName,
INTERFACE_LIBRARY));
2109 const auto bram_fu = GetPointerS<functional_unit>(bram_f_unit);
2110 const auto load_op_node = bram_fu->get_operation(
"LOAD");
2111 const auto load_op = GetPointerS<operation>(load_op_node);
2112 const auto load_delay = load_op->time_m->get_execution_time();
2113 const auto load_cycles = load_op->time_m->get_cycles();
2114 const auto load_ii = load_op->time_m->get_initiation_time();
2115 const auto load_sp = load_op->time_m->get_stage_period();
2116 for(
const auto& fdName : operationsR)
2118 const auto op = GetPointerS<operation>(fu->get_operation(fdName));
2121 op->time_m->set_execution_time(load_delay, load_cycles);
2122 op->time_m->set_initiation_time(load_ii);
2123 op->time_m->set_stage_period(load_sp);
2124 op->time_m->set_synthesis_dependent(
true);
2126 const auto store_op_node = bram_fu->get_operation(
"STORE");
2127 const auto store_op = GetPointerS<operation>(store_op_node);
2128 const auto store_delay = store_op->time_m->get_execution_time();
2129 const auto store_cycles = store_op->time_m->get_cycles();
2130 const auto store_ii = store_op->time_m->get_initiation_time();
2131 const auto store_sp = store_op->time_m->get_stage_period();
2132 for(
const auto& fdName : operationsW)
2134 const auto op = GetPointerS<operation>(fu->get_operation(fdName));
2137 op->time_m->set_execution_time(store_delay, store_cycles);
2138 op->time_m->set_initiation_time(store_ii);
2139 op->time_m->set_stage_period(store_sp);
2140 op->time_m->set_synthesis_dependent(
true);
2145 const std::set<std::string>& operationsW,
const interface_info& info,
2146 FunctionArchitectureRef func_arch)
const 2149 const auto HLSMgr = GetPointerS<HLS_manager>(
AppM);
2151 "Missing parameter '" + info.
arg_id +
"' from function architecute.");
2152 const auto& parm_attrs = func_arch->parms.at(info.
arg_id);
2153 const auto& bundle_name = parm_attrs.at(FunctionArchitecture::parm_bundle);
2154 const auto ResourceName =
ENCODE_FDNAME(bundle_name,
"",
"");
2155 const auto HLS_D = HLSMgr->get_HLS_device();
2156 const auto TechMan = HLS_D->get_technology_manager();
2163 const auto& iface_attrs = func_arch->ifaces.at(bundle_name);
2167 const auto interface_top = CM->
get_circ();
2169 GetPointerS<module>(interface_top)->set_description(
"Interface module for function: " + ResourceName);
2171 GetPointerS<module>(interface_top)->set_authors(
"Component automatically generated by bambu");
2173 GetPointerS<module>(interface_top)->set_multi_unit_multiplicity(1
U);
2175 const auto address_bitsize = HLSMgr->get_address_bitsize();
2176 const auto nbitDataSize = 64u -
static_cast<unsigned>(__builtin_clzll(info.
bitwidth));
2177 const auto backEndBitsize =
2178 iface_attrs.find(FunctionArchitecture::iface_cache_bus_size) != iface_attrs.end() ?
2179 std::stoull(iface_attrs.find(FunctionArchitecture::iface_cache_bus_size)->second) :
2207 CM->
add_port(
"in1", port_o::IN, interface_top, size1);
2209 CM->
add_port(
"in2", port_o::IN, interface_top, rwsize);
2211 CM->
add_port(
"in3", port_o::IN, interface_top, rwtypeIn);
2213 const auto addrPort = CM->
add_port(
"in4", port_o::IN, interface_top, address_interface_datatype);
2214 GetPointerS<port_o>(addrPort)->set_is_addr_bus(
true);
2216 const auto awready = CM->
add_port(
"_m_axi_" + bundle_name +
"_awready", port_o::IN, interface_top, bool_type);
2217 GetPointerS<port_o>(awready)->set_port_interface(port_o::port_interface::M_AXI_AWREADY);
2219 const auto wready = CM->
add_port(
"_m_axi_" + bundle_name +
"_wready", port_o::IN, interface_top, bool_type);
2220 GetPointerS<port_o>(wready)->set_port_interface(port_o::port_interface::M_AXI_WREADY);
2222 const auto bid = CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_bid", port_o::IN, 1, interface_top, idType);
2223 GetPointerS<port_o>(bid)->set_port_interface(port_o::port_interface::M_AXI_BID);
2225 const auto bresp = CM->
add_port(
"_m_axi_" + bundle_name +
"_bresp", port_o::IN, interface_top, respType);
2226 GetPointerS<port_o>(bresp)->set_port_interface(port_o::port_interface::M_AXI_BRESP);
2229 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_buser", port_o::IN, 1, interface_top, userType);
2230 GetPointerS<port_o>(buser)->set_port_interface(port_o::port_interface::M_AXI_BUSER);
2232 const auto bvalid = CM->
add_port(
"_m_axi_" + bundle_name +
"_bvalid", port_o::IN, interface_top, bool_type);
2233 GetPointerS<port_o>(bvalid)->set_port_interface(port_o::port_interface::M_AXI_BVALID);
2235 const auto arready = CM->
add_port(
"_m_axi_" + bundle_name +
"_arready", port_o::IN, interface_top, bool_type);
2236 GetPointerS<port_o>(arready)->set_port_interface(port_o::port_interface::M_AXI_ARREADY);
2238 const auto rid = CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_rid", port_o::IN, 1, interface_top, idType);
2239 GetPointerS<port_o>(rid)->set_port_interface(port_o::port_interface::M_AXI_RID);
2241 const auto rdata = CM->
add_port(
"_m_axi_" + bundle_name +
"_rdata", port_o::IN, interface_top, rwtypeOut);
2242 GetPointerS<port_o>(rdata)->set_port_interface(port_o::port_interface::M_AXI_RDATA);
2244 const auto rresp = CM->
add_port(
"_m_axi_" + bundle_name +
"_rresp", port_o::IN, interface_top, respType);
2245 GetPointerS<port_o>(rresp)->set_port_interface(port_o::port_interface::M_AXI_RRESP);
2247 const auto rlast = CM->
add_port(
"_m_axi_" + bundle_name +
"_rlast", port_o::IN, interface_top, bool_type);
2248 GetPointerS<port_o>(rlast)->set_port_interface(port_o::port_interface::M_AXI_RLAST);
2251 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_ruser", port_o::IN, 1, interface_top, userType);
2252 GetPointerS<port_o>(ruser)->set_port_interface(port_o::port_interface::M_AXI_RUSER);
2254 const auto rvalid = CM->
add_port(
"_m_axi_" + bundle_name +
"_rvalid", port_o::IN, interface_top, bool_type);
2255 GetPointerS<port_o>(rvalid)->set_port_interface(port_o::port_interface::M_AXI_RVALID);
2258 CM->
add_port(
"out1", port_o::OUT, interface_top, rwtypeIn);
2260 const auto awid = CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_awid", port_o::OUT, 1, interface_top, idType);
2261 GetPointerS<port_o>(awid)->set_port_interface(port_o::port_interface::M_AXI_AWID);
2264 CM->
add_port(
"_m_axi_" + bundle_name +
"_awaddr", port_o::OUT, interface_top, address_interface_datatype);
2265 GetPointerS<port_o>(awaddr)->set_port_interface(port_o::port_interface::M_AXI_AWADDR);
2267 const auto awlen = CM->
add_port(
"_m_axi_" + bundle_name +
"_awlen", port_o::OUT, interface_top, lenType);
2268 GetPointerS<port_o>(awlen)->set_port_interface(port_o::port_interface::M_AXI_AWLEN);
2270 const auto awsize = CM->
add_port(
"_m_axi_" + bundle_name +
"_awsize", port_o::OUT, interface_top, sizeType);
2271 GetPointerS<port_o>(awsize)->set_port_interface(port_o::port_interface::M_AXI_AWSIZE);
2273 const auto awburst = CM->
add_port(
"_m_axi_" + bundle_name +
"_awburst", port_o::OUT, interface_top, burstType);
2274 GetPointerS<port_o>(awburst)->set_port_interface(port_o::port_interface::M_AXI_AWBURST);
2277 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_awlock", port_o::OUT, 1, interface_top, lockType);
2278 GetPointerS<port_o>(awlock)->set_port_interface(port_o::port_interface::M_AXI_AWLOCK);
2280 const auto awcache = CM->
add_port(
"_m_axi_" + bundle_name +
"_awcache", port_o::OUT, interface_top, cacheType);
2281 GetPointerS<port_o>(awcache)->set_port_interface(port_o::port_interface::M_AXI_AWCACHE);
2283 const auto awprot = CM->
add_port(
"_m_axi_" + bundle_name +
"_awprot", port_o::OUT, interface_top, protType);
2284 GetPointerS<port_o>(awprot)->set_port_interface(port_o::port_interface::M_AXI_AWPROT);
2286 const auto awqos = CM->
add_port(
"_m_axi_" + bundle_name +
"_awqos", port_o::OUT, interface_top, qosType);
2287 GetPointerS<port_o>(awqos)->set_port_interface(port_o::port_interface::M_AXI_AWQOS);
2289 const auto awregion = CM->
add_port(
"_m_axi_" + bundle_name +
"_awregion", port_o::OUT, interface_top, regionType);
2290 GetPointerS<port_o>(awregion)->set_port_interface(port_o::port_interface::M_AXI_AWREGION);
2293 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_awuser", port_o::OUT, 1, interface_top, userType);
2294 GetPointerS<port_o>(awuser)->set_port_interface(port_o::port_interface::M_AXI_AWUSER);
2296 const auto awvalid = CM->
add_port(
"_m_axi_" + bundle_name +
"_awvalid", port_o::OUT, interface_top, bool_type);
2297 GetPointerS<port_o>(awvalid)->set_port_interface(port_o::port_interface::M_AXI_AWVALID);
2299 const auto wdata = CM->
add_port(
"_m_axi_" + bundle_name +
"_wdata", port_o::OUT, interface_top, rwtypeOut);
2300 GetPointerS<port_o>(wdata)->set_port_interface(port_o::port_interface::M_AXI_WDATA);
2303 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_wstrb", port_o::OUT, 1, interface_top, strbType);
2304 GetPointerS<port_o>(wstrb)->set_port_interface(port_o::port_interface::M_AXI_WSTRB);
2306 const auto wlast = CM->
add_port(
"_m_axi_" + bundle_name +
"_wlast", port_o::OUT, interface_top, bool_type);
2307 GetPointerS<port_o>(wlast)->set_port_interface(port_o::port_interface::M_AXI_WLAST);
2310 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_wuser", port_o::OUT, 1, interface_top, userType);
2311 GetPointerS<port_o>(wuser)->set_port_interface(port_o::port_interface::M_AXI_WUSER);
2313 const auto wvalid = CM->
add_port(
"_m_axi_" + bundle_name +
"_wvalid", port_o::OUT, interface_top, bool_type);
2314 GetPointerS<port_o>(wvalid)->set_port_interface(port_o::port_interface::M_AXI_WVALID);
2316 const auto bready = CM->
add_port(
"_m_axi_" + bundle_name +
"_bready", port_o::OUT, interface_top, bool_type);
2317 GetPointerS<port_o>(bready)->set_port_interface(port_o::port_interface::M_AXI_BREADY);
2319 const auto arid = CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_arid", port_o::OUT, 1, interface_top, idType);
2320 GetPointerS<port_o>(arid)->set_port_interface(port_o::port_interface::M_AXI_ARID);
2323 CM->
add_port(
"_m_axi_" + bundle_name +
"_araddr", port_o::OUT, interface_top, address_interface_datatype);
2324 GetPointerS<port_o>(araddr)->set_port_interface(port_o::port_interface::M_AXI_ARADDR);
2326 const auto arlen = CM->
add_port(
"_m_axi_" + bundle_name +
"_arlen", port_o::OUT, interface_top, lenType);
2327 GetPointerS<port_o>(arlen)->set_port_interface(port_o::port_interface::M_AXI_ARLEN);
2329 const auto arsize = CM->
add_port(
"_m_axi_" + bundle_name +
"_arsize", port_o::OUT, interface_top, sizeType);
2330 GetPointerS<port_o>(arsize)->set_port_interface(port_o::port_interface::M_AXI_ARSIZE);
2332 const auto arburst = CM->
add_port(
"_m_axi_" + bundle_name +
"_arburst", port_o::OUT, interface_top, burstType);
2333 GetPointerS<port_o>(arburst)->set_port_interface(port_o::port_interface::M_AXI_ARBURST);
2336 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_arlock", port_o::OUT, 1, interface_top, lockType);
2337 GetPointerS<port_o>(arlock)->set_port_interface(port_o::port_interface::M_AXI_ARLOCK);
2339 const auto arcache = CM->
add_port(
"_m_axi_" + bundle_name +
"_arcache", port_o::OUT, interface_top, cacheType);
2340 GetPointerS<port_o>(arcache)->set_port_interface(port_o::port_interface::M_AXI_ARCACHE);
2342 const auto arprot = CM->
add_port(
"_m_axi_" + bundle_name +
"_arprot", port_o::OUT, interface_top, protType);
2343 GetPointerS<port_o>(arprot)->set_port_interface(port_o::port_interface::M_AXI_ARPROT);
2345 const auto arqos = CM->
add_port(
"_m_axi_" + bundle_name +
"_arqos", port_o::OUT, interface_top, qosType);
2346 GetPointerS<port_o>(arqos)->set_port_interface(port_o::port_interface::M_AXI_ARQOS);
2348 const auto arregion = CM->
add_port(
"_m_axi_" + bundle_name +
"_arregion", port_o::OUT, interface_top, regionType);
2349 GetPointerS<port_o>(arregion)->set_port_interface(port_o::port_interface::M_AXI_ARREGION);
2352 CM->
add_port_vector(
"_m_axi_" + bundle_name +
"_aruser", port_o::OUT, 1, interface_top, userType);
2353 GetPointerS<port_o>(aruser)->set_port_interface(port_o::port_interface::M_AXI_ARUSER);
2355 const auto arvalid = CM->
add_port(
"_m_axi_" + bundle_name +
"_arvalid", port_o::OUT, interface_top, bool_type);
2356 GetPointerS<port_o>(arvalid)->set_port_interface(port_o::port_interface::M_AXI_ARVALID);
2358 const auto rready = CM->
add_port(
"_m_axi_" + bundle_name +
"_rready", port_o::OUT, interface_top, bool_type);
2359 GetPointerS<port_o>(rready)->set_port_interface(port_o::port_interface::M_AXI_RREADY);
2361 bool has_slave =
false;
2362 for(
auto& p : func_arch->parms)
2364 if(p.second.at(FunctionArchitecture::parm_bundle) == bundle_name)
2366 const auto& parm_offset = p.second.at(FunctionArchitecture::parm_offset);
2367 if(parm_offset ==
"slave")
2371 else if(parm_offset ==
"direct")
2373 const auto offset_port =
2374 CM->
add_port(
"_" + p.first, port_o::IN, interface_top, address_interface_datatype);
2375 GetPointerS<port_o>(offset_port)->set_port_interface(port_o::port_interface::PI_M_AXI_DIRECT);
2381 const auto s_awvalid = CM->
add_port(
"_s_axi_AXILiteS_AWVALID", port_o::IN, interface_top, bool_type);
2382 GetPointerS<port_o>(s_awvalid)->set_port_interface(port_o::port_interface::S_AXIL_AWVALID);
2383 const auto s_awaddr =
2384 CM->
add_port(
"_s_axi_AXILiteS_AWADDR", port_o::IN, interface_top, address_interface_datatype);
2385 GetPointerS<port_o>(s_awaddr)->set_port_interface(port_o::port_interface::S_AXIL_AWADDR);
2386 const auto s_wvalid = CM->
add_port(
"_s_axi_AXILiteS_WVALID", port_o::IN, interface_top, bool_type);
2387 GetPointerS<port_o>(s_wvalid)->set_port_interface(port_o::port_interface::S_AXIL_WVALID);
2388 const auto s_wdata =
2389 CM->
add_port(
"_s_axi_AXILiteS_WDATA", port_o::IN, interface_top, address_interface_datatype);
2390 GetPointerS<port_o>(s_wdata)->set_port_interface(port_o::port_interface::S_AXIL_WDATA);
2391 const auto s_wstrb = CM->
add_port(
"_s_axi_AXILiteS_WSTRB", port_o::IN, interface_top, strbType);
2392 GetPointerS<port_o>(s_wstrb)->set_port_interface(port_o::port_interface::S_AXIL_WSTRB);
2393 const auto s_arvalid = CM->
add_port(
"_s_axi_AXILiteS_ARVALID", port_o::IN, interface_top, bool_type);
2394 GetPointerS<port_o>(s_arvalid)->set_port_interface(port_o::port_interface::S_AXIL_ARVALID);
2395 const auto s_araddr =
2396 CM->
add_port(
"_s_axi_AXILiteS_ARADDR", port_o::IN, interface_top, address_interface_datatype);
2397 GetPointerS<port_o>(s_araddr)->set_port_interface(port_o::port_interface::S_AXIL_ARADDR);
2398 const auto s_rready = CM->
add_port(
"_s_axi_AXILiteS_RREADY", port_o::IN, interface_top, bool_type);
2399 GetPointerS<port_o>(s_rready)->set_port_interface(port_o::port_interface::S_AXIL_RREADY);
2400 const auto s_bready = CM->
add_port(
"_s_axi_AXILiteS_BREADY", port_o::IN, interface_top, bool_type);
2401 GetPointerS<port_o>(s_bready)->set_port_interface(port_o::port_interface::S_AXIL_BREADY);
2403 const auto s_awready = CM->
add_port(
"_s_axi_AXILiteS_AWREADY", port_o::OUT, interface_top, bool_type);
2404 GetPointerS<port_o>(s_awready)->set_port_interface(port_o::port_interface::S_AXIL_AWREADY);
2405 const auto s_wready = CM->
add_port(
"_s_axi_AXILiteS_WREADY", port_o::OUT, interface_top, bool_type);
2406 GetPointerS<port_o>(s_wready)->set_port_interface(port_o::port_interface::S_AXIL_WREADY);
2407 const auto s_arready = CM->
add_port(
"_s_axi_AXILiteS_ARREADY", port_o::OUT, interface_top, bool_type);
2408 GetPointerS<port_o>(s_arready)->set_port_interface(port_o::port_interface::S_AXIL_ARREADY);
2409 const auto s_rvalid = CM->
add_port(
"_s_axi_AXILiteS_RVALID", port_o::OUT, interface_top, bool_type);
2410 GetPointerS<port_o>(s_rvalid)->set_port_interface(port_o::port_interface::S_AXIL_RVALID);
2411 const auto s_rdata =
2412 CM->
add_port(
"_s_axi_AXILiteS_RDATA", port_o::OUT, interface_top, address_interface_datatype);
2413 GetPointerS<port_o>(s_rdata)->set_port_interface(port_o::port_interface::S_AXIL_RDATA);
2414 const auto s_rresp = CM->
add_port(
"_s_axi_AXILiteS_RRESP", port_o::OUT, interface_top, respType);
2415 GetPointerS<port_o>(s_rresp)->set_port_interface(port_o::port_interface::S_AXIL_RRESP);
2416 const auto s_bvalid = CM->
add_port(
"_s_axi_AXILiteS_BVALID", port_o::OUT, interface_top, bool_type);
2417 GetPointerS<port_o>(s_bvalid)->set_port_interface(port_o::port_interface::S_AXIL_BVALID);
2418 const auto s_bresp = CM->
add_port(
"_s_axi_AXILiteS_BRESP", port_o::OUT, interface_top, respType);
2419 GetPointerS<port_o>(s_bresp)->set_port_interface(port_o::port_interface::S_AXIL_BRESP);
2424 "ReadWrite_" + info.
name +
"ModuleGenerator");
2428 const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName,
INTERFACE_LIBRARY));
2430 fu->area_m->set_area_value(0);
2431 if(iface_attrs.find(FunctionArchitecture::iface_cache_line_count) != iface_attrs.end())
2433 const auto flushName =
ENCODE_FDNAME(bundle_name,
"_Flush_",
"m_axi");
2435 const auto op = GetPointer<operation>(fu->get_operation(flushName));
2437 op->bounded =
false;
2438 op->time_m->set_execution_time(HLS_D->get_technology_manager()->CGetSetupHoldTime() +
EPSILON, 0);
2439 op->time_m->set_synthesis_dependent(
true);
2441 HLSMgr->global_resource_constraints[std::make_pair(ResourceName,
INTERFACE_LIBRARY)] = std::make_pair(1
U, 1
U);
2445 for(
const auto& fdName : operationsR)
2449 for(
const auto& fdName : operationsW)
2455 const auto fu = GetPointerS<functional_unit>(TechMan->get_fu(ResourceName,
INTERFACE_LIBRARY));
2457 for(
const auto& fdName : operationsR)
2459 const auto op = GetPointerS<operation>(fu->get_operation(fdName));
2461 op->bounded =
false;
2462 op->time_m->set_execution_time(HLS_D->get_technology_manager()->CGetSetupHoldTime() +
EPSILON, 0);
2463 op->time_m->set_synthesis_dependent(
true);
2465 for(
const auto& fdName : operationsW)
2467 const auto op = GetPointer<operation>(fu->get_operation(fdName));
2469 op->bounded =
false;
2470 op->time_m->set_execution_time(HLS_D->get_technology_manager()->CGetSetupHoldTime() +
EPSILON, 0);
2471 op->time_m->set_synthesis_dependent(
true);
2476 const interface_info& info, FunctionArchitectureRef func_arch)
const 2478 if(info.
name ==
"none" || info.
name ==
"acknowledge" || info.
name ==
"valid" || info.
name ==
"ovalid" ||
2479 info.
name ==
"handshake" || info.
name ==
"fifo" || info.
name ==
"axis")
2481 THROW_ASSERT(!operationsR.empty() || !operationsW.empty(),
"unexpected condition");
2482 const auto IO_P = !operationsR.empty() && !operationsW.empty();
2486 else if(info.
name ==
"array")
2490 else if(info.
name ==
"m_axi")
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
static bool IsSameType(const tree_nodeConstRef &tn0, const tree_nodeConstRef &tn1)
Given two nodes tells if they have same base type (const is not considered: const double == double) ...
static size_t CGetPointerSize(const ParameterConstRef parameters)
Return the size of the pointer in bit.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
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;.
void ChasePointerInterface(tree_nodeRef ptr_var, std::list< tree_nodeRef > &writeStmt, std::list< tree_nodeRef > &readStmt, interface_info &info)
Collect information about resource area.
File containing functions and utilities to support the printing of debug messagges.
#define STR_CST_interface_parameter_keyword
interface_parameter_keyword
std::string ToString() const
Print this node as string in gimple format.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Structure representing the most relevant information about the type of a structural object...
Step successfully executed.
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
static std::vector< unsigned int > GetSortedRoots(const CallGraphManagerConstRef &CGM)
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
#define GENERATED_LICENSE
#define BB_EXIT
constant identifying the basic block node of type exit
static std::string GetString(enum port_direction)
constexpr T get_aligned_ac_bitsize(T bitsize)
Definition of the class representing a generic C application.
const structural_objectRef get_circ() const
Get a reference to circ field.
const int output_level
The output level.
static tree_nodeConstRef CGetArrayBaseType(const tree_nodeConstRef &type)
static bool IsArrayEquivType(const tree_nodeConstRef &type)
Return true if treenode is an array or it is equivalent to an array (record recursively having a sing...
std::map< enum parm_attr, std::string > parm_attrs
RelationshipType
The relationship type.
Source must be executed to satisfy target.
mathematical utility function not provided by standard libraries
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
void create_resource_Read_simple(const std::set< std::string > &operations, const interface_info &info, FunctionArchitectureRef func_arch, bool IO_port) const
std::map< enum iface_attr, std::string > iface_attrs
#define ARRAY_1D_STD_BRAM_NN_SDS
This class manages the circuit structures.
tree_nodeRef create_binary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const std::string &srcp, enum kind operation_kind) const
Function used to create a binary expression.
A simple interface to token object of the raw files.
Collect information about resource performance.
#define ARRAY_1D_STD_BRAM_SDS
unsigned long long factor
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
#define LIBRARY_STD_FU
standard library where all standard HLS resources are defined
static const std::regex signature_param_typename("((?:\+\*)+(?:<[^>]*>)?\*[\&\]*\*)")
static std::string print_function_name(const tree_managerConstRef &TM, const function_decl *fd)
Return the name of the function in a string.
Class specification of the manager of the technology library data structures.
Data structure describing a basic block at tree level.
#define INTERFACE_LIBRARY
interface library
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
~InterfaceInfer() override
Destructor.
tree_nodeRef create_unary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op, const std::string &srcp, enum kind operation_kind) const
EXPRESSION_TREE_NODES.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
tree_nodeRef CreateGimpleAssign(const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, const tree_nodeRef &op, unsigned int function_decl_nid, const std::string &srcp) const
Create gimple assignment.
static std::string GetMangledFunctionName(const function_decl *fd)
Return the mangled function name.
#define THROW_WARNING(str_expr)
helper function used to throw a warning in a standard way: though it uses PRINT_DBG_MEX, the debug level used is such that the message is always printed
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define CLOCK_PORT_NAME
standard name for ports
static void addCallPointAndExpand(CustomUnorderedSet< unsigned int > &AV, const application_managerRef AM, unsigned int caller_id, unsigned int called_id, unsigned int call_id, enum FunctionEdgeInfo::CallType call_type, int DL)
void ChasePointerInterfaceRecurse(CustomOrderedSet< unsigned > &Visited, tree_nodeRef ptr_var, std::list< tree_nodeRef > &writeStmt, std::list< tree_nodeRef > &readStmt, interface_info &info)
static bool IsArrayType(const tree_nodeConstRef &type)
Return true if treenode is an array.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
static void add_NP_functionality(structural_objectRef cir, NP_functionality::NP_functionaly_type dt, std::string functionality_description)
Add a not-parsed functionality.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
tree_nodeRef GetPointerType(const tree_nodeConstRef &ptd, unsigned long long algn=0) const
Function that creates a pointer type if it is not already present, otherwise it returns the one that ...
void set_top_info(const std::string &id, const technology_managerRef &LM, const std::string &Library="")
void update(const tree_nodeRef &tn, const std::string &_type_name, ParameterConstRef parameters)
void create_resource_m_axi(const std::set< std::string > &operationsR, const std::set< std::string > &operationsW, const interface_info &info, FunctionArchitectureRef func_arch) const
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
Class specification of the data structures used to manage technology information. ...
InterfaceInfer(const application_managerRef AppM, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
port_interface
Enum type describing if the port is associated with a specific interface type.
static structural_objectRef add_port(const std::string &id, port_o::port_direction pdir, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port.
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Classes to describe design flow graph.
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
Target must be reexecuted.
static const std::string ComputeSignature(const TechnologyFlowStep_Type technology_flow_step_type)
Compute the signature of a technology flow step.
Factory for technology flow step.
#define BB_ENTRY
constant identifying the basic block node of type entry
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
constexpr T get_aligned_bitsize(T bitsize)
#define GET_CONST_NODE(t)
void create_resource_array(const std::set< std::string > &operationsR, const std::set< std::string > &operationsW, const interface_info &info, FunctionArchitectureRef func_arch) const
Load parsed protocol interface attributes.
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
FunctionArchitecture::iface_attrs & iface_attrs
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
tree_nodeRef create_function_decl(const std::string &function_name, const tree_nodeRef &scpe, const std::vector< tree_nodeConstRef > &argsT, const tree_nodeConstRef &returnType, const std::string &srcp, bool with_body) const
create the declaration of a function without its body
tree_nodeRef GetBooleanType() const
Function that creates a boolean type if it is not already present, otherwise it returns the one that ...
This file collects some utility functions.
tree_nodeRef GetCustomIntegerType(unsigned long long prec, bool unsigned_p) const
create an integer type starting from a given prec
static std::vector< tree_nodeRef > GetCallArgs(tree_nodeRef stmt)
static tree_nodeConstRef ResolvePointerAlias(const CallGraphManagerConstRef &CGM, const tree_managerConstRef &TM, const tree_nodeConstRef &var, unsigned int fid)
static std::string get_decl_name(tree_nodeRef tn)
#define ENCODE_FDNAME(arg_name, MODE, interface_type)
FunctionArchitecture::parm_attrs & parm_attrs
interface_info(const std::string &_arg_id, const std::string &_interface_fname, bool fixed_size, FunctionArchitecture::parm_attrs &_parm_attrs, FunctionArchitecture::iface_attrs &_iface_attrs)
refcount< T > lock() const
unsigned long long bitwidth
tree_nodeRef CreateCallExpr(const tree_nodeConstRef &called_function, const std::vector< tree_nodeRef > &args, const std::string &srcp) const
Create a call_expr.
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
static tree_nodeConstRef GetBaseVariable(const tree_nodeConstRef &mem)
Retrun the base variable of a memory access.
void setReadInterface(tree_nodeRef stmt, const std::string &arg_name, std::set< std::string > &operationsR, bool commonRWSignature, tree_nodeConstRef interface_datatype, const tree_manipulationRef tree_man, const tree_managerRef TM)
This class describes all classes used to represent a structural object.
static area_infoRef factory(const ParameterConstRef &Param)
Factory method.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
static std::tuple< unsigned int, unsigned int > GetCallStmt(const CallGraphManagerConstRef &CGM, unsigned int fid)
static std::string PrintType(const tree_managerConstRef &TM, const tree_nodeConstRef &type, bool global=false, bool print_qualifiers=false, bool print_storage=false, const tree_nodeConstRef &var=nullptr, const var_pp_functorConstRef &vppf=var_pp_functorConstRef(), const std::string &prefix="", const std::string &tail="")
Print a type and its variable in case var is not zero.
DesignFlowStep_Status Exec() override
Execute this step.
This struct represent a 'return' statement.
tree_nodeRef GetVoidType() const
TYPE_OBJ.
tree_nodeRef create_gimple_call(const tree_nodeConstRef &called_function, const std::vector< tree_nodeRef > &args, unsigned int function_decl_nid, const std::string &srcp) const
GIMPLE_CALL.
TYPE distance(TYPE position_x[nAtoms], TYPE position_y[nAtoms], TYPE position_z[nAtoms], int i, int j)
void create_resource_Write_simple(const std::set< std::string > &operations, const interface_info &info, FunctionArchitectureRef func_arch, bool IO_port) const
tree_nodeRef CreateNopExpr(const tree_nodeConstRef &operand, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, unsigned int function_decl_nid) const
Create a nop_expr to perform a conversion.
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static bool IsStructType(const tree_nodeConstRef &type)
Return true if treenode is a record.
const std::string interface_fname
tree_nodeRef GetUnsignedIntegerType() const
Function that creates a unsigned integer type if it is not already present, otherwise it returns the ...
unsigned long long ac_type_bitwidth(const std::string &intType, bool &is_signed, bool &is_fixed)
It collects all the common strings covering PandA copyrights issues.
static tree_nodeConstRef CGetPointedType(const tree_nodeConstRef &pointer)
Return the pointed type of a pointer object.
void create_resource(const std::set< std::string > &operationsR, const std::set< std::string > &operationsW, const interface_info &info, FunctionArchitectureRef func_arch) const
this class is used to manage the command-line or XML options.
void forwardInterface(const tree_nodeRef &fnode, const tree_nodeRef &parm_node, const interface_info &info)
tree_nodeRef create_ssa_name(const tree_nodeConstRef &var, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, bool volatile_flag=false, bool virtual_flag=false) const
MISCELLANEOUS_OBJ_TREE_NODES.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
static std::string GetFunctionName(const tree_managerConstRef &TM, const tree_nodeConstRef &decl)
Return the name of the function.
Class implementation of the structural_manager.
Class specification of the manager for each library.
int debug_level
The debug level.
void setWriteInterface(tree_nodeRef stmt, const std::string &arg_name, std::set< std::string > &operationsW, bool commonRWSignature, tree_nodeConstRef interface_datatype, const tree_manipulationRef tree_man, const tree_managerRef TM)
#define GET_INDEX_CONST_NODE(t)
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
tree_nodeRef create_identifier_node(const std::string &strg) const
IDENTIFIER_TREE_NODE.
static structural_objectRef add_port_vector(std::string id, port_o::port_direction pdir, unsigned int n_ports, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port_vector.
tree_nodeRef create_gimple_modify_stmt(const tree_nodeRef &op0, const tree_nodeRef &op1, unsigned int function_decl_nid, const std::string &srcp) const
GIMPLE_ASSIGN.
#define GENERATED_COPYRIGHT
std::string cxa_demangle(const std::string &input)
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
static time_infoRef factory(const ParameterConstRef Param)
Class specification of the manager of the tree structures extracted from the raw file.
static unsigned long long GetArrayTotalSize(const tree_nodeConstRef &node)
Return the total number of elements of the the base type in the array.
Base class for technology flow steps.
HLS specialization of generic_device.
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
A brief description of the C++ Header File.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Implementation of the wrapper to Gcc for C sources.