85 const DesignFlowManagerConstRef _design_flow_manager,
116 GetPointer<module>(circuit)->set_description(
"FSM based controller description for " + function_name);
118 GetPointer<module>(circuit)->set_authors(
"Component automatically generated by bambu");
125 std::string state_representation;
143 for(
unsigned int i = 0; i < to_be_printed.size(); i++)
145 output += (to_be_printed[i] ==
default_COND ?
"-" : std::to_string(to_be_printed[i]));
146 if(i != (to_be_printed.size() - 1) && with_comma)
159 const auto FB =
HLSMgr->CGetFunctionBehavior(
funId);
161 const auto fsymbol = FB->CGetBehavioralHelper()->GetMangledFunctionName();
162 const auto func_arch =
HLSMgr->module_arch->GetArchitecture(fsymbol);
163 const auto is_dataflow_top = func_arch &&
164 func_arch->attrs.find(FunctionArchitecture::func_dataflow) != func_arch->attrs.end() &&
165 func_arch->attrs.find(FunctionArchitecture::func_dataflow)->second ==
"top";
168 THROW_ASSERT(boost::out_degree(entry, *stg) == 1,
"Non deterministic initial state");
170 const auto first_state =
boost::target(*boost::out_edges(entry, *stg).first, *stg);
177 std::map<vertex, std::vector<long long int>> present_state;
182 std::list<vertex> working_list;
183 astg->TopologicalSort(working_list);
184 THROW_ASSERT(std::find(working_list.begin(), working_list.end(), first_state) != working_list.end(),
186 working_list.erase(std::find(working_list.begin(), working_list.end(), first_state));
187 working_list.push_front(first_state);
189 std::map<vertex, std::vector<bool>> state_Xregs;
190 std::map<unsigned int, unsigned int> wren_list;
191 std::map<unsigned int, unsigned int> register_selectors;
193 std::map<unsigned int, CustomUnorderedSet<vertex>> loop_map;
194 std::map<unsigned int, std::list<vertex>> loop_executing_ops;
195 std::map<unsigned int, std::list<vertex>> loop_starting_ops;
197 std::map<unsigned int, vertex> loop_last_state;
200 if(FB->is_pipeline_enabled())
202 for(
const auto& v : working_list)
204 auto info = astg->CGetStateInfo(v);
207 if(info->loopId != 0)
209 loop_map[info->loopId].insert(v);
215 for(
auto loop : loop_map)
217 auto loop_first_state = first_state;
220 bool found_first =
false;
221 bool found_last =
false;
224 for(
auto v : loop_map[get<0>(loop)])
228 if(stg->CGetStateInfo(boost::source(ie, *astg))->loopId != std::get<0>(loop))
230 THROW_ASSERT(not found_first,
"A loop has multiple first states");
234 loop_first_state = v;
237 bool all_external =
true;
240 all_external = all_external && astg->CGetStateInfo(
boost::target(lst, *astg))->loopId != std::get<0>(loop);
248 THROW_ASSERT(!found_last,
"A loop has multiple outgoing edges");
252 loop_last_state[std::get<0>(loop)] = v;
254 for(
auto op : stg->CGetStateInfo(v)->executing_operations)
256 loop_executing_ops[get<0>(loop)].push_front(op);
259 THROW_ASSERT(found_last,
"No last state was detected for loop " + std::to_string(get<0>(loop)));
260 THROW_ASSERT(found_first,
"No first state was detected for loop " + std::to_string(get<0>(loop)));
261 loop_starting_ops[get<0>(loop)] = stg->CGetStateInfo(loop_first_state)->starting_operations;
264 std::map<unsigned int, std::map<vertex, std::set<unsigned int>>> bypass_signals;
265 for(
const auto& v : working_list)
270 if(analyzed_loops.find(stg->CGetStateInfo(v)->loopId) == analyzed_loops.end())
273 "Analyzing loop " + std::to_string(stg->CGetStateInfo(v)->loopId));
274 present_state[v] = std::vector<long long int>(
out_num, 0);
275 if(stg->CGetStateInfo(v)->loopId != 0 && FB->is_pipeline_enabled())
277 analyzed_loops.insert(stg->CGetStateInfo(v)->loopId);
279 if(selectors.find(conn_binding::IN) != selectors.end())
281 for(
const auto& s : selectors.at(conn_binding::IN))
284 std::map<vertex, CustomOrderedSet<vertex>> activations_check;
286 const auto& activations = GetPointer<commandport_obj>(s.second)->get_activations();
287 for(
const auto& a : activations)
290 if(activations_check.find(std::get<0>(a)) != activations_check.end())
292 THROW_ASSERT(!activations_check.find(std::get<0>(a))->second.empty(),
293 "empty set not expected here");
294 if(activations_check.at(std::get<0>(a)).find(std::get<1>(a)) ==
295 activations_check.at(std::get<0>(a)).end())
301 else if(activations_check.at(std::get<0>(a)).find(
NULL_VERTEX) !=
302 activations_check.at(std::get<0>(a)).end())
308 activations_check[std::get<0>(a)].
insert(std::get<1>(a));
318 activations_check[std::get<0>(a)].
insert(std::get<1>(a));
321 if(std::get<0>(a) == v && (stg->CGetStateInfo(v)->loopId == 0 || !FB->is_pipeline_enabled()))
323 present_state[v][
out_ports[s.second]] = 1;
325 else if(loop_map[stg->CGetStateInfo(v)->loopId].find(std::get<0>(a)) !=
326 loop_map[stg->CGetStateInfo(v)->loopId].end() &&
327 stg->CGetStateInfo(v)->loopId != 0 && FB->is_pipeline_enabled())
329 present_state[v][
out_ports[s.second]] = 1;
336 const auto TreeM =
HLSMgr->get_tree_manager();
337 const auto& operations = (stg->CGetStateInfo(v)->loopId == 0 || !FB->is_pipeline_enabled()) ?
338 astg->CGetStateInfo(v)->executing_operations :
339 loop_executing_ops[stg->CGetStateInfo(v)->loopId];
340 for(
const auto& op : operations)
344 const auto op_tn = GetPointer<functional_unit>(tn)->get_operation(
347 "Time model not available for operation: " +
GET_NAME(data, op));
348 const auto& CM = GetPointer<functional_unit>(tn)->CM;
353 const auto top = CM->get_circ();
355 const auto fu_module = GetPointer<module>(
top);
360 if(!GetPointer<operation>(op_tn)->is_bounded() && (!start_port_i || !done_port_i))
362 THROW_ERROR(
"Unbounded operations have to have both done_port and start_port ports!" +
363 STR(TreeM->CGetTreeNode(data->CGetOpNodeInfo(op)->GetNodeId())));
367 bool is_starting_operation =
true;
368 if(!is_dataflow_top && (stg->CGetStateInfo(v)->loopId == 0 || !FB->is_pipeline_enabled()))
370 const auto& starting_ops = stg->CGetStateInfo(v)->starting_operations;
371 is_starting_operation = std::find(starting_ops.begin(), starting_ops.end(), op) != starting_ops.end();
374 if((!GetPointer<operation>(op_tn)->is_bounded()))
376 auto node = TreeM->CGetTreeNode(data->CGetOpNodeInfo(op)->GetNodeId());
377 if(node->get_kind() == gimple_assign_K)
379 const auto nodeGA = GetPointerS<const gimple_assign>(node);
383 const auto storage_value_index =
386 const auto doneCommand =
388 const auto doneVertex = GetPointer<commandport_obj>(doneCommand)->get_vertex();
390 const auto reg_obj =
HLS->
Rreg->
get(written_reg);
392 reg_obj, written_reg);
394 bypass_signals[1 +
out_ports.find(sel_port)->second][v].insert(
400 if((!GetPointer<operation>(op_tn)->is_bounded() || start_port_i) &&
401 (!stg->CGetStateInfo(v)->is_dummy || is_dataflow_top) && is_starting_operation)
403 const auto unbounded_port =
405 unbounded_ports.insert(unbounded_port);
406 present_state[v][unbounded_port] = 1;
410 if(stg->CGetStateInfo(v)->loopId == 0 || !FB->is_pipeline_enabled())
418 state_Xregs[v][accessed_reg] =
false;
422 if(selectors.find(conn_binding::IN) != selectors.end())
424 for(
const auto& s : selectors.at(conn_binding::IN))
428 const auto current_port = GetPointer<commandport_obj>(s.second);
430 if(current_port->get_command_type() == commandport_obj::command_type::WRENABLE)
432 const auto reg_obj = GetPointer<register_obj>(current_port->get_elem());
433 wren_list.insert(std::make_pair(reg_obj->get_register_index(),
out_ports[s.second]));
436 if(state_Xregs[v][reg_obj->get_register_index()] && v != first_state)
438 present_state[v][
out_ports[s.second]] = 2;
440 "Set X value for wr_en on register reg_" +
441 std::to_string(reg_obj->get_register_index()));
445 else if(current_port->get_command_type() == commandport_obj::command_type::SELECTOR)
447 const auto selector_slave = current_port->get_elem();
448 if(GetPointer<mux_obj>(selector_slave))
450 auto mux_slave = GetPointer<mux_obj>(selector_slave)->get_final_target();
451 if(mux_slave->get_type() == generic_obj::resource_type::REGISTER)
453 const auto reg_index = GetPointer<register_obj>(mux_slave)->get_register_index();
454 register_selectors[
out_ports[s.second]] = reg_index;
456 else if(mux_slave->get_type() == generic_obj::resource_type::FUNCTIONAL_UNIT &&
457 active_fu.find(mux_slave) == active_fu.end())
460 parameters->GetParameter<
int>(
"enable-FSMX") == 1)
462 present_state[v][
out_ports[s.second]] = 2;
474 "---default output after considering unbounded: " +
container_to_string(present_state[v],
" "));
480 bool first_io =
true;
481 for(
const auto& vio : bypass_signals)
491 parse +=
STR(vio.first) +
"=";
492 bool first_vi =
true;
493 for(
const auto& vi : vio.second)
503 parse += stg->CGetStateInfo(vi.first)->name +
">";
505 for(
const auto& i : vi.second)
521 analyzed_loops.clear();
524 for(
const auto& v : working_list)
533 if(analyzed_loops.find(stg->CGetStateInfo(v)->loopId) == analyzed_loops.end())
535 if(stg->CGetStateInfo(v)->loopId != 0 && FB->is_pipeline_enabled())
537 analyzed_loops.insert(stg->CGetStateInfo(v)->loopId);
543 std::list<EdgeDescriptor> sorted;
545 bool found_default =
false;
547 if(stg->CGetStateInfo(v)->loopId == 0 || !FB->is_pipeline_enabled())
553 ver = loop_last_state[stg->CGetStateInfo(v)->loopId];
559 if(stg->CGetTransitionInfo(oe)->get_has_default())
561 found_default =
true;
566 sorted.push_back(oe);
571 sorted.push_back(oe);
576 sorted.push_back(default_edge);
581 for(
const auto e : sorted)
584 "-->Considering successor state " + stg->CGetStateInfo(
boost::target(e, *stg))->name);
586 std::vector<std::string> in(
in_num,
"-");
589 auto transitionType = stg->CGetTransitionInfo(e)->get_type();
596 auto op = stg->CGetTransitionInfo(e)->get_operation();
603 auto op = stg->CGetTransitionInfo(e)->get_operation();
610 auto ops = stg->CGetTransitionInfo(e)->get_operations();
613 auto op = *(ops.begin());
616 "two different values for the same condition port");
621 auto state = stg->CGetTransitionInfo(e)->get_ref_state();
624 "two different values for the same condition port");
625 in[
mu_ports.find(state)->second] =
"1";
630 auto ops = stg->CGetTransitionInfo(e)->get_operations();
633 auto op = *(ops.begin());
636 "two different values for the same condition port");
641 auto state = stg->CGetTransitionInfo(e)->get_ref_state();
644 "two different values for the same condition port");
645 in[
mu_ports.find(state)->second] =
"0";
650 auto op = stg->CGetTransitionInfo(e)->get_operation();
654 THROW_ASSERT(value ==
"-",
"two different values for the same condition port");
655 auto labels = stg->CGetTransitionInfo(e)->get_labels();
656 for(
auto label : labels)
667 if(stg->CGetTransitionInfo(e)->get_has_default())
687 for(
auto in_it = in.begin(); in_it != in.end(); ++in_it)
689 if(in_it == in.begin())
695 parse +=
"," + *in_it;
701 vertex next_state = last_transition ? first_state : tgt;
702 bool assert_done_port =
false;
703 if(done_port_is_registered)
709 assert_done_port =
true;
716 assert_done_port = last_transition;
722 if(present_state[v][
k] == 1 && unbounded_ports.find(
k) == unbounded_ports.end())
724 transition_outputs[
k] = 0;
728 if(selectors.find(conn_binding::IN) != selectors.end())
730 for(
const auto& s : selectors.at(conn_binding::IN))
732 auto current_port = GetPointer<commandport_obj>(s.second);
733 if(current_port->get_command_type() == commandport_obj::command_type::MULTI_UNBOUNDED_ENABLE)
735 auto mu_obj = GetPointer<multi_unbounded_obj>(current_port->get_elem());
736 if(v == mu_obj->get_fsm_state())
738 transition_outputs[
out_ports[s.second]] = 1;
741 const auto& activations = current_port->get_activations();
742 for(
const auto& a : activations)
745 bool source_activation =
false;
746 if(stg->CGetStateInfo(v)->loopId == 0 || !FB->is_pipeline_enabled())
748 source_activation = std::get<0>(a) == v;
752 source_activation = loop_map[stg->CGetStateInfo(v)->loopId].find(std::get<0>(a)) !=
753 loop_map[stg->CGetStateInfo(v)->loopId].end();
755 if(source_activation && (std::get<1>(a) == tgt || std::get<1>(a) ==
NULL_VERTEX))
758 transition_outputs[
out_ports[s.second]] = 1;
763 for(
auto const& sel : register_selectors)
767 if(wren_list.find(sel.second) != wren_list.end() &&
768 ((transition_outputs[wren_list[sel.second]] == 0) ||
769 (transition_outputs[wren_list[sel.second]] ==
default_COND &&
770 present_state[v][wren_list[sel.second]] != 1)))
772 transition_outputs[sel.first] = 2;
780 if(present_state[v][
k] == transition_outputs[
k])
784 else if(present_state[v][k] != transition_outputs[k] && present_state[v][k] == 1 &&
785 transition_outputs[k] == 0)
792 parse +=
" " + stg->CGetStateInfo(next_state)->name +
" " + (assert_done_port ?
"1" :
"-") +
815 return "&" +
STR(pos);
821 auto cle = GetPointer<case_label_expr>(node);
822 THROW_ASSERT(cle->op0,
"guard expected in a case_label_expr");
824 "expected integer_cst object as guard in a case_label_expr");
830 "expected integer_cst object as guard in a case_label_expr");
835 return STR(low_result);
839 std::string res_string;
840 for(
auto current_value = low_result; current_value <= high_result; ++current_value)
842 if(current_value == low_result)
844 res_string =
STR(current_value);
848 res_string +=
"|" +
STR(current_value);
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Class specification to contain liveness information.
virtual void add_correct_transition_memory(const std::string &state_representation, structural_managerRef SM)
Set the correct NP functionality.
unsigned int get_register(unsigned int sv) const
return the register index where the storage value is stored
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
const HLS_managerRef HLSMgr
information about all the HLS synthesis
a multi unbounded controller
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 * top(node_stack *head)
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
void create_state_machine(std::string &parse)
Generates the string representation of the FSM.
refcount< structural_type_descriptor > structural_type_descriptorRef
RefCount type definition of the structural_type_descriptor class structure.
File containing functions and utilities to support the printing of debug messagges.
Base class for all unbounded objects added to datapath.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
generic_objRef get(const vertex v) const
Returns reference to funit object associated with this vertex.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
This file contains the structures needed to manage a graph that will represent the state transition g...
Structure representing the most relevant information about the type of a structural object...
Base class for all command ports into datapath.
#define TYPE_MULTIIF
constant identifying the a multi-way if
#define GET_CLASS(obj)
Macro returning the actual type of an object.
std::string get_function_name() const
Return the name of the function.
#define GENERATED_LICENSE
const structural_objectRef get_circ() const
Get a reference to circ field.
vertex get_entry_state() const
Gets vertex that represents state that contains entry node.
generic_objRef bind_selector_port(direction_type dir, unsigned int mode, const vertex &cond, const OpGraphConstRef data)
virtual void add_common_ports(structural_objectRef circuit, structural_managerRef SM)
This member function adds the standard ports (clock, reset, done and command ones) to a circuit...
DesignFlowStep_Status InternalExec() override
Execute the step.
const std::map< unsigned int, Selectors > & GetSelectors() const
Header class for the creation of the classical FSM controller.
static std::string input_vector_to_string(const std::vector< long long int > &to_be_printed, bool with_comma)
unsigned int get_assign(const vertex &v) const
Returns the functional unit assigned to the vertex.
const unsigned int funId
identifier of the function to be processed (0 means that it is a global step)
#define GET_NAME(data, vertex_index)
Helper macro returning the name associated with a node.
exceptions managed by PandA
AllocationInformationRef allocation_information
Store the technology information.
vertex get_exit_state() const
Gets vertex that represents state that contains exit node.
void insert(node_tree **tree, int val)
Class specification of the manager of the technology library data structures.
std::map< vertex, unsigned int > cond_ports
This is the same as in_ports except that the first element is of type vertex.
static unsigned int get_multi_way_if_pos(const tree_managerConstRef &TM, unsigned int node_id, unsigned int cond)
return the position of con in the gimple_multi_way_if conditions
redefinition of map to manage ordered/unordered structures
volatile int output[DIM_Y][DIM_X]
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#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
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
unsigned int in_num
Initialized after add_common_ports is called. It represents the current number of input ports...
fu_bindingRef Rfu
Store the refcounted functional unit binding of the operations.
static void add_NP_functionality(structural_objectRef cir, NP_functionality::NP_functionaly_type dt, std::string functionality_description)
Add a not-parsed functionality.
std::string get_guard_value(const tree_managerRef TM, const unsigned int index, vertex op, const OpGraphConstRef data)
Returns the value of the guard value of a case_label_expr default is not managed. ...
Data structure used to store the register binding of variables.
StorageValueInformationRef storage_value_information
data-structure for storage values
Base class for multiplexer into datapath.
void set_top_info(const std::string &id, const technology_managerRef &LM, const std::string &Library="")
Data structure used to store the interconnection binding of datapath elements.
Data structure used to store the schedule of the operations.
static const uint32_t k[]
unsigned int out_num
Initialized after add_common_ports is called. It represents the current number of output ports...
Class specification of the data structures used to manage technology information. ...
generic_objRef get(const unsigned int &r) const
Returns reference to register object associated to a given index.
fsm_controller(const ParameterConstRef Param, const HLS_managerRef HLSMgr, unsigned int funId, const DesignFlowManagerConstRef design_flow_manager, const HLSFlowStep_Type hls_flow_step_type=HLSFlowStep_Type::FSM_CONTROLLER_CREATOR)
Constructor.
#define default_COND
constant used to represent label "default" of a switch construct
redefinition of set to manage ordered/unordered structures
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
void set_black_box(bool bb)
Set the black box property associated with the structural_object.
Base class for all register into datapath.
This file contains the structures needed to manage a graph that will represent the state transition g...
const BehavioralHelperConstRef CGetBehavioralHelper() const
Returns the helper associated with the function.
Classes specification of the tree_node data structures.
static std::string NormalizeTypename(const std::string &id)
Return normalized name of types and variables.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
std::map< generic_objRef, unsigned int > out_ports
This contains all the ports that go from the controller to the datapath, used to enable the registers...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
reg_bindingRef Rreg
Store the refcounted register binding of the variables.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
const StateTransitionGraphConstRef CGetAstg() const
Returns pointer to state transition graph created.
livenessRef Rliv
data-structure containing the variable liveness
This file collects some utility functions.
structural_managerRef controller
Store the controller description.
bool registered_done_port
true when the done port is registered
This class describes all classes used to represent a structural object.
Class specification of the tree_reindex support class.
Generic class managing controller creation algorithms.
Data structure used to store the functional-unit binding of the vertexes.
Class specification of the basic_block structure.
hlsRef HLS
HLS data structure of the function to be analyzed.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
unsigned int get_used_regs() const
returns number of used register
It collects all the common strings covering PandA copyrights issues.
~fsm_controller() override
Destructor.
std::string container_to_string(_InputIt first, _InputIt last, const std::string &separator, bool trim_empty=true)
Class implementation of the structural_manager.
StateTransitionGraphManagerRef STG
Store the refcounted state transition graph.
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
Base class for all register into datapath.
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
Data structure definition for high-level synthesis flow.
const StateTransitionGraphConstRef CGetStg() const
Returns pointer to state transition graph created.
conn_bindingRef Rconn
Store the refcounted interconnection of datapath elements.
#define GENERATED_COPYRIGHT
#define NULL_VERTEX
null vertex definition
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
std::map< vertex, unsigned int > mu_ports
This map put into relation fsm states and alldone multi_unbounded ports.
const CustomOrderedSet< unsigned int > & get_live_in(const vertex &v) const
Get the set of variables live at the input of a vertex.
boost::graph_traits< graph >::edge_descriptor EdgeDescriptor
edge definition.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...