82 #define EPSILON 0.0001 85 const DesignFlowManagerConstRef _design_flow_manager,
98 switch(relationship_type)
110 GetPointer<const HLS_manager>(
AppM) && GetPointerS<const HLS_manager>(
AppM)->get_HLS(
function_id) and
119 const auto design_flow_step =
120 design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
121 if(GetPointerS<const FunctionFrontendFlowStep>(design_flow_step)->
CGetBBVersion() !=
124 relationships.insert(std::make_pair(UPDATE_SCHEDULE,
SAME_FUNCTION));
134 relationships.insert(std::make_pair(COMMUTATIVE_EXPR_RESTRUCTURING,
SAME_FUNCTION));
135 relationships.insert(std::make_pair(COMPLETE_BB_GRAPH,
SAME_FUNCTION));
136 relationships.insert(std::make_pair(FUNCTION_CALL_OPT,
SAME_FUNCTION));
137 relationships.insert(std::make_pair(MULTI_WAY_IF,
SAME_FUNCTION));
138 relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF,
SAME_FUNCTION));
146 return relationships;
157 GetPointer<const HLS_manager>(
AppM) && GetPointerS<const HLS_manager>(
AppM)->get_HLS(
function_id) and
166 const auto design_flow_step = design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
167 if(GetPointerS<const FunctionFrontendFlowStep>(design_flow_step)->
CGetBBVersion() !=
192 TM =
AppM->get_tree_manager();
202 bool modified =
false;
205 THROW_ASSERT(GetPointer<const HLS_manager>(
AppM)->get_HLS_device(),
"unexpected condition");
206 const auto hls_d = GetPointerS<const HLS_manager>(
AppM)->get_HLS_device();
207 THROW_ASSERT(hls_d->has_parameter(
"max_lut_size"),
"unexpected condition");
208 const auto max_lut_size = hls_d->get_parameter<
size_t>(
"max_lut_size");
212 const auto sl = GetPointerS<const statement_list>(
GET_CONST_NODE(fd->body));
213 for(
const auto&
block : sl->list_of_bloc)
216 const auto& list_of_stmt =
block.second->CGetStmtList();
217 for(
auto stmt = list_of_stmt.begin(); stmt != list_of_stmt.end(); stmt++)
219 if(!
AppM->ApplyNewTransformation())
224 std::list<tree_nodeRef> new_tree_nodes;
227 auto next_stmt_ptr = std::next(stmt);
237 bool first_operand_of_first =
true;
238 bool first_operand_of_second =
true;
243 first_operand_of_first =
false;
248 "---Chained with a second cond_expr: " +
STR(second_stmt));
253 first_operand_of_second =
false;
261 const auto first_ga = GetPointer<const gimple_assign>(
GET_NODE(*stmt));
262 const auto first_ce = GetPointer<const cond_expr>(
GET_NODE(first_ga->op1));
264 const auto second_ga = GetPointer<const gimple_assign>(
GET_NODE(second_stmt));
265 const auto second_ce = GetPointer<const cond_expr>(
GET_NODE(second_ga->op1));
267 const auto third_ga = GetPointer<const gimple_assign>(
GET_NODE(third_stmt));
268 const auto third_ce = GetPointer<const cond_expr>(
GET_NODE(third_ga->op1));
274 double operand_ready_time = 0.0;
276 const auto other_operand_of_first = first_operand_of_first ? first_ce->op2 : first_ce->op1;
277 const auto other_operand_of_second = first_operand_of_second ? second_ce->op2 : second_ce->op1;
279 operands.insert(std::make_pair(other_operand_of_first, *stmt));
280 operands.insert(std::make_pair(other_operand_of_second, second_stmt));
281 operands.insert(std::make_pair(third_ce->op1, third_stmt));
282 operands.insert(std::make_pair(third_ce->op2, third_stmt));
283 operands.insert(std::make_pair(first_ce->op0, *stmt));
284 operands.insert(std::make_pair(second_ce->op0, second_stmt));
285 operands.insert(std::make_pair(third_ce->op0, third_stmt));
286 for(
const auto& operand : operands)
289 "---Analyzing when " +
STR(operand.first) +
" used in " +
STR(operand.second) +
" is ready");
290 const auto sn = GetPointer<const ssa_name>(
GET_NODE(operand.first));
293 const auto def_operand = GetPointer<const gimple_node>(
GET_NODE(sn->CGetDefStmt()));
294 if(def_operand->bb_index ==
block.first)
296 const auto def_stmt = sn->CGetDefStmt();
302 "---Connection time is " +
STR(connection_time));
303 const auto current_operand_ready_time = ending_time + connection_time;
304 operand_ready_time =
std::max(operand_ready_time, current_operand_ready_time);
306 "---New ready time is " +
STR(operand_ready_time));
314 "---Delay of first operation is " +
STR(cond_expr_time1));
315 const auto cond_expr_time2 =
318 "---Delay of second operation is " +
STR(cond_expr_time2));
319 const auto cond_expr_time3 =
322 "---Delay of third operation is " +
STR(cond_expr_time3));
323 const auto new_ending_time = operand_ready_time +
std::max(cond_expr_time1, cond_expr_time3) +
328 "---Operand ready time " +
STR(operand_ready_time) +
" - New ending time " +
329 STR(new_ending_time) +
" - Old ending time " +
STR(old_time));
330 if(new_ending_time +
EPSILON >= old_time)
343 auto first_value = first_operand_of_second ? second_ce->op2 : second_ce->op1;
344 auto second_value = first_operand_of_first ? first_ce->op2 : first_ce->op1;
345 if(!first_operand_of_first)
347 std::swap(first_value, second_value);
349 const auto cond_expr_node = tree_man->create_ternary_operation(
type_node, first_ce->op0, first_value,
357 const auto sn1 = GetPointer<const ssa_name>(
GET_CONST_NODE(first_value));
358 const auto sn2 = GetPointer<const ssa_name>(
GET_CONST_NODE(second_value));
359 if(sn1->var && sn2->var && sn1->var->index == sn2->var->index)
364 const auto first_ga_op0 = GetPointer<const ssa_name>(
GET_CONST_NODE(first_ga->op0));
365 const auto ssa_node = tree_man->create_ssa_name(var,
type_node, first_ga_op0->min, first_ga_op0->max);
366 GetPointerS<ssa_name>(
GET_NODE(ssa_node))->bit_values = first_ga_op0->bit_values;
369 const auto curr_stmt =
373 block.second->PushBefore(curr_stmt, *stmt,
AppM);
374 new_tree_nodes.push_back(curr_stmt);
380 if(!first_operand_of_first && !first_operand_of_second)
382 const auto boolType = tree_man->GetBooleanType();
386 const auto DefaultUnsignedLongLongInt = tree_man->GetUnsignedLongLongType();
389 tree_man->create_lut_expr(boolType, lut_constant_node, first_ce->op0,
nullptr,
nullptr,
nullptr,
398 const auto not_expr =
399 tree_man->create_unary_operation(boolType, first_ce->op0,
BUILTIN_SRCP, truth_not_expr_K);
405 block.second->PushBefore(ga, *stmt,
AppM);
406 new_tree_nodes.push_back(ga);
407 and_first_cond = GetPointerS<gimple_assign>(
GET_NODE(ga))->op0;
409 else if(first_operand_of_first && first_operand_of_second)
412 and_first_cond = first_ce->op0;
416 const auto boolType = tree_man->GetBooleanType();
423 const auto boolType = tree_man->GetBooleanType();
428 const auto DefaultUnsignedLongLongInt = tree_man->GetUnsignedLongLongType();
429 long long int lut_val;
430 if(!first_operand_of_first && !first_operand_of_second)
434 else if(!first_operand_of_first && first_operand_of_second)
438 else if(first_operand_of_first && !first_operand_of_second)
448 tree_man->create_lut_expr(boolType, lut_constant_node, second_ce->op0, first_ce->op0,
nullptr,
449 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
BUILTIN_SRCP);
457 if(!first_operand_of_first && !first_operand_of_second)
459 const auto not_expr0 =
460 tree_man->create_unary_operation(boolType, second_ce->op0,
BUILTIN_SRCP, truth_not_expr_K);
461 const auto op0_not_expr = tree_man->CreateGimpleAssign(
464 block.second->PushBefore(op0_not_expr, *stmt,
AppM);
465 new_tree_nodes.push_back(op0_not_expr);
466 const auto not_expr1 =
467 tree_man->create_unary_operation(boolType, first_ce->op0,
BUILTIN_SRCP, truth_not_expr_K);
468 const auto op1_not_expr = tree_man->CreateGimpleAssign(
471 block.second->PushBefore(op1_not_expr, *stmt,
AppM);
472 new_tree_nodes.push_back(op1_not_expr);
473 const auto and_expr = tree_man->create_binary_operation(
474 boolType, GetPointerS<gimple_assign>(
GET_NODE(op0_not_expr))->op0,
480 else if(!first_operand_of_first && first_operand_of_second)
482 const auto not_expr1 =
483 tree_man->create_unary_operation(boolType, first_ce->op0,
BUILTIN_SRCP, truth_not_expr_K);
484 const auto op1_not_expr = tree_man->CreateGimpleAssign(
487 block.second->PushBefore(op1_not_expr, *stmt,
AppM);
488 new_tree_nodes.push_back(op1_not_expr);
489 const auto and_expr = tree_man->create_binary_operation(
490 boolType, second_ce->op0, GetPointerS<gimple_assign>(
GET_NODE(op1_not_expr))->op0,
BUILTIN_SRCP,
496 else if(first_operand_of_first && !first_operand_of_second)
498 const auto not_expr0 =
499 tree_man->create_unary_operation(boolType, second_ce->op0,
BUILTIN_SRCP, truth_not_expr_K);
500 const auto op0_not_expr = tree_man->CreateGimpleAssign(
503 block.second->PushBefore(op0_not_expr, *stmt,
AppM);
504 new_tree_nodes.push_back(op0_not_expr);
505 const auto and_expr = tree_man->create_binary_operation(
514 const auto and_expr = tree_man->create_binary_operation(boolType, second_ce->op0, first_ce->op0,
522 block.second->PushBefore(ga, *stmt,
AppM);
523 new_tree_nodes.push_back(ga);
524 and_first_cond = GetPointerS<gimple_assign>(
GET_NODE(ga))->op0;
528 const auto root_cond_expr = tree_man->create_ternary_operation(
529 type_node, and_first_cond, first_operand_of_second ? second_ce->op1 : second_ce->op2, ssa_node,
533 const auto root_gimple_node =
538 block.second->Replace(*stmt, root_gimple_node,
true,
AppM);
540 new_tree_nodes.push_back(root_gimple_node);
541 AppM->RegisterTransformation(
GetName(), root_gimple_node);
547 block.second->RemoveStmt(second_stmt,
AppM);
549 for(
const auto& temp_stmt : list_of_stmt)
555 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
559 "---Written BB_Inside_" +
GetName() +
"_" +
STR(counter) +
".dot");
563 if(new_time +
EPSILON > old_time)
567 for(
const auto& to_be_removed : new_tree_nodes)
569 block.second->RemoveStmt(to_be_removed,
AppM);
573 next_stmt ?
block.second->PushBefore(second_stmt, next_stmt,
AppM) :
574 block.second->PushBack(second_stmt,
AppM);
575 next_stmt ?
block.second->PushBefore(first_stmt, next_stmt,
AppM) :
576 block.second->PushBack(first_stmt,
AppM);
579 for(
const auto& temp_stmt : list_of_stmt)
585 stmt = std::prev(next_stmt_ptr);
591 stmt = list_of_stmt.begin();
605 const auto ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(tn));
610 return GET_NODE(ga->op1)->get_kind() == cond_expr_K;
614 bool is_third_node)
const 616 const auto ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(tn));
617 const auto ce = GetPointer<const cond_expr>(
GET_NODE(ga->op1));
620 const auto sn = GetPointer<const ssa_name>(operand);
629 if(!is_third_node && sn->CGetNumberUses() > 1)
633 const auto def = GetPointer<const gimple_assign>(
GET_NODE(sn->CGetDefStmt()));
638 if(def->bb_index != ga->bb_index)
642 const auto chain_ce = GetPointer<const cond_expr>(
GET_NODE(def->op1));
650 return sn->CGetDefStmt();
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
bool IsCondExprGimple(const tree_nodeConstRef tn) const
Return true if tree node is a gimple_assign with a cond_expr in the right part.
#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;.
virtual void Initialize()
Initialize the step (i.e., like a constructor, but executed just before exec.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
AbsControlStep get_cstep(const vertex &op) const
Returns the clock cycle where the given operation has been scheduled.
AllocationInformationRef allocation_information
The allocation information.
AbsControlStep get_cstep_end(const vertex &op) const
Return the last clock cycle in which the operation execute.
A simple interface to token object of the raw files.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Data structure describing a basic block at tree level.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
~CondExprRestructuring() override
Destructor.
CondExprRestructuring(const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
void UpdateTime(const unsigned int operation_index, bool update_cs=true)
Compute the starting and the ending time of a statement.
Data structure used to store the schedule of the operations.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
tree_nodeRef IsCondExprChain(const tree_nodeConstRef tn, const bool first, bool is_third_node) const
Given a gimple_assign with cond_expr in the right part and one of its operand it checks: ...
#define EPSILON
Header include.
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.
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.
Analysis step restructing tree of cond_expr to reduce critical path delay.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
unsigned int CGetBBVersion() const
#define GET_CONST_NODE(t)
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
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.
static const unsigned int UNKNOWN
The value used to identified unknown functional unit.
This struct specifies the block node.
This file collects some utility functions.
double GetStartingTime(const unsigned int operation) const
Return the starting time of the operation.
refcount< T > lock() const
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
struct definition of the type node structures.
Class specification of the tree_reindex support class.
tree_managerRef TM
The tree manager.
Data structure used to store the functional-unit binding of the vertexes.
ScheduleRef schedule
The schedule.
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.
this class is used to manage the command-line or XML options.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
unsigned counter[N_THREADS]
int debug_level
The debug level.
double GetEndingTime(const unsigned int operation) const
Return the starting time of the operation.
DesignFlowStep_Status InternalExec() override
Performs the loops analysis.
#define GET_INDEX_CONST_NODE(t)
static bool is_constant(const tree_managerConstRef &TM, const unsigned int index)
Return if a tree node is a constant object.
Data structure definition for high-level synthesis flow.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
HLS specialization of generic_device.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
static const std::string ComputeSignature(const FrontendFlowStepType frontend_flow_step_type, const unsigned int function_id)
Compute the signature of a function frontend flow step.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...