Browse Source

interface -> io_nodes, io_loc fix

devel
Stefan Holst 2 years ago
parent
commit
f0dac36ac7
  1. 16
      Demo.ipynb
  2. 2
      src/kyupy/bench.py
  3. 43
      src/kyupy/circuit.py
  4. 2
      src/kyupy/logic_sim.py
  5. 7
      src/kyupy/schedule.py
  6. 2
      src/kyupy/stil.py
  7. 2
      src/kyupy/verilog.py
  8. 2
      src/kyupy/wave_sim.py
  9. 2
      src/kyupy/wave_sim_4ig.py
  10. 2
      tests/test_bench.py
  11. 6
      tests/test_circuit.py

16
Demo.ipynb

@ -115,6 +115,7 @@ @@ -115,6 +115,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
@ -125,7 +126,7 @@ @@ -125,7 +126,7 @@
"\n",
"A line in the circuit has a unique ID, a driver node and a receiver node. The connections in the dump show the direction (\">\" for output, \"<\" for input) and the line-ID. For example in `mycircuit`: Node-0 has one output connected to Line-1, and this Line-1 is connected to the input of Node-5.\n",
"\n",
"The `interface` is the list of nodes forming the ports (inputs and outputs):"
"The `io_nodes` is the list of nodes forming the ports (inputs and outputs):"
]
},
{
@ -149,7 +150,7 @@ @@ -149,7 +150,7 @@
}
],
"source": [
"mycircuit.interface"
"mycircuit.io_nodes"
]
},
{
@ -1326,9 +1327,9 @@ @@ -1326,9 +1327,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "worker",
"display_name": "Python 3",
"language": "python",
"name": "worker"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
@ -1340,7 +1341,12 @@ @@ -1340,7 +1341,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.13"
"version": "3.6.8"
},
"vscode": {
"interpreter": {
"hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
}
}
},
"nbformat": 4,

2
src/kyupy/bench.py

@ -23,7 +23,7 @@ class BenchTransformer(Transformer): @@ -23,7 +23,7 @@ class BenchTransformer(Transformer):
def parameters(self, args): return [self.c.get_or_add_fork(name) for name in args]
def interface(self, args): self.c.interface.extend(args[0])
def interface(self, args): self.c.io_nodes.extend(args[0])
def assignment(self, args):
name, cell_type, drivers = args

43
src/kyupy/circuit.py

@ -5,7 +5,7 @@ A node is an instance of class :class:`Node`, @@ -5,7 +5,7 @@ A node is an instance of class :class:`Node`,
and a line is an instance of class :class:`Line`.
"""
from collections import deque
from collections import deque, defaultdict
import re
@ -203,7 +203,7 @@ class Circuit: @@ -203,7 +203,7 @@ class Circuit:
to enforce consecutiveness.
A subset of nodes can be designated as primary input- or output-ports of the circuit.
This is done by adding them to the :py:attr:`interface` list.
This is done by adding them to the :py:attr:`io_nodes` list.
"""
def __init__(self, name=None):
self.name = name
@ -219,13 +219,13 @@ class Circuit: @@ -219,13 +219,13 @@ class Circuit:
The position of a line in this list equals its index :code:`self.lines[42].index == 42`.
"""
self.interface = GrowingList()
self.io_nodes = GrowingList()
"""A list of nodes that are designated as primary input- or output-ports.
Port-nodes are contained in :py:attr:`nodes` as well as :py:attr:`interface`.
The position of a node in the interface list corresponds to positions of logic values in test vectors.
Port-nodes are contained in :py:attr:`nodes` as well as :py:attr:`io_nodes`.
The position of a node in the io_nodes list corresponds to positions of logic values in test vectors.
The port direction is not stored explicitly.
Usually, nodes in the interface list without any lines in their :py:attr:`Node.ins` list are primary inputs,
Usually, nodes in the io_nodes list without any lines in their :py:attr:`Node.ins` list are primary inputs,
and nodes without any lines in their :py:attr:`Node.outs` list are regarded as primary outputs.
"""
self.cells = {}
@ -248,50 +248,57 @@ class Circuit: @@ -248,50 +248,57 @@ class Circuit:
d = c.forks[line.driver.name] if line.driver.kind == '__fork__' else c.cells[line.driver.name]
r = c.forks[line.reader.name] if line.reader.kind == '__fork__' else c.cells[line.reader.name]
Line(c, (d, line.driver_pin), (r, line.reader_pin))
for node in self.interface:
for node in self.io_nodes:
if node.kind == '__fork__':
n = c.forks[node.name]
else:
n = c.cells[node.name]
c.interface.append(n)
c.io_nodes.append(n)
return c
def __getstate__(self):
nodes = [(node.name, node.kind) for node in self.nodes]
lines = [(line.driver.index, line.driver_pin, line.reader.index, line.reader_pin) for line in self.lines]
interface = [n.index for n in self.interface]
io_nodes = [n.index for n in self.io_nodes]
return {'name': self.name,
'nodes': nodes,
'lines': lines,
'interface': interface }
'io_nodes': io_nodes }
def __setstate__(self, state):
self.name = state['name']
self.nodes = IndexList()
self.lines = IndexList()
self.interface = GrowingList()
self.io_nodes = GrowingList()
self.cells = {}
self.forks = {}
for s in state['nodes']:
Node(self, *s)
for driver, driver_pin, reader, reader_pin in state['lines']:
Line(self, (self.nodes[driver], driver_pin), (self.nodes[reader], reader_pin))
for n in state['interface']:
self.interface.append(self.nodes[n])
for n in state['io_nodes']:
self.io_nodes.append(self.nodes[n])
def __eq__(self, other):
return self.nodes == other.nodes and self.lines == other.lines and self.interface == other.interface
return self.nodes == other.nodes and self.lines == other.lines and self.io_nodes == other.io_nodes
def dump(self):
"""Returns a string representation of the circuit and all its nodes.
"""
header = f'{self.name}({",".join([str(n.index) for n in self.interface])})\n'
header = f'{self.name}({",".join([str(n.index) for n in self.io_nodes])})\n'
return header + '\n'.join([str(n) for n in self.nodes])
def __repr__(self):
name = f' {self.name}' if self.name else ''
return f'<Circuit{name} cells={len(self.cells)} forks={len(self.forks)} ' + \
f'lines={len(self.lines)} ports={len(self.interface)}>'
f'lines={len(self.lines)} ports={len(self.io_nodes)}>'
@property
def cell_counts(self):
counts = defaultdict(int)
for n in self.cells.values():
counts[n.kind] += 1
return counts
def topological_order(self):
"""Generator function to iterate over all nodes in topological order.
@ -375,8 +382,8 @@ class Circuit: @@ -375,8 +382,8 @@ class Circuit:
def io_loc(self, prefix):
d_top = dict()
for i, n in enumerate(list(self.interface) + [n for n in self.nodes if 'dff' in n.kind.lower()]):
if m := re.match(fr'({prefix}.*?)((?:[_\[\]]\d+)*[_\[\]]*$)', n.name):
for i, n in enumerate(list(self.io_nodes) + [n for n in self.nodes if 'dff' in n.kind.lower()]):
if m := re.match(fr'({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]:

2
src/kyupy/logic_sim.py

@ -32,7 +32,7 @@ class LogicSim: @@ -32,7 +32,7 @@ class LogicSim:
nbytes = (sims - 1) // 8 + 1
dffs = [n for n in circuit.nodes if 'dff' in n.kind.lower()]
latches = [n for n in circuit.nodes if 'latch' in n.kind.lower()]
self.interface = list(circuit.interface) + dffs + latches
self.interface = list(circuit.io_nodes) + dffs + latches
self.width = len(self.interface)
"""The number of bits in the circuit state (number of ports + number of state-elements)."""

7
src/kyupy/schedule.py

@ -157,7 +157,7 @@ class Schedule: @@ -157,7 +157,7 @@ class Schedule:
"""
def __init__(self, circuit, strip_forks=False, keep_signals=True, signal_caps=1):
self.circuit = circuit
self.interface = list(circuit.interface) + [n for n in circuit.nodes if 'dff' in n.kind.lower()]
self.interface = list(circuit.io_nodes) + [n for n in circuit.nodes if 'dff' in n.kind.lower()]
if isinstance(signal_caps, int):
signal_caps = [signal_caps] * len(circuit.lines)
@ -303,3 +303,8 @@ class Schedule: @@ -303,3 +303,8 @@ class Schedule:
self.vat[self.ppo_offset + i] = self.vat[n.ins[0]]
self.state_length = h.max_size
from collections import defaultdict
self.prim_counts = defaultdict(int)
names_dict = SimPrim.names()
for op, _, _, _, _, _ in self.ops: self.prim_counts[names_dict[op]] += 1

2
src/kyupy/stil.py

@ -55,7 +55,7 @@ class StilFile: @@ -55,7 +55,7 @@ class StilFile:
capture = dict((k, v.replace('\n', '').replace('N', '-')) for k, v in call.parameters.items())
def _maps(self, c):
interface = list(c.interface) + [n for n in c.nodes if 'DFF' in n.kind]
interface = list(c.io_nodes) + [n for n in c.nodes if 'DFF' in n.kind]
intf_pos = dict((n.name, i) for i, n in enumerate(interface))
pi_map = [intf_pos[n] for n in self.signal_groups['_pi']]
po_map = [intf_pos[n] for n in self.signal_groups['_po']]

2
src/kyupy/verilog.py

@ -96,7 +96,7 @@ class VerilogTransformer(Transformer): @@ -96,7 +96,7 @@ class VerilogTransformer(Transformer):
for name in sd.names:
n = Node(c, name, kind=sd.kind)
if name in positions:
c.interface[positions[name]] = n
c.io_nodes[positions[name]] = n
if sd.kind == 'input':
Line(c, n, Node(c, name))
for s1, s2 in assignments: # pass 1.5: process signal assignments

2
src/kyupy/wave_sim.py

@ -117,7 +117,7 @@ class WaveSim: @@ -117,7 +117,7 @@ class WaveSim:
self.circuit = circuit
self.sims = sims
self.overflows = 0
self.interface = list(circuit.interface) + [n for n in circuit.nodes if 'dff' in n.kind.lower()]
self.interface = list(circuit.io_nodes) + [n for n in circuit.nodes if 'dff' in n.kind.lower()]
self.lst_eat_valid = False

2
src/kyupy/wave_sim_4ig.py

@ -117,7 +117,7 @@ class WaveSim: @@ -117,7 +117,7 @@ class WaveSim:
self.circuit = circuit
self.sims = sims
self.overflows = 0
self.interface = list(circuit.interface) + [n for n in circuit.nodes if 'dff' in n.kind.lower()]
self.interface = list(circuit.io_nodes) + [n for n in circuit.nodes if 'dff' in n.kind.lower()]
self.lst_eat_valid = False

2
tests/test_bench.py

@ -12,4 +12,4 @@ def test_b01(mydir): @@ -12,4 +12,4 @@ def test_b01(mydir):
def test_simple():
c = bench.parse('input(a, b) output(z) z=and(a,b)')
assert len(c.nodes) == 4
assert len(c.interface) == 3
assert len(c.io_nodes) == 3

6
tests/test_circuit.py

@ -57,9 +57,9 @@ def test_circuit(): @@ -57,9 +57,9 @@ def test_circuit():
assert 'in1' in c.cells
assert 'and1' not in c.cells
c.interface[0] = in1
c.interface[1] = in2
c.interface[2] = out1
c.io_nodes[0] = in1
c.io_nodes[1] = in2
c.io_nodes[2] = out1
and1 = Node(c, 'and1', kind='and')
Line(c, in1, and1)

Loading…
Cancel
Save