def create_ep_img(type): """ @brief create the endpoint image @param[in] type specifying source or sink @param[out] return the subgraph (source or sink) and the invisible node needed to make the subgraphs allign """ current_index = cu.get_non_rep_nuber() invis_node = type + '_invis' + str(current_index) sub_graph = Digraph(name='cluster_' + str(current_index)) sub_graph.attr( 'graph', label='', style='invis', ) sub_graph.attr('node') sub_graph.node(invis_node, style='invis', shape='point') return sub_graph, invis_node
def create_ep_img(ep_type): """Creates the endpoint image. Args: ep_type: specifying source or sink. Returns: The subgraph (source or sink) and the invisible node needed to make the subgraphs align. """ current_index = cu.get_non_rep_nuber() invis_node = ep_type + '_invis' + str(current_index) sub_graph = Digraph(name='cluster_' + str(current_index)) sub_graph.attr( 'graph', label='', style='invis', ) sub_graph.attr('node') sub_graph.node(invis_node, style='invis', shape='point') return sub_graph, invis_node
def create_graph(endpoints, transforms, operators, proc, detailed_tooltip=False): """ @brief Create the graph provided the graph details @param[in] endpoints containing the endpoint details @param[in] transform containing the edge details for graph @param[in] processor number being analysed @param[in] detailed_tooltip If true, the tooltip will contain a lot more information. """ current_proc = proc graph_dict = create_graph_dict(endpoints, operators) main_graph = Digraph(format='svg') main_graph.attr('graph', compound='true', fontname="Verdana", rankdir='LR', href='#Graph', tooltip='Graph') for cluster_name in graph_dict: # source endpoint subgraph configuration source, source_invis = create_ep_img('source') # sink endpoint subgraph configuration sink, sink_invis = create_ep_img('sink') contains_source = False contains_sink = False for ep_id, details in graph_dict[cluster_name][ELEMENTS].iteritems(): if details[DIRECTION] == 'SOURCE': # add source nodes contains_source = True add_ep_img(ep_id, details, source, details[EP_TITLE], details[ALL_DETAILS], current_proc, detailed_tooltip) elif details[DIRECTION] == 'SINK': # add sink nodes contains_sink = True add_ep_img(ep_id, details, sink, details[EP_TITLE], details[ALL_DETAILS], current_proc, detailed_tooltip) else: raise Exception("Direction not supported!") # configure operator subgraph if not graph_dict[cluster_name][IS_OPERATOR]: if contains_source: cap1 = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) # configure operator source graph attributes cap1.attr('graph', label=cluster_name + ' source', style='filled', fillcolor='gold', color='black', tooltip=cluster_name) cap1.subgraph(source) main_graph.subgraph(cap1) if contains_sink: cap2 = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) # configure operator sink graph attributes cap2.attr('graph', label=cluster_name + ' sink', style='filled', fillcolor='gold', color='black', tooltip=cluster_name) cap2.subgraph(sink) main_graph.subgraph(cap2) else: op_name = cluster_name.split(' ')[0] op_id = cluster_name.split(' ')[1] op_num = str(hex(((int(op_id, 16) & STREAM_EP_OPID_MASK) >> 6))) cap = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) # configure operator attributes href = '#%sOperator%s,ep_op_id%s,%s' % ( (current_proc + '_', op_num, op_id, op_name)) tooltip = get_operator_tooltip( cluster_name, graph_dict[cluster_name][ALL_DETAILS], detailed_tooltip) cap.attr('graph', label=cluster_name, style='filled', href=href, fillcolor='lightblue3', color='black', tooltip=tooltip) cap.subgraph(source) cap.subgraph(sink) main_graph.edge(sink_invis, source_invis, style='invis') # add operator subgraph to main graph main_graph.subgraph(cap) # make connections between endpoints for transform in transforms: tooltip = get_transform_tooltip(transform, detailed_tooltip) main_graph.edge("0x%04x" % (transform.source.id), "0x%04x" % (transform.sink.id), labeltooltip=tooltip, label=str(100 * transform.cbuffer.amt_data / (transform.cbuffer.buffer_size - 1)) + "%%\\n%d\\n0x%04x" % (transform.cbuffer.buffer_size - 1, transform.id), href="#" + current_proc + "_" + transform.title_str.replace(" ", "")) return main_graph
def create_legend(): """ @Bbrief create legend for the graph image @param[out] legend Digraph """ leg = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) leg.attr('graph', tooltip='legend', href='#Legend', label='Legend', rankdir='LR', title='Legend', labelloc='t') # create real endpoint cluster leg_real_clust = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) leg_real_clust.attr('graph', label='<Real endpoint cluster name>', style='filled', fillcolor='gold', color='black') leg_real_clust_source, real_source_invis = create_ep_img('source') leg_real_clust_sink, real_sink_invis = create_ep_img('sink') leg_real_clust_source.node('real_ep_source_id', shape='rectangle', label='<real endpoint source id>', height='0.01', color='red', style='filled') leg_real_clust_sink.node('real_ep_sink_id', shape='rectangle', label='<real endpoint sink id>', height='0.01', color='red', style='filled') leg_real_clust.edge(real_sink_invis, real_source_invis, style='invis') leg_real_clust.subgraph(leg_real_clust_source) leg_real_clust.subgraph(leg_real_clust_sink) leg.subgraph(leg_real_clust) # create operator cluster leg_op_clust_params = { 'style': 'filled', 'height': '0.01', 'shape': 'rectangle' } leg_op_clust = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) leg_op_clust.attr('graph', label='<Operator Name>', style='filled', fillcolor='lightblue3', color='black', title='Operator') leg_op_clust_source, _ = create_ep_img('source') leg_op_clust_sink, _ = create_ep_img('sink') leg_op_clust_source.node( 'op_source', color='chartreuse1', label='<source terminal number>\\n <source endpoint id>', **leg_op_clust_params) leg_op_clust_sink.node( 'op_sink', color='cyan4', label='<sink terminal number>\\n <sink endpoint id>', **leg_op_clust_params) leg_op_clust.edge('op_sink', 'op_source', style='invis') leg_op_clust_source.node('op_source_real', label='<sink terminal ' 'number>\\n <real source endpoint id>', color='red', **leg_op_clust_params) leg_op_clust_sink.node('op_sink_real', label='<sink terminal ' 'number>\\n <real sink endpoint id>', color='red', **leg_op_clust_params) leg_op_clust.edge('op_sink_real', 'op_source_real', style='invis') leg_op_clust.subgraph(leg_op_clust_source) leg_op_clust.subgraph(leg_op_clust_sink) # create edge between real endpoint source and sink operator endpoint leg.edge('real_ep_source_id', 'op_sink', label='<percentage buffer ' 'filled>\n<total buffer size>\n<terminal id>') leg.subgraph(leg_op_clust) return leg
def create_graph(endpoints, transforms, operators, proc): """Create the graph provided the graph details. Args: endpoints: Containing the endpoint details. transforms: Containing the edge details for graph. operators proc: Number being analysed. """ current_proc = proc graph_dict = create_graph_dict(endpoints, operators) main_graph = Digraph(format='svg') main_graph.attr('graph', compound='true', fontname="Verdana", rankdir='LR', href='#Graph', tooltip='Graph') for cluster_name in graph_dict: # source endpoint subgraph configuration source, source_invis = create_ep_img('source') # sink endpoint subgraph configuration sink, sink_invis = create_ep_img('sink') contains_source = False contains_sink = False for ep_id, details in graph_dict[cluster_name][ELEMENTS].items(): if details[DIRECTION] == 'SOURCE': # add source nodes contains_source = True add_ep_img(ep_id, details, source, details[EP_TITLE], current_proc) elif details[DIRECTION] == 'SINK': # add sink nodes contains_sink = True add_ep_img(ep_id, details, sink, details[EP_TITLE], current_proc) else: raise Exception("Direction not supported!") # configure operator subgraph if not graph_dict[cluster_name][IS_OPERATOR]: if contains_source: cap1 = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) # configure operator source graph attributes cap1.attr('graph', label=cluster_name + ' source', style='filled', fillcolor='gold', color='black', tooltip=cluster_name) cap1.subgraph(source) main_graph.subgraph(cap1) if contains_sink: cap2 = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) # configure operator sink graph attributes cap2.attr('graph', label=cluster_name + ' sink', style='filled', fillcolor='gold', color='black', tooltip=cluster_name) cap2.subgraph(sink) main_graph.subgraph(cap2) else: op_name = cluster_name.split(' ')[0] op_id = cluster_name.split(' ')[1] op_num = str(hex(((int(op_id, 16) & STREAM_EP_OPID_MASK) >> 6))) cap = Digraph(name='cluster_' + str(cu.get_non_rep_nuber())) # configure operator attributes href = '#%sOperator%s,ep_op_id%s,%s' % ( (current_proc + '_', op_num, op_id, op_name)) tooltip = cluster_name cap.attr('graph', label=cluster_name, style='filled', href=href, fillcolor='lightblue3', color='black', tooltip=tooltip) cap.subgraph(source) cap.subgraph(sink) main_graph.edge(sink_invis, source_invis, style='invis') # add operator subgraph to main graph main_graph.subgraph(cap) # make connections between endpoints for transform in transforms: tooltip = get_transform_tooltip(transform) # The available space in circular buffers are always one unit # less than the total size in order to avoid having read and write # pointers pointing to the same location. available_size = transform.cbuffer.buffer_size - 1 usage = available_size - transform.cbuffer.av_space usage_percentage_text = "{:0.2f}%".format(usage * 100 / float(available_size)) usage_text = '{}/{}'.format(usage, available_size) main_graph.edge("0x%04x" % (transform.source.id), "0x%04x" % (transform.sink.id), labeltooltip=tooltip, label='{}\n{}\n0x{:04x}'.format( usage_percentage_text, usage_text, transform.id, ), href="#" + current_proc + "_" + transform.title_str.replace(" ", "")) return main_graph