76 : memory_allocation_policy(_memory_allocation_policy),
77 memory_allocation_channels_type(_memory_allocation_channels_type)
99 ret +=
"EXT_PIPELINED_BRAM";
136 const DesignFlowManagerConstRef _design_flow_manager,
139 :
HLS_step(_parameters, _HLSMgr, _design_flow_manager, _hls_flow_step_type,
140 _hls_flow_step_specialization and
142 _hls_flow_step_specialization :
158 switch(relationship_type)
184 const auto cg_man =
HLSMgr->CGetCallGraphManager();
185 func_list = cg_man->GetReachedBodyFunctions();
189 const auto function_behavior =
HLSMgr->CGetFunctionBehavior(It);
191 const auto& parm_decl_copied = function_behavior->get_parm_decl_copied();
192 for(
const auto p : parm_decl_copied)
194 HLSMgr->Rmem->add_parm_decl_copied(p);
197 const auto& parm_decl_stored = function_behavior->get_parm_decl_stored();
198 for(
const auto p : parm_decl_stored)
200 HLSMgr->Rmem->add_parm_decl_stored(p);
203 const auto& parm_decl_loaded = function_behavior->get_parm_decl_loaded();
204 for(
const auto p : parm_decl_loaded)
206 HLSMgr->Rmem->add_actual_parm_loaded(p);
214 bool use_unknown_address =
false;
215 bool has_unaligned_accesses =
false;
216 auto m64P =
parameters->getOption<std::string>(OPT_gcc_m32_mx32).find(
"-m64") != std::string::npos;
217 bool assume_aligned_access_p =
219 const auto TreeM =
HLSMgr->get_tree_manager();
222 const auto FB =
HLSMgr->CGetFunctionBehavior(It);
223 const auto BH = FB->CGetBehavioralHelper();
224 const auto& function_parameters = BH->get_parameters();
226 if(FB->get_dereference_unknown_addr())
229 "---This function uses unknown addresses deref: " + BH->get_function_name());
232 use_unknown_address |= FB->get_dereference_unknown_addr();
234 if(FB->get_unaligned_accesses())
237 "---This function performs unaligned accesses: " + BH->get_function_name());
238 if(assume_aligned_access_p)
240 THROW_ERROR(
"Option --aligned-access have been specified on a function with unaligned accesses");
244 has_unaligned_accesses |= FB->get_unaligned_accesses();
246 for(
auto const parameter : function_parameters)
248 if(
HLSMgr->Rmem->is_parm_decl_copied(parameter) && !
HLSMgr->Rmem->is_parm_decl_stored(parameter))
250 HLSMgr->Rmem->set_implicit_memcpy(
true);
255 if(
HLSMgr->Rmem->has_implicit_memcpy())
257 const auto memcpy_function = TreeM->GetFunction(
MEMCPY);
258 func_list.insert(memcpy_function->index);
261 unsigned long long maximum_bus_size = 0;
262 bool use_databus_width =
false;
263 bool has_intern_shared_data =
false;
264 bool has_misaligned_indirect_ref =
HLSMgr->Rmem->has_packed_vars();
265 bool needMemoryMappedRegisters =
false;
266 const auto call_graph_manager =
HLSMgr->CGetCallGraphManager();
267 const auto root_functions = call_graph_manager->GetRootFunctions();
269 for(
auto fun_id : func_list)
271 const auto function_behavior =
HLSMgr->CGetFunctionBehavior(fun_id);
272 const auto behavioral_helper = function_behavior->CGetBehavioralHelper();
273 const auto is_interfaced =
HLSMgr->hasToBeInterfaced(behavioral_helper->get_function_index());
274 const auto fname = behavioral_helper->GetMangledFunctionName();
275 const auto func_arch =
HLSMgr->module_arch->GetArchitecture(fname);
276 if(function_behavior->get_has_globals() &&
parameters->isOption(OPT_expose_globals) &&
277 parameters->getOption<
bool>(OPT_expose_globals))
279 has_intern_shared_data =
true;
281 const auto& function_parameters = behavioral_helper->get_parameters();
282 for(
const auto function_parameter : function_parameters)
284 const auto pname = behavioral_helper->PrintVariable(function_parameter);
285 if(func_arch && root_functions.find(fun_id) != root_functions.end())
287 THROW_ASSERT(func_arch->parms.find(pname) != func_arch->parms.end(),
288 "Parameter " + pname +
" not found in function " + fname);
289 const auto& parm_attrs = func_arch->parms.at(pname);
290 const auto& iface_attrs = func_arch->ifaces.at(parm_attrs.at(FunctionArchitecture::parm_bundle));
291 const auto iface_mode = iface_attrs.at(FunctionArchitecture::iface_mode);
292 if(iface_mode !=
"default")
297 if(
HLSMgr->Rmem->is_parm_decl_copied(function_parameter) &&
298 !
HLSMgr->Rmem->is_parm_decl_stored(function_parameter))
300 use_databus_width =
true;
301 maximum_bus_size =
std::max(maximum_bus_size, 8ull);
305 use_unknown_address =
true;
308 THROW_WARNING(
"This function uses unknown addresses: " + behavioral_helper->get_function_name());
312 if(function_behavior->has_packed_vars())
314 has_misaligned_indirect_ref =
true;
316 const auto& parm_decl_stored = function_behavior->get_parm_decl_stored();
317 for(
unsigned int p : parm_decl_stored)
324 "Analyzing function for bus size: " + behavioral_helper->get_function_name());
326 graph::vertex_iterator v, v_end;
327 const auto TM =
HLSMgr->get_tree_manager();
328 const auto fnode = TM->CGetTreeReindex(fun_id);
330 if(
HLSMgr->design_interface_io.find(fname) !=
HLSMgr->design_interface_io.end())
332 for(
const auto& bb2arg2stmtsR :
HLSMgr->design_interface_io.find(fname)->second)
334 for(
const auto& arg2stms : bb2arg2stmtsR.second)
336 if(arg2stms.second.size() > 0)
338 for(
const auto& stmt : arg2stms.second)
340 const auto op_it = g->CGetOpGraphInfo()->tree_node_to_operation.find(stmt);
341 if(op_it != g->CGetOpGraphInfo()->tree_node_to_operation.end())
343 RW_stmts.insert(op_it->second);
351 for(boost::tie(v, v_end) = boost::vertices(*g); v != v_end; ++v)
353 if(RW_stmts.find(*v) != RW_stmts.end())
357 const auto current_op = g->CGetOpNodeInfo(*v)->GetOperation();
358 const auto var_read =
HLSMgr->get_required_values(fun_id, *v);
362 const auto curr_tn = TreeM->CGetTreeNode(g->CGetOpNodeInfo(*v)->GetNodeId());
363 const auto me = GetPointer<const gimple_assign>(curr_tn);
364 THROW_ASSERT(me,
"only gimple_assign's are allowed as memory operations");
377 has_misaligned_indirect_ref =
true;
380 if(!has_misaligned_indirect_ref)
386 if(!has_intern_shared_data && var && function_behavior->is_variable_mem(var->index) &&
387 !
HLSMgr->Rmem->is_private_memory(var->index) &&
parameters->isOption(OPT_expose_globals) &&
388 parameters->getOption<
bool>(OPT_expose_globals))
392 (((!vd->scpe ||
GET_NODE(vd->scpe)->get_kind() == translation_unit_decl_K) && !vd->static_flag) ||
395 has_intern_shared_data =
399 unsigned long long value_bitsize;
402 const auto size_var = std::get<0>(var_read[0]);
409 const auto size_var =
HLSMgr->get_produced_value(fun_id, *v);
414 if(!(function_behavior->is_variable_mem(var->index) &&
HLSMgr->Rmem->is_private_memory(var->index)))
416 maximum_bus_size =
std::max(maximum_bus_size, value_bitsize);
419 " with maximum_bus_size=" +
STR(maximum_bus_size) +
" " + curr_tn->ToString());
425 use_databus_width =
true;
426 maximum_bus_size =
std::max(maximum_bus_size, 8ull);
427 if(assume_aligned_access_p)
429 THROW_ERROR(
"Option --aligned-access cannot be used in presence of memcpy, memcmp or memset");
433 auto vr_it_end = var_read.end();
434 for(
auto vr_it = var_read.begin(); vr_it != vr_it_end; ++vr_it)
436 const auto var = std::get<0>(*vr_it);
439 const auto var_node = TreeM->CGetTreeReindex(var);
455 maximum_bus_size =
std::max(maximum_bus_size, bitsize);
457 " with maximum_bus_size=" +
STR(maximum_bus_size) +
" " +
458 g->CGetOpNodeInfo(*v)->node->ToString());
464 const auto top_functions =
HLSMgr->CGetCallGraphManager()->GetRootFunctions();
465 const auto local_needMemoryMappedRegisters = top_functions.count(fun_id) ?
466 parameters->getOption<
bool>(OPT_memory_mapped_top) :
467 HLSMgr->hasToBeInterfaced(fun_id);
468 needMemoryMappedRegisters = needMemoryMappedRegisters || local_needMemoryMappedRegisters;
469 if(local_needMemoryMappedRegisters)
471 unsigned long long addr_bus_bitsize;
472 if(
parameters->isOption(OPT_addr_bus_bitsize))
474 addr_bus_bitsize =
parameters->getOption<
unsigned int>(OPT_addr_bus_bitsize);
478 addr_bus_bitsize = m64P ? 64 : 32;
480 for(
const auto& par : behavioral_helper->GetParameters())
483 const auto is_a_struct_union =
485 if(is_a_struct_union)
487 maximum_bus_size =
std::max(addr_bus_bitsize, maximum_bus_size);
501 "Analyzed function for bus size: " + behavioral_helper->get_function_name());
504 const auto HLS_D =
HLSMgr->get_HLS_device();
505 unsigned long long bram_bitsize = 0;
506 unsigned addr_bus_bitsize = 0;
507 const auto bram_bitsize_min = HLS_D->get_parameter<
unsigned int>(
"BRAM_bitsize_min");
508 const auto bram_bitsize_max = HLS_D->get_parameter<
unsigned int>(
"BRAM_bitsize_max");
509 HLSMgr->Rmem->set_maxbram_bitsize(bram_bitsize_max);
511 maximum_bus_size = ceil_pow2(maximum_bus_size);
513 if(has_misaligned_indirect_ref || has_unaligned_accesses)
515 if(maximum_bus_size > bram_bitsize_max)
517 THROW_ERROR(
"Unsupported data bus size. In case, try a device supporting this BRAM BITSIZE: " +
518 STR(maximum_bus_size) +
" available maximum BRAM BITSIZE: " +
STR(bram_bitsize_max));
522 bram_bitsize = maximum_bus_size;
525 else if(maximum_bus_size / 2 > bram_bitsize_max)
527 THROW_ERROR(
"Unsupported data bus size. In case, try a device supporting this BRAM BITSIZE: " +
528 STR(maximum_bus_size / 2) +
" available maximum BRAM BITSIZE: " +
STR(bram_bitsize_max));
532 bram_bitsize = maximum_bus_size / 2;
535 if(bram_bitsize < bram_bitsize_min)
537 bram_bitsize = bram_bitsize_min;
545 if(
parameters->isOption(OPT_addr_bus_bitsize))
547 addr_bus_bitsize =
parameters->getOption<
unsigned int>(OPT_addr_bus_bitsize);
549 else if(use_unknown_address)
551 addr_bus_bitsize = m64P ? 64 : 32;
556 addr_bus_bitsize = m64P ? 64 : 32;
558 else if(
HLSMgr->Rmem->get_memory_address() -
HLSMgr->base_address > 0)
560 addr_bus_bitsize = m64P ? 64 : 32;
564 unsigned long long int addr_range =
HLSMgr->Rmem->get_max_address();
568 std::max(addr_range, ((2 * HLS_D->get_parameter<
unsigned long long int>(
"BRAM_bitsize_max")) / 8));
572 for(index = 1; addr_range >= (1ull <<
index); ++
index)
576 addr_bus_bitsize =
index;
577 if(
HLSMgr->Rmem->count_non_private_internal_symbols() == 1)
583 if(needMemoryMappedRegisters)
586 maximum_bus_size =
std::max(maximum_bus_size, static_cast<unsigned long long>(addr_bus_bitsize));
588 HLSMgr->set_address_bitsize(addr_bus_bitsize);
589 HLSMgr->Rmem->set_bus_data_bitsize(maximum_bus_size);
592 HLSMgr->Rmem->set_bram_bitsize(bram_bitsize);
593 HLSMgr->Rmem->set_intern_shared_data(has_intern_shared_data);
594 HLSMgr->Rmem->set_use_unknown_addresses(use_unknown_address);
595 HLSMgr->Rmem->set_unaligned_accesses(has_unaligned_accesses);
600 "---" + (use_databus_width ? std::string(
"Spec may exploit DATA bus width") :
601 std::string(
"Spec may not exploit DATA bus width")));
603 "---" + (!use_unknown_address ?
604 std::string(
"All the data have a known address") :
605 std::string(
"Spec accesses data having an address unknown at compile time")));
607 "---" + (!has_intern_shared_data ? std::string(
"Internal data is not externally accessible") :
608 std::string(
"Internal data may be accessed")));
610 "---DATA bus bitsize: " +
STR(
HLSMgr->Rmem->get_bus_data_bitsize()));
613 "---SIZE bus bitsize: " +
STR(
HLSMgr->Rmem->get_bus_size_bitsize()));
614 if(
HLSMgr->Rmem->has_all_pointers_resolved())
618 if(has_unaligned_accesses)
622 if(
HLSMgr->Rmem->get_allocated_parameters_memory())
625 "---Total amount of memory allocated for memory mapped parameters: " +
626 STR(
HLSMgr->Rmem->get_allocated_parameters_memory()));
629 "---Internally allocated memory (no private memories): " +
630 STR(
HLSMgr->Rmem->get_allocated_internal_memory()));
632 "---Internally allocated memory: " +
STR(
HLSMgr->Rmem->get_allocated_space()));
643 const auto function_behavior =
HLSMgr->CGetFunctionBehavior(functionId);
644 const auto behavioral_helper = function_behavior->CGetBehavioralHelper();
645 const auto function_return = behavioral_helper->GetFunctionReturnType(functionId);
650 behavioral_helper->get_parameters().empty() && !function_return);
659 const auto& topParams = behavioral_helper->get_parameters();
660 for(
auto itr = topParams.begin(), end = topParams.end(); itr != end; ++itr)
664 auto par_name = behavioral_helper->PrintVariable(*itr);
665 Rmem->
add_parameter(behavioral_helper->get_function_index(), *itr, par_name, !function_return && itr_next == end);
678 Rmem->
add_parameter(behavioral_helper->get_function_index(), function_return,
"@return_" + functionName,
true);
696 std::map<unsigned int, unsigned int> cur_bb_ver;
697 std::map<unsigned int, unsigned int> cur_bitvalue_ver;
698 const auto CGMan =
HLSMgr->CGetCallGraphManager();
699 for(
const auto i : CGMan->GetReachedBodyFunctions())
701 const auto FB =
HLSMgr->CGetFunctionBehavior(i);
702 cur_bb_ver[i] = FB->GetBBVersion();
703 cur_bitvalue_ver[i] = FB->GetBitValueVersion();
711 const auto CGMan =
HLSMgr->CGetCallGraphManager();
712 for(
const auto i : CGMan->GetReachedBodyFunctions())
714 const auto FB =
HLSMgr->CGetFunctionBehavior(i);
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
static bool IsUnionType(const tree_nodeConstRef &type)
Return if treenode is an union.
const HLS_managerRef HLSMgr
information about all the HLS synthesis
static bool IsComplexType(const tree_nodeConstRef &type)
Return if treenode is a complex.
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;.
static std::string name_function(const tree_managerConstRef &tm, const unsigned int index)
Return the name of the function.
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
#define MEMCPY
constant string identifying the operation performed when two objects are memcopied.
static unsigned long long AccessedMaximumBitsize(const tree_nodeConstRef &type_node, unsigned long long bitsize)
return the maximum bitsize associated with the elements accessible through type_node ...
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define OUTPUT_LEVEL_NONE
no output print is performed.
unsigned long long int get_parameter_base_address(unsigned int funId, unsigned int var) const
Get the current base address of the given variable.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
std::map< unsigned int, unsigned int > last_bb_ver
The version of BB IR representation on which this step was applied.
~memory_allocation() override
Destructor.
Definition of the class representing a generic C application.
const int output_level
The output level.
only external memory access Datapath see only 1 memory port, while the bus manage parallel accesses ...
static bool is_a_misaligned_vector(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode index is a a misaligned access to a vector data object.
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)
all objects that need to be stored in memory are allocated on an external pipelined memory ...
void finalize_memory_allocation()
Performs a final analysis of the memory allocation to finalize the data-structure.
#define GET_NAME(data, vertex_index)
Helper macro returning the name associated with a node.
virtual DesignFlowStep_Status InternalExec()=0
Execute the step.
MemoryAllocation_ChannelsType
The number of channels.
static bool IsVolatile(const tree_nodeConstRef &tn)
return true in case the tree node corresponds to a volatile variable
all objects that need to be stored in memory are allocated on an external memory
MemoryAllocationSpecialization(const MemoryAllocation_Policy memory_allocation_policy, const MemoryAllocation_ChannelsType memory_allocation_channels_type)
Constructor.
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
redefinition of map to manage ordered/unordered structures
static bool is_packed_access(const tree_managerConstRef &TreeM, unsigned int node_index)
Check if the access is on a packed data structure or not.
#define TYPE_LOAD
Constant string identifying a memory load operation.
#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.
memory_allocation(const ParameterConstRef _parameters, const HLS_managerRef HLSMgr, const DesignFlowManagerConstRef design_flow_manager, const HLSFlowStep_Type hls_flow_step_type, const HLSFlowStepSpecializationConstRef hls_flow_step_specialization=HLSFlowStepSpecializationConstRef())
Constructor.
#define MEMSET
constant string identifying the operation performed when two objects are memsetted.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
T ceil_log2(T x)
Return the smallest n such that 2**n >= X.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
all global variables, static variables and strings are allocated on BRAMs
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...
Target must be reexecuted.
redefinition of set to manage ordered/unordered structures
#define TYPE_STORE
Constant string identifying a memory store operation.
void allocate_parameters(unsigned int functionId, memoryRef Rmem=nullptr)
Allocate parameters for given function.
#define MEMCMP
constant string identifying the operation performed when two objects are memcompared.
#define GET_CONST_NODE(t)
Classes specification of the tree_node data structures.
const MemoryAllocation_ChannelsType memory_allocation_channels_type
number of channels
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
Base class to allocate memories in high-level synthesis.
static bool is_a_pointer(const tree_managerConstRef &TM, const unsigned int index)
Return if treenode index is a pointer.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
std::map< unsigned int, unsigned int > last_bitvalue_ver
The version of bit value IR representation on which this step was applied.
T compute_n_bytes(T bitsize)
static void check_bitwidth(unsigned long long prec)
check if the maximum bitwidth used for registers, busses, muxes, etc. is compatible with prec ...
This file collects some utility functions.
for each memory at maximum n parallel direct accesses and one indirect access
static tree_nodeConstRef GetBaseVariable(const tree_nodeConstRef &mem)
Retrun the base variable of a memory access.
CustomOrderedSet< unsigned int > func_list
list of functions to be analyzed
struct definition of the type node structures.
Class specification of the tree_reindex support class.
const CustomUnorderedSet< std::tuple< HLSFlowStep_Type, HLSFlowStepSpecializationConstRef, HLSFlowStep_Relationship > > ComputeHLSRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Compute the relationship of this step.
T * GetPointer(const refcount< U > &t)
Template function used to hide dynamic_cast The template parameter T represents a type of an object h...
std::string GetKindText() const override
Return the string representation of this.
DesignFlowStep_Status Exec() override
Execute the step.
unsigned int memory_version
The version of memory representation on which this step was applied.
all local variables, static variables and strings are allocated on BRAMs
for each memory at maximum n parallel direct accesses and n parallel indirect accesses ...
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
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.
for each memory at maximum one direct access and one indirect access
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
std::string GetSignature() const override
Return the contribution to the signature of a step given by the specialization.
Generic device description.
int debug_level
The debug level.
The information about how memory allocation has to be specialized.
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
refcount< const HLSFlowStepSpecialization > HLSFlowStepSpecializationConstRef
const refcount definition of the class
all objects that need to be stored in memory are allocated on BRAMs
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
const MemoryAllocation_Policy memory_allocation_policy
memory allocation policy
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
Datastructure to represent memory information in high-level synthesis.
MemoryAllocation_Policy
The allocation memory polycy.
void add_parameter(unsigned int funID_scope, unsigned int var, const std::string &var_name, bool is_last)
Allocates a parameter to the set of the interface registers.
Class specification of the manager of the tree structures extracted from the raw file.
HLS specialization of generic_device.
A brief description of the C++ Header File.
void setup_memory_allocation()
Prepares the data structures for the memory allocation.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...