|
|
@ -123,6 +123,9 @@ class VerilogTransformer(Transformer): |
|
|
|
assignments = [] |
|
|
|
assignments = [] |
|
|
|
for stmt in args[2:]: # pass 1: instantiate cells and driven signals |
|
|
|
for stmt in args[2:]: # pass 1: instantiate cells and driven signals |
|
|
|
if isinstance(stmt, Instantiation): |
|
|
|
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) |
|
|
|
n = Node(c, stmt.name, kind=stmt.type) |
|
|
|
for p, s in stmt.pins.items(): |
|
|
|
for p, s in stmt.pins.items(): |
|
|
|
if self.tlib.pin_is_output(n.kind, p): |
|
|
|
if self.tlib.pin_is_output(n.kind, p): |
|
|
@ -141,35 +144,41 @@ class VerilogTransformer(Transformer): |
|
|
|
c.io_nodes[positions[name]] = n |
|
|
|
c.io_nodes[positions[name]] = n |
|
|
|
if sd.kind == 'input': |
|
|
|
if sd.kind == 'input': |
|
|
|
Line(c, n, Node(c, name)) |
|
|
|
Line(c, n, Node(c, name)) |
|
|
|
for target, source in assignments: # pass 1.5: process signal assignments |
|
|
|
while len(assignments) > 0: |
|
|
|
target_sigs = [] |
|
|
|
more_assignments = [] |
|
|
|
if not isinstance(target, list): target = [target] |
|
|
|
for target, source in assignments: # pass 1.5: process signal assignments |
|
|
|
for s in target: |
|
|
|
target_sigs = [] |
|
|
|
if s in sig_decls: |
|
|
|
if not isinstance(target, list): target = [target] |
|
|
|
target_sigs += sig_decls[s].names |
|
|
|
for s in target: |
|
|
|
else: |
|
|
|
if s in sig_decls: |
|
|
|
target_sigs.append(s) |
|
|
|
target_sigs += sig_decls[s].names |
|
|
|
source_sigs = [] |
|
|
|
else: |
|
|
|
if not isinstance(source, list): source = [source] |
|
|
|
target_sigs.append(s) |
|
|
|
for s in source: |
|
|
|
source_sigs = [] |
|
|
|
if s in sig_decls: |
|
|
|
if not isinstance(source, list): source = [source] |
|
|
|
source_sigs += sig_decls[s].names |
|
|
|
for s in source: |
|
|
|
else: |
|
|
|
if s in sig_decls: |
|
|
|
source_sigs.append(s) |
|
|
|
source_sigs += sig_decls[s].names |
|
|
|
for t, s in zip(target_sigs, source_sigs): |
|
|
|
else: |
|
|
|
if t in c.forks: |
|
|
|
source_sigs.append(s) |
|
|
|
assert s not in c.forks, 'assignment between two driven signals' |
|
|
|
for t, s in zip(target_sigs, source_sigs): |
|
|
|
Line(c, c.forks[t], Node(c, s)) |
|
|
|
if t in c.forks: |
|
|
|
elif s in c.forks: |
|
|
|
assert s not in c.forks, 'assignment between two driven signals' |
|
|
|
assert t not in c.forks, 'assignment between two driven signals' |
|
|
|
Line(c, c.forks[t], Node(c, s)) |
|
|
|
Line(c, c.forks[s], Node(c, t)) |
|
|
|
elif s in c.forks: |
|
|
|
elif s.startswith("1'b"): |
|
|
|
assert t not in c.forks, 'assignment between two driven signals' |
|
|
|
cnode = Node(c, f'__const{s[3]}_{const_count}__', f'__const{s[3]}__') |
|
|
|
Line(c, c.forks[s], Node(c, t)) |
|
|
|
const_count += 1 |
|
|
|
elif s.startswith("1'b"): |
|
|
|
Line(c, cnode, Node(c, t)) |
|
|
|
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 |
|
|
|
for stmt in args[2:]: # pass 2: connect signals to readers |
|
|
|
if isinstance(stmt, Instantiation): |
|
|
|
if isinstance(stmt, Instantiation): |
|
|
|
for p, s in stmt.pins.items(): |
|
|
|
for p, s in stmt.pins.items(): |
|
|
|
|
|
|
|
if stmt.name not in c.cells: continue |
|
|
|
n = c.cells[stmt.name] |
|
|
|
n = c.cells[stmt.name] |
|
|
|
if self.tlib.pin_is_output(n.kind, p): continue |
|
|
|
if self.tlib.pin_is_output(n.kind, p): continue |
|
|
|
if s.startswith("1'b"): |
|
|
|
if s.startswith("1'b"): |
|
|
|