Compare commits
1
Commits
449bf9a031
...
bda89dc1b0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bda89dc1b0 |
No files matched your search
@@ -0,0 +1,64 @@
|
|||||||
|
"""A parser and dumper for Atalanta's plain-text test pattern format (*.test).
|
||||||
|
|
||||||
|
A *.test file contains one test pattern per line in the form ``<index>: <bits>``,
|
||||||
|
where ``<bits>`` is a string of ``'0'`` and ``'1'`` characters giving the values of
|
||||||
|
the primary inputs (in circuit order). Lines starting with ``'*'`` are comments.
|
||||||
|
|
||||||
|
This parser also accepts files without ``<index>:`` and patterns elements in 8-valued
|
||||||
|
logic such as ``'R'``, ``'F'``, ``'X'``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from . import readtext, logic
|
||||||
|
from .circuit import Circuit
|
||||||
|
|
||||||
|
_pattern_re = re.compile(r'^\s*(?:\d+:\s*)?([01HLRFX-]+)\s*$')
|
||||||
|
|
||||||
|
|
||||||
|
class TestFile:
|
||||||
|
"""Intermediate representation of a *.test pattern file.
|
||||||
|
|
||||||
|
:param text: The contents of a *.test file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, text: str):
|
||||||
|
patterns = []
|
||||||
|
for line in text.splitlines():
|
||||||
|
if (m := _pattern_re.match(line)) is not None:
|
||||||
|
patterns.append(logic.mvarray(m.group(1)))
|
||||||
|
|
||||||
|
self.patterns = np.stack(patterns, axis=-1) if patterns \
|
||||||
|
else np.zeros((0, 0), dtype=np.uint8)
|
||||||
|
"""The parsed patterns as a mvarray (see :py:mod:`~kyupy.logic`).
|
||||||
|
|
||||||
|
The second-to-last axis goes along primary inputs, the last axis goes along patterns.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def tests(self, circuit: Circuit):
|
||||||
|
"""Assembles and returns the test pattern set for the given circuit.
|
||||||
|
|
||||||
|
:param circuit: The circuit to assemble the patterns for. The patterns will follow the
|
||||||
|
:py:attr:`~kyupy.circuit.Circuit.io_nodes` ordering of the circuit.
|
||||||
|
:return: A logic array (see :py:mod:`~kyupy.logic`). The values for primary inputs are
|
||||||
|
filled, all other values are left unassigned.
|
||||||
|
"""
|
||||||
|
pi_locs = [i for i, n in enumerate(circuit.io_nodes) if len(n.ins) == 0]
|
||||||
|
tests = np.full((len(circuit.io_nodes), self.patterns.shape[-1]), logic.UNASSIGNED, dtype=np.uint8)
|
||||||
|
tests[pi_locs] = self.patterns
|
||||||
|
return tests
|
||||||
|
|
||||||
|
|
||||||
|
def parse(text) -> TestFile:
|
||||||
|
"""Parses the given ``text`` and returns a :class:`TestFile` object."""
|
||||||
|
return TestFile(text)
|
||||||
|
|
||||||
|
|
||||||
|
def load(file) -> TestFile:
|
||||||
|
"""Parses the contents of ``file`` and returns a :class:`TestFile` object.
|
||||||
|
|
||||||
|
Files with `.gz`-suffix are decompressed on-the-fly.
|
||||||
|
"""
|
||||||
|
return parse(readtext(file))
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from kyupy import atalanta, logic
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse():
|
||||||
|
text = '\n'.join([
|
||||||
|
'* Test pattern file',
|
||||||
|
'1: 0011',
|
||||||
|
'2: 1100',
|
||||||
|
'1010',
|
||||||
|
])
|
||||||
|
tf = atalanta.parse(text)
|
||||||
|
|
||||||
|
# second-to-last axis = inputs, last axis = patterns
|
||||||
|
assert tf.patterns.shape == (4, 3)
|
||||||
|
assert tf.patterns.dtype == np.uint8
|
||||||
|
assert set(np.unique(tf.patterns)) <= {logic.ZERO, logic.ONE}
|
||||||
|
|
||||||
|
# patterns are stored along the last axis
|
||||||
|
assert list(tf.patterns[:, 0]) == [logic.ZERO, logic.ZERO, logic.ONE, logic.ONE]
|
||||||
|
assert list(tf.patterns[:, 1]) == [logic.ONE, logic.ONE, logic.ZERO, logic.ZERO]
|
||||||
|
assert list(tf.patterns[:, 2]) == [logic.ONE, logic.ZERO, logic.ONE, logic.ZERO]
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty():
|
||||||
|
tf = atalanta.parse('* only comments\n* nothing else\n')
|
||||||
|
assert tf.patterns.shape == (0, 0)
|
||||||
|
assert tf.patterns.dtype == np.uint8
|
||||||
Reference in new issue
Block a user