flow/network: replace NetworkX MultiDiGraph with simple implementation
authorRobert Jordens <jordens@gmail.com>
Sun, 7 Sep 2014 06:09:52 +0000 (00:09 -0600)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sun, 7 Sep 2014 08:48:46 +0000 (16:48 +0800)
migen/flow/network.py

index 62900af8962f205eb2d2da792c9246885691ffd8..2064f909512ba6716069a10a0a5fce02b1676dee 100644 (file)
@@ -1,4 +1,4 @@
-from networkx import MultiDiGraph
+from collections import defaultdict
 
 from migen.fhdl.std import *
 from migen.genlib.misc import optree
@@ -26,7 +26,70 @@ class AbstractActor:
                r += ">"
                return r
 
-# TODO: rewrite this without networkx and without non-determinism
+class MultiDiGraph:
+       def __init__(self):
+               self.edges = defaultdict(list)
+               self.incoming = defaultdict(set)
+               self.outgoing = defaultdict(set)
+               self.nodes = set()
+
+       def add_edge(self, a, b, **edge):
+               self.edges[(a, b)].append(edge)
+               self.incoming[b].add(a)
+               self.outgoing[a].add(b)
+               self.nodes |= {a, b}
+
+       def __iter__(self):
+               return iter(self.nodes)
+
+       def __len__(self):
+               return len(self.nodes)
+
+       def edges_iter(self, data=True):
+               assert data
+               for (a, b), edges in self.edges.items():
+                       for edge in edges:
+                               yield a, b, edge
+
+       def get_edge_data(self, a, b):
+               return dict(enumerate(self.edges[(a, b)]))
+
+       def add_node(self, node):
+               self.nodes.add(node)
+
+       def remove_node(self, node):
+               for i in self.incoming.pop(node):
+                       del self.edges[(i, node)]
+                       self.outgoing[i].remove(node)
+               for i in self.outgoing.pop(node):
+                       del self.edges[(node, i)]
+                       self.incoming[i].remove(node)
+               self.nodes.remove(node)
+
+       def remove_edge(self, a, b, key):
+               e = self.edges[(a, b)]
+               del e[key]
+               if not e:
+                       self.incoming[b].remove(a)
+                       self.outgoing[a].remove(b)
+
+       def in_edges(self, sink, data=True):
+               assert data
+               e = []
+               for source in self.incoming[sink]:
+                       for edge in self.edges[(source, sink)]:
+                               e.append((source, sink, edge))
+               return e
+
+       def out_edges(self, source, data=True):
+               assert data
+               e = []
+               for sink in self.outgoing[source]:
+                       for edge in self.edges[(source, sink)]:
+                               e.append((source, sink, edge))
+               return e
+
+# TODO: rewrite this without non-determinism
 class DataFlowGraph(MultiDiGraph):
        def __init__(self):
                MultiDiGraph.__init__(self)
@@ -76,7 +139,7 @@ class DataFlowGraph(MultiDiGraph):
                inst = actor.create_instance()
                self.abstract_busy_signals[id(inst)] = actor.busy
                self.replace_actor(actor, inst)
-       
+
        # Returns a dictionary
        #   source -> [sink1, ..., sinkn]
        # source element is a (node, endpoint) pair.
@@ -91,7 +154,7 @@ class DataFlowGraph(MultiDiGraph):
                        else:
                                d[el_src] = [el_dst]
                return d
-       
+
        # Returns a dictionary
        #   sink -> [source1, ... sourcen]
        # sink element is a (node, endpoint) pair.