|
|
|
@ -347,9 +347,9 @@ class Circuit: |
|
|
|
stats['__line__'] = len(self.lines) |
|
|
|
stats['__line__'] = len(self.lines) |
|
|
|
for n in self.cells.values(): |
|
|
|
for n in self.cells.values(): |
|
|
|
stats[n.kind] += 1 |
|
|
|
stats[n.kind] += 1 |
|
|
|
if 'dff' in n.kind.lower(): stats['__dff__'] += 1 |
|
|
|
if tlib.is_dff(n.kind): stats['__dff__'] += 1 |
|
|
|
elif 'latch' in n.kind.lower(): stats['__latch__'] += 1 |
|
|
|
elif tlib.is_latch(n.kind): stats['__latch__'] += 1 |
|
|
|
elif 'put' not in n.kind.lower(): stats['__comb__'] += 1 # no input or output |
|
|
|
elif 'put' not in n.kind.lower(): stats['__comb__'] += 1 # don't count input or output towards comb |
|
|
|
stats['__seq__'] = stats['__dff__'] + stats['__latch__'] |
|
|
|
stats['__seq__'] = stats['__dff__'] + stats['__latch__'] |
|
|
|
return dict(stats) |
|
|
|
return dict(stats) |
|
|
|
|
|
|
|
|
|
|
|
@ -581,24 +581,23 @@ class Circuit: |
|
|
|
if line is not None: |
|
|
|
if line is not None: |
|
|
|
yield line |
|
|
|
yield line |
|
|
|
|
|
|
|
|
|
|
|
def reversed_topological_order(self): |
|
|
|
def reversed_topological_order(self, tlib: 'TechLib'): # type: ignore |
|
|
|
"""Generator function to iterate over all nodes in reversed topological order. |
|
|
|
"""Generator function to iterate over all nodes in reversed topological order. |
|
|
|
|
|
|
|
|
|
|
|
Nodes without output lines and nodes whose :py:attr:`Node.kind` contains the |
|
|
|
Nodes without output lines and sequential nodes (flip-flops, latches) are yielded first. |
|
|
|
substrings 'dff' or 'latch' are yielded first. |
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
visit_count = [0] * len(self.nodes) |
|
|
|
visit_count = [0] * len(self.nodes) |
|
|
|
queue = deque(n for n in self.nodes if len(n.outs) == 0 or 'dff' in n.kind.lower() or 'latch' in n.kind.lower()) |
|
|
|
queue = deque(n for n in self.nodes if len(n.outs) == 0 or tlib.is_dff(n.kind) or tlib.is_latch(n.kind)) |
|
|
|
while len(queue) > 0: |
|
|
|
while len(queue) > 0: |
|
|
|
n = queue.popleft() |
|
|
|
n = queue.popleft() |
|
|
|
for line in n.ins: |
|
|
|
for line in n.ins: |
|
|
|
pred = line.driver |
|
|
|
pred = line.driver |
|
|
|
visit_count[pred] += 1 |
|
|
|
visit_count[pred] += 1 |
|
|
|
if visit_count[pred] == len(pred.outs) and 'dff' not in pred.kind.lower() and 'latch' not in pred.kind.lower(): |
|
|
|
if visit_count[pred] == len(pred.outs) and not tlib.is_dff(pred.kind) and not tlib.is_latch(pred.kind): |
|
|
|
queue.append(pred) |
|
|
|
queue.append(pred) |
|
|
|
yield n |
|
|
|
yield n |
|
|
|
|
|
|
|
|
|
|
|
def fanin(self, origin_nodes): |
|
|
|
def fanin(self, origin_nodes, tlib: 'TechLib'): # type: ignore |
|
|
|
"""Generator function to iterate over the fan-in cone of a given list of origin nodes. |
|
|
|
"""Generator function to iterate over the fan-in cone of a given list of origin nodes. |
|
|
|
|
|
|
|
|
|
|
|
Nodes are yielded in reversed topological order. |
|
|
|
Nodes are yielded in reversed topological order. |
|
|
|
@ -606,11 +605,10 @@ class Circuit: |
|
|
|
marks = [False] * len(self.nodes) |
|
|
|
marks = [False] * len(self.nodes) |
|
|
|
for n in origin_nodes: |
|
|
|
for n in origin_nodes: |
|
|
|
marks[n] = True |
|
|
|
marks[n] = True |
|
|
|
for n in self.reversed_topological_order(): |
|
|
|
for n in self.reversed_topological_order(tlib): |
|
|
|
if not marks[n]: |
|
|
|
if not marks[n]: |
|
|
|
for line in n.outs: |
|
|
|
for line in n.outs.without_nones(): |
|
|
|
if line is not None: |
|
|
|
marks[n] |= marks[line.reader] |
|
|
|
marks[n] |= marks[line.reader] |
|
|
|
|
|
|
|
if marks[n]: |
|
|
|
if marks[n]: |
|
|
|
yield n |
|
|
|
yield n |
|
|
|
|
|
|
|
|
|
|
|
|