From d2357859f6e6662fbf48c2826489ad9154ac4eb1 Mon Sep 17 00:00:00 2001 From: Stefan Holst Date: Mon, 15 Apr 2024 17:01:11 +0900 Subject: [PATCH] more robust matching and assign processing --- src/kyupy/circuit.py | 2 +- src/kyupy/sdf.py | 4 +-- src/kyupy/verilog.py | 61 +++++++++++++++++++++++++------------------- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/kyupy/circuit.py b/src/kyupy/circuit.py index aaad109..e387ffc 100644 --- a/src/kyupy/circuit.py +++ b/src/kyupy/circuit.py @@ -312,7 +312,7 @@ class Circuit: def _locs(self, prefix, nodes): d_top = dict() for i, n in enumerate(nodes): - if m := re.match(fr'({prefix}.*?)((?:[\d_\[\]])*$)', n.name): + if m := re.match(fr'({re.escape(prefix)}.*?)((?:[\d_\[\]])*$)', n.name): path = [m[1]] + [int(v) for v in re.split(r'[_\[\]]+', m[2]) if len(v) > 0] d = d_top for j in path[:-1]: diff --git a/src/kyupy/sdf.py b/src/kyupy/sdf.py index 32ff2be..5314efb 100644 --- a/src/kyupy/sdf.py +++ b/src/kyupy/sdf.py @@ -107,8 +107,8 @@ class DelayFile: for n1, n2, *delvals in self._interconnects: delvals = [d if len(d) > 0 else [0, 0, 0] for d in delvals] if max(max(delvals)) == 0: continue - cn1, pn1 = n1.split('/') if '/' in n1 else (n1, None) - cn2, pn2 = n2.split('/') if '/' in n2 else (n2, None) + cn1, pn1 = (n1, None) if (slash := n1.rfind('/')) < 0 else (n1[:slash], n1[slash+1:]) + cn2, pn2 = (n2, None) if (slash := n2.rfind('/')) < 0 else (n2[:slash], n2[slash+1:]) cn1 = cn1.replace('\\','') cn2 = cn2.replace('\\','') c1, c2 = circuit.cells[cn1], circuit.cells[cn2] diff --git a/src/kyupy/verilog.py b/src/kyupy/verilog.py index 1c6a0d1..0938a81 100644 --- a/src/kyupy/verilog.py +++ b/src/kyupy/verilog.py @@ -123,6 +123,9 @@ class VerilogTransformer(Transformer): assignments = [] for stmt in args[2:]: # pass 1: instantiate cells and driven signals if isinstance(stmt, Instantiation): + if stmt.type not in self.tlib.cells: + log.warn(f'Ignoring cell of unknown kind "{stmt.type}"') + continue n = Node(c, stmt.name, kind=stmt.type) for p, s in stmt.pins.items(): if self.tlib.pin_is_output(n.kind, p): @@ -141,35 +144,41 @@ class VerilogTransformer(Transformer): c.io_nodes[positions[name]] = n if sd.kind == 'input': Line(c, n, Node(c, name)) - for target, source in assignments: # pass 1.5: process signal assignments - target_sigs = [] - if not isinstance(target, list): target = [target] - for s in target: - if s in sig_decls: - target_sigs += sig_decls[s].names - else: - target_sigs.append(s) - source_sigs = [] - if not isinstance(source, list): source = [source] - for s in source: - if s in sig_decls: - source_sigs += sig_decls[s].names - else: - source_sigs.append(s) - for t, s in zip(target_sigs, source_sigs): - if t in c.forks: - assert s not in c.forks, 'assignment between two driven signals' - Line(c, c.forks[t], Node(c, s)) - elif s in c.forks: - assert t not in c.forks, 'assignment between two driven signals' - Line(c, c.forks[s], Node(c, t)) - elif s.startswith("1'b"): - cnode = Node(c, f'__const{s[3]}_{const_count}__', f'__const{s[3]}__') - const_count += 1 - Line(c, cnode, Node(c, t)) + while len(assignments) > 0: + more_assignments = [] + for target, source in assignments: # pass 1.5: process signal assignments + target_sigs = [] + if not isinstance(target, list): target = [target] + for s in target: + if s in sig_decls: + target_sigs += sig_decls[s].names + else: + target_sigs.append(s) + source_sigs = [] + if not isinstance(source, list): source = [source] + for s in source: + if s in sig_decls: + source_sigs += sig_decls[s].names + else: + source_sigs.append(s) + for t, s in zip(target_sigs, source_sigs): + if t in c.forks: + assert s not in c.forks, 'assignment between two driven signals' + Line(c, c.forks[t], Node(c, s)) + elif s in c.forks: + assert t not in c.forks, 'assignment between two driven signals' + Line(c, c.forks[s], Node(c, t)) + elif s.startswith("1'b"): + cnode = Node(c, f'__const{s[3]}_{const_count}__', f'__const{s[3]}__') + const_count += 1 + Line(c, cnode, Node(c, t)) + else: + more_assignments.append((target, source)) + assignments = more_assignments for stmt in args[2:]: # pass 2: connect signals to readers if isinstance(stmt, Instantiation): for p, s in stmt.pins.items(): + if stmt.name not in c.cells: continue n = c.cells[stmt.name] if self.tlib.pin_is_output(n.kind, p): continue if s.startswith("1'b"):