From 1b8588e37f60d1ff27573254d87c9607fac3227f Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson <raska119@student.liu.se> Date: Thu, 7 May 2020 10:56:47 +0200 Subject: [PATCH] Visualizing PG looks good to me. Tests for this feature will not be tested alongside every other test since they only display a graph and do not test any logics. --- b_asic/signal_flow_graph.py | 25 +++++++++++++++++++++++++ setup.py | 3 ++- test/test_sfg.py | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py index 79b539cc..d51f13b4 100644 --- a/b_asic/signal_flow_graph.py +++ b/b_asic/signal_flow_graph.py @@ -9,6 +9,7 @@ from collections import defaultdict, deque from io import StringIO from queue import PriorityQueue import itertools +from graphviz import Digraph from b_asic.port import SignalSourceProvider, OutputPort from b_asic.operation import Operation, AbstractOperation, MutableOutputMap, MutableRegisterMap @@ -608,6 +609,30 @@ class SFG(AbstractOperation): return precedence_list + def show_precedence_graph(self) -> None: + p_list = self.get_precedence_list() + pg = Digraph() + pg.attr(rankdir = 'LR') + + # Creates nodes for each output port in the precedence list + for i in range(len(p_list)): + ports = p_list[i] + with pg.subgraph(name='cluster_' + str(i)) as sub: + sub.attr(label='N' + str(i + 1)) + for port in ports: + sub.node(port.operation.graph_id + '.' + str(port.index)) + # Creates edges for each output port and creates nodes for each operation and edges for them as well + for i in range(len(p_list)): + ports = p_list[i] + for port in ports: + for signal in port.signals: + pg.edge(port.operation.graph_id + '.' + str(port.index), signal.destination.operation.graph_id) + pg.node(signal.destination.operation.graph_id, shape = 'square') + pg.edge(port.operation.graph_id, port.operation.graph_id + '.' + str(port.index)) + pg.node(port.operation.graph_id, shape = 'square') + + pg.view() + def print_precedence_graph(self) -> None: """Prints a representation of the SFG's precedence list to the standard out. If the precedence list already has been calculated then it uses the cached version, diff --git a/setup.py b/setup.py index 43d55d40..62ac6af2 100644 --- a/setup.py +++ b/setup.py @@ -71,7 +71,8 @@ setuptools.setup( install_requires = [ "pybind11>=2.3.0", "numpy", - "install_qt_binding" + "install_qt_binding", + "graphviz" ], packages = ["b_asic"], ext_modules = [CMakeExtension("b_asic")], diff --git a/test/test_sfg.py b/test/test_sfg.py index 6f0a7ec4..a27b404e 100644 --- a/test/test_sfg.py +++ b/test/test_sfg.py @@ -691,12 +691,12 @@ class TestConnectExternalSignalsToComponentsMultipleComp: out1.input(0).connect(sub1, "S7") test_sfg = SFG(inputs=[inp1, inp2, inp3, inp4], outputs=[out1]) + assert test_sfg.evaluate(1, 2, 3, 4) == 16 sfg1.connect_external_signals_to_components() assert test_sfg.evaluate(1, 2, 3, 4) == 16 assert not test_sfg.connect_external_signals_to_components() - class TestTopologicalOrderOperations: def test_feedback_sfg(self, simple_filter): topological_order = simple_filter.get_operations_topological_order() -- GitLab