Browse Source

more robust matching and assign processing

devel
Stefan Holst 8 months ago
parent
commit
d2357859f6
  1. 2
      src/kyupy/circuit.py
  2. 4
      src/kyupy/sdf.py
  3. 61
      src/kyupy/verilog.py

2
src/kyupy/circuit.py

@ -312,7 +312,7 @@ class Circuit: @@ -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]:

4
src/kyupy/sdf.py

@ -107,8 +107,8 @@ class DelayFile: @@ -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]

61
src/kyupy/verilog.py

@ -123,6 +123,9 @@ class VerilogTransformer(Transformer): @@ -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): @@ -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"):

Loading…
Cancel
Save