From d3897246c59d0f441c33327168962aafd520fef6 Mon Sep 17 00:00:00 2001 From: Stefan Holst Date: Sun, 9 Jul 2023 19:04:22 +0900 Subject: [PATCH] move resolving cells to circuit, more doc --- src/kyupy/circuit.py | 28 +++++++++++++++++++++++----- src/kyupy/sdf.py | 7 +++++-- src/kyupy/techlib.py | 5 ----- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/kyupy/circuit.py b/src/kyupy/circuit.py index 0b8da39..fbea3c5 100644 --- a/src/kyupy/circuit.py +++ b/src/kyupy/circuit.py @@ -314,6 +314,16 @@ class Circuit: def get_or_add_fork(self, name): return self.forks[name] if name in self.forks else Node(self, name) + def remove_dangling_nodes(self, root_node:Node): + if len([l for l in root_node.outs if l is not None]) > 0: return + lines = [l for l in root_node.ins if l is not None] + drivers = [l.driver for l in lines] + root_node.remove() + for l in lines: + l.remove() + for d in drivers: + self.remove_dangling_nodes(d) + def eliminate_1to1_forks(self): """Removes all forks that drive only one node. @@ -356,8 +366,6 @@ class Circuit: node_out_lines = list(node.outs) + [None] * (len(impl_out_lines)-len(node.outs)) assert len(node_in_lines) == len(impl_in_lines) assert len(node_out_lines) == len(impl_out_lines) - in_lines_map = dict(zip(impl_in_lines, node_in_lines)) - out_lines_map = dict(zip(impl_out_lines, node_out_lines)) node.remove() node_map = dict() ios = set(impl.io_nodes) @@ -370,13 +378,16 @@ class Circuit: for l in impl.lines: # add all internal lines to main circuit if l.reader in node_map and l.driver in node_map: Line(self, (node_map[l.driver], l.driver_pin), (node_map[l.reader], l.reader_pin)) - for l, ll in in_lines_map.items(): # connect inputs + for l, ll in zip(impl_in_lines, node_in_lines): # connect inputs if ll is None: continue ll.reader = node_map[l.reader] ll.reader_pin = l.reader_pin ll.reader.ins[ll.reader_pin] = ll - for l, ll in out_lines_map.items(): # connect outputs - if ll is None: continue + for l, ll in zip(impl_out_lines, node_out_lines): # connect outputs + if ll is None: + if l.driver in node_map: + self.remove_dangling_nodes(node_map[l.driver]) + continue if len(l.reader.outs) > 0: # output is also read by impl. circuit, connect to fork. ll.driver = node_map[l.reader] ll.driver_pin = len(l.reader.outs) @@ -385,6 +396,13 @@ class Circuit: ll.driver_pin = l.driver_pin ll.driver.outs[ll.driver_pin] = ll + def resolve_tlib_cells(self, tlib): + """Substitute all technology library cells with kyupy native simulation primitives. + """ + for n in list(self.nodes): + if n.kind in tlib.cells:# and 'DFF' not in n.kind and 'LATCH' not in n.kind: + self.substitute(n, tlib.cells[n.kind][0]) + def copy(self): """Returns a deep copy of the circuit. """ diff --git a/src/kyupy/sdf.py b/src/kyupy/sdf.py index 9e7e1b1..0346adf 100644 --- a/src/kyupy/sdf.py +++ b/src/kyupy/sdf.py @@ -40,8 +40,11 @@ class DelayFile: All IOPATH delays for a node ``n`` are annotated to the line connected to the input pin specified in the IOPATH. - Only supports two delvals per delval_list. First delval is rising/posedge, second delval is falling/negedge - transition at the output of the IOPATH (SDF spec, pp. 3-17). + Limited support of SDF spec: + * ABSOLUTE delay values only + * two delvals per delval_list. First is rising/posedge, second is falling/negedge + transition at the output of the IOPATH (SDF spec, pp. 3-17). + * PATHPULSE declarations are ignored. * Axis 0: dataset (usually 3 datasets per SDF-file) * Axis 1: line index (e.g. ``n.ins[0]``, ``n.ins[1]``) diff --git a/src/kyupy/techlib.py b/src/kyupy/techlib.py index 95d23d9..8ab9939 100644 --- a/src/kyupy/techlib.py +++ b/src/kyupy/techlib.py @@ -128,11 +128,6 @@ class TechLibNew: def pin_is_output(self, kind, pin): return self.cells[kind][1][pin][1] - def resolve(self, circuit): - for n in list(circuit.nodes): - if n.kind in self.cells: - circuit.substitute(n, self.cells[n.kind][0]) - NANGATE = TechLibNew(r""" FILLCELL_X{1,2,4,8,16,32} ;