aboutsummaryrefslogtreecommitdiffstats
path: root/3rdparty/pybind11/tests/test_buffers.py
blob: f0f370844b90c423bf52e3a2f30934fe8c349103 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# -*- coding: utf-8 -*-
import io
import struct
import ctypes

import pytest

import env  # noqa: F401

from pybind11_tests import buffers as m
from pybind11_tests import ConstructorStats

np = pytest.importorskip("numpy")


def test_from_python():
    with pytest.raises(RuntimeError) as excinfo:
        m.Matrix(np.array([1, 2, 3]))  # trying to assign a 1D array
    assert str(excinfo.value) == "Incompatible buffer format!"

    m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
    m4 = m.Matrix(m3)

    for i in range(m4.rows()):
        for j in range(m4.cols()):
            assert m3[i, j] == m4[i, j]

    cstats = ConstructorStats.get(m.Matrix)
    assert cstats.alive() == 1
    del m3, m4
    assert cstats.alive() == 0
    assert cstats.values() == ["2x3 matrix"]
    assert cstats.copy_constructions == 0
    # assert cstats.move_constructions >= 0  # Don't invoke any
    assert cstats.copy_assignments == 0
    assert cstats.move_assignments == 0


# https://foss.heptapod.net/pypy/pypy/-/issues/2444
def test_to_python():
    mat = m.Matrix(5, 4)
    assert memoryview(mat).shape == (5, 4)

    assert mat[2, 3] == 0
    mat[2, 3] = 4.0
    mat[3, 2] = 7.0
    assert mat[2, 3] == 4
    assert mat[3, 2] == 7
    assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,)
    assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,)

    mat2 = np.array(mat, copy=False)
    assert mat2.shape == (5, 4)
    assert abs(mat2).sum() == 11
    assert mat2[2, 3] == 4 and mat2[3, 2] == 7
    mat2[2, 3] = 5
    assert mat2[2, 3] == 5

    cstats = ConstructorStats.get(m.Matrix)
    assert cstats.alive() == 1
    del mat
    pytest.gc_collect()
    assert cstats.alive() == 1
    del mat2  # holds a mat reference
    pytest.gc_collect()
    assert cstats.alive() == 0
    assert cstats.values() == ["5x4 matrix"]
    assert cstats.copy_constructions == 0
    # assert cstats.move_constructions >= 0  # Don't invoke any
    assert cstats.copy_assignments == 0
    assert cstats.move_assignments == 0


def test_inherited_protocol():
    """SquareMatrix is derived from Matrix and inherits the buffer protocol"""

    matrix = m.SquareMatrix(5)
    assert memoryview(matrix).shape == (5, 5)
    assert np.asarray(matrix).shape == (5, 5)


def test_pointer_to_member_fn():
    for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
        buf = cls()
        buf.value = 0x12345678
        value = struct.unpack("i", bytearray(buf))[0]
        assert value == 0x12345678


def test_readonly_buffer():
    buf = m.BufferReadOnly(0x64)
    view = memoryview(buf)
    assert view[0] == b"d" if env.PY2 else 0x64
    assert view.readonly


def test_selective_readonly_buffer():
    buf = m.BufferReadOnlySelect()

    memoryview(buf)[0] = b"d" if env.PY2 else 0x64
    assert buf.value == 0x64

    io.BytesIO(b"A").readinto(buf)
    assert buf.value == ord(b"A")

    buf.readonly = True
    with pytest.raises(TypeError):
        memoryview(buf)[0] = b"\0" if env.PY2 else 0
    with pytest.raises(TypeError):
        io.BytesIO(b"1").readinto(buf)


def test_ctypes_array_1d():
    char1d = (ctypes.c_char * 10)()
    int1d = (ctypes.c_int * 15)()
    long1d = (ctypes.c_long * 7)()

    for carray in (char1d, int1d, long1d):
        info = m.get_buffer_info(carray)
        assert info.itemsize == ctypes.sizeof(carray._type_)
        assert info.size == len(carray)
        assert info.ndim == 1
        assert info.shape == [info.size]
        assert info.strides == [info.itemsize]
        assert not info.readonly


def test_ctypes_array_2d():
    char2d = ((ctypes.c_char * 10) * 4)()
    int2d = ((ctypes.c_int * 15) * 3)()
    long2d = ((ctypes.c_long * 7) * 2)()

    for carray in (char2d, int2d, long2d):
        info = m.get_buffer_info(carray)
        assert info.itemsize == ctypes.sizeof(carray[0]._type_)
        assert info.size == len(carray) * len(carray[0])
        assert info.ndim == 2
        assert info.shape == [len(carray), len(carray[0])]
        assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
        assert not info.readonly


@pytest.mark.skipif(
    "env.PYPY and env.PY2", reason="PyPy2 bytes buffer not reported as readonly"
)
def test_ctypes_from_buffer():
    test_pystr = b"0123456789"
    for pyarray in (test_pystr, bytearray(test_pystr)):
        pyinfo = m.get_buffer_info(pyarray)

        if pyinfo.readonly:
            cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
            cinfo = m.get_buffer_info(cbytes)
        else:
            cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
            cinfo = m.get_buffer_info(cbytes)

        assert cinfo.size == pyinfo.size
        assert cinfo.ndim == pyinfo.ndim
        assert cinfo.shape == pyinfo.shape
        assert cinfo.strides == pyinfo.strides
        assert not cinfo.readonly
">: ['clkbuf_sink']}), Cell('RAMB4_S1_S1', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S1_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S1_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S1_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S1_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S2_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S2_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S2_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S2_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S4_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S4_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S4_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S8_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S8_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB4_S16_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), # Virtex 2, Spartan 3. Cell('RAMB16_S1', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16_S2', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16_S4', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16_S9', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16_S18', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16_S36', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16_S1_S1', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S1_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S1_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S1_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S1_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S1_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S2_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S2_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S2_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S2_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S2_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S4_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S4_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S4_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S4_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S9_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S9_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S9_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S18_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S18_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16_S36_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), # Spartan 3A (in addition to above). Cell('RAMB16BWE_S18', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16BWE_S36', port_attrs={'CLK': ['clkbuf_sink']}), Cell('RAMB16BWE_S18_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16BWE_S18_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16BWE_S36_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16BWE_S36_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB16BWE_S36_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), # Spartan 3A DSP. Cell('RAMB16BWER', port_attrs={ 'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), # Spartan 6 (in addition to above). Cell('RAMB8BWER', port_attrs={ 'CLKAWRCLK': ['clkbuf_sink'], 'CLKBRDCLK': ['clkbuf_sink']}), # Virtex 4. Cell('FIFO16', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('RAMB16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB32_S64_ECC', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), # Virtex 5. Cell('FIFO18', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('FIFO18_36', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('FIFO36', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('FIFO36_72', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('RAMB18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}), Cell('RAMB18SDP', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('RAMB36SDP', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), # Virtex 6 / Series 7. Cell('FIFO18E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('FIFO36E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), #Cell('RAMB18E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}), #Cell('RAMB36E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}), # Ultrascale. Cell('FIFO18E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('FIFO36E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('RAMB18E2', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}), Cell('RAMB36E2', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}), # Ultra RAM. Cell('URAM288', port_attrs={'CLK': ['clkbuf_sink']}), Cell('URAM288_BASE', port_attrs={'CLK': ['clkbuf_sink']}), # Multipliers and DSP. # Cell('MULT18X18'), # Virtex 2, Spartan 3 # Cell('MULT18X18S', port_attrs={'C': ['clkbuf_sink']}), # Spartan 3 # Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E # Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP # Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6 # Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4 Cell('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5 #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7 Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale # I/O logic. # Virtex 2, Spartan 3. # Note: these two are not officially listed in the HDL library guide, but # they are more fundamental than OFDDR* and are necessary to construct # differential DDR outputs (OFDDR* can only do single-ended). Cell('FDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}), Cell('FDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}), Cell('IFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}), Cell('IFDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}), Cell('OFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'Q': ['iopad_external_pin']}), Cell('OFDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'Q': ['iopad_external_pin']}), Cell('OFDDRTCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'O': ['iopad_external_pin']}), Cell('OFDDRTRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'O': ['iopad_external_pin']}), # Spartan 3E. Cell('IDDR2', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}), Cell('ODDR2', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}), # Virtex 4. Cell('IDDR', port_attrs={'C': ['clkbuf_sink']}), Cell('IDDR_2CLK', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}), Cell('ODDR', port_attrs={'C': ['clkbuf_sink']}), Cell('IDELAYCTRL', keep=True, port_attrs={'REFCLK': ['clkbuf_sink']}), Cell('IDELAY', port_attrs={'C': ['clkbuf_sink']}), Cell('ISERDES', port_attrs={ 'CLK': ['clkbuf_sink'], 'OCLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink'], }), Cell('OSERDES', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}), # Virtex 5. Cell('IODELAY', port_attrs={'C': ['clkbuf_sink']}), Cell('ISERDES_NODELAY', port_attrs={ 'CLK': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink'], 'OCLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink'], }), # Virtex 6. Cell('IODELAYE1', port_attrs={'C': ['clkbuf_sink']}), Cell('ISERDESE1', port_attrs={ 'CLK': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink'], 'OCLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink'], }), Cell('OSERDESE1', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}), # Series 7. Cell('IDELAYE2', port_attrs={'C': ['clkbuf_sink']}), Cell('ODELAYE2', port_attrs={'C': ['clkbuf_sink']}), Cell('ISERDESE2', port_attrs={ 'CLK': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink'], 'OCLK': ['clkbuf_sink'], 'OCLKB': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink'], 'CLKDIVP': ['clkbuf_sink'], }), Cell('OSERDESE2', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}), Cell('PHASER_IN', keep=True), Cell('PHASER_IN_PHY', keep=True), Cell('PHASER_OUT', keep=True), Cell('PHASER_OUT_PHY', keep=True), Cell('PHASER_REF', keep=True), Cell('PHY_CONTROL', keep=True), # Ultrascale. Cell('IDDRE1', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}), Cell('ODDRE1', port_attrs={'C': ['clkbuf_sink']}), Cell('IDELAYE3', port_attrs={'CLK': ['clkbuf_sink']}), Cell('ODELAYE3', port_attrs={'CLK': ['clkbuf_sink']}), Cell('ISERDESE3', port_attrs={ 'CLK': ['clkbuf_sink'], 'CLK_B': ['clkbuf_sink'], 'FIFO_RD_CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink'], }), Cell('OSERDESE3', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}), Cell('BITSLICE_CONTROL', keep=True), Cell('RIU_OR', keep=True), Cell('RX_BITSLICE'), Cell('RXTX_BITSLICE'), Cell('TX_BITSLICE'), Cell('TX_BITSLICE_TRI'), # Spartan 6. Cell('IODELAY2', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}), Cell('IODRP2', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}), Cell('IODRP2_MCB', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}), Cell('ISERDES2', port_attrs={ 'CLK0': ['clkbuf_sink'], 'CLK1': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink'], }), Cell('OSERDES2', port_attrs={ 'CLK0': ['clkbuf_sink'], 'CLK1': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink'], }), # I/O buffers. # Input. # Cell('IBUF', port_attrs={'I': ['iopad_external_pin']}), Cell('IBUF_DLY_ADJ', port_attrs={'I': ['iopad_external_pin']}), Cell('IBUF_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin']}), Cell('IBUF_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin']}), Cell('IBUF_ANALOG', port_attrs={'I': ['iopad_external_pin']}), Cell('IBUFE3', port_attrs={'I': ['iopad_external_pin']}), Cell('IBUFDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_DLY_ADJ', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_DIFF_OUT_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDSE3', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_DPHY', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), # Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}), Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), # I/O. # Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}), Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}), Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}), Cell('IOBUFE3', port_attrs={'IO': ['iopad_external_pin']}), Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_DIFF_OUT', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_DIFF_OUT_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), Cell('IOBUFDSE3', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}), # Output. # Cell('OBUF', port_attrs={'O': ['iopad_external_pin']}), Cell('OBUFDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), Cell('OBUFDS_DPHY', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), # Output + tristate. # Cell('OBUFT', port_attrs={'O': ['iopad_external_pin']}), Cell('OBUFTDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), # Pulls. Cell('KEEPER'), Cell('PULLDOWN'), Cell('PULLUP'), # Misc. Cell('DCIRESET', keep=True), Cell('HPIO_VREF', keep=True), # Ultrascale # Clock buffers (global). # Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFGCE', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFGCE_1', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFGMUX', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFGMUX_1', port_attrs={'O': ['clkbuf_driver']}), #Cell('BUFGCTRL', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFGMUX_CTRL', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFGMUX_VIRTEX4', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFG_GT', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFG_GT_SYNC'), Cell('BUFG_PS', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFGCE_DIV', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFH', port_attrs={'O': ['clkbuf_driver']}), #Cell('BUFHCE', port_attrs={'O': ['clkbuf_driver']}), # Clock buffers (IO) -- Spartan 6. Cell('BUFIO2', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}), Cell('BUFIO2_2CLK', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}), Cell('BUFIO2FB', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFPLL', port_attrs={'IOCLK': ['clkbuf_driver']}), Cell('BUFPLL_MCB', port_attrs={'IOCLK0': ['clkbuf_driver'], 'IOCLK1': ['clkbuf_driver']}), # Clock buffers (IO and regional) -- Virtex. Cell('BUFIO', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFIODQS', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFR', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFMR', port_attrs={'O': ['clkbuf_driver']}), Cell('BUFMRCE', port_attrs={'O': ['clkbuf_driver']}), # Clock components. # VIrtex. # TODO: CLKDLL # TODO: CLKDLLE # TODO: CLKDLLHF # Virtex 2, Spartan 3. Cell('DCM'), # Spartan 3E. Cell('DCM_SP'), # Spartan 6 (also uses DCM_SP and PLL_BASE). Cell('DCM_CLKGEN'), # Virtex 4/5. Cell('DCM_ADV'), Cell('DCM_BASE'), Cell('DCM_PS'), # Virtex 4. Cell('PMCD'), # Virtex 5. Cell('PLL_ADV'), Cell('PLL_BASE'), # Virtex 6. Cell('MMCM_ADV'), Cell('MMCM_BASE'), # Series 7. Cell('MMCME2_ADV'), Cell('MMCME2_BASE'), Cell('PLLE2_ADV'), Cell('PLLE2_BASE'), # Ultrascale. Cell('MMCME3_ADV'), Cell('MMCME3_BASE'), Cell('PLLE3_ADV'), Cell('PLLE3_BASE'), # Ultrascale+. Cell('MMCME4_ADV'), Cell('MMCME4_BASE'), Cell('PLLE4_ADV'), Cell('PLLE4_BASE'), # Misc stuff. Cell('BUFT'), # Series 7 I/O FIFOs. Cell('IN_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), Cell('OUT_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}), # Ultrascale special synchronizer register. Cell('HARD_SYNC', port_attrs={'CLK': ['clkbuf_sink']}), # Singletons. # Startup. # TODO: STARTUP_VIRTEX # TODO: STARTUP_VIRTEX2 Cell('STARTUP_SPARTAN3', keep=True), Cell('STARTUP_SPARTAN3E', keep=True), Cell('STARTUP_SPARTAN3A', keep=True), Cell('STARTUP_SPARTAN6', keep=True), Cell('STARTUP_VIRTEX4', keep=True), Cell('STARTUP_VIRTEX5', keep=True), Cell('STARTUP_VIRTEX6', keep=True), Cell('STARTUPE2', keep=True), # Series 7 Cell('STARTUPE3', keep=True), # Ultrascale # Capture trigger. # TODO: CAPTURE_VIRTEX # TODO: CAPTURE_VIRTEX2 Cell('CAPTURE_SPARTAN3', keep=True), Cell('CAPTURE_SPARTAN3A', keep=True), Cell('CAPTURE_VIRTEX4', keep=True), Cell('CAPTURE_VIRTEX5', keep=True), Cell('CAPTURE_VIRTEX6', keep=True), Cell('CAPTUREE2', keep=True), # Series 7 # Internal Configuration Access Port. # TODO: ICAP_VIRTEX2 Cell('ICAP_SPARTAN3A', keep=True), Cell('ICAP_SPARTAN6', keep=True), Cell('ICAP_VIRTEX4', keep=True), Cell('ICAP_VIRTEX5', keep=True), Cell('ICAP_VIRTEX6', keep=True), Cell('ICAPE2', keep=True), # Series 7 Cell('ICAPE3', keep=True), # Ultrascale # JTAG. # TODO: BSCAN_VIRTEX # TODO: BSCAN_VIRTEX2 Cell('BSCAN_SPARTAN3', keep=True), Cell('BSCAN_SPARTAN3A', keep=True), Cell('BSCAN_SPARTAN6', keep=True), Cell('BSCAN_VIRTEX4', keep=True), Cell('BSCAN_VIRTEX5', keep=True), Cell('BSCAN_VIRTEX6', keep=True), Cell('BSCANE2', keep=True), # Series 7, Ultrascale # DNA port. Cell('DNA_PORT'), # Virtex 5/6, Series 7, Spartan 3A/6 Cell('DNA_PORTE2'), # Ultrascale # Frame ECC. Cell('FRAME_ECC_VIRTEX4'), Cell('FRAME_ECC_VIRTEX5'), Cell('FRAME_ECC_VIRTEX6'), Cell('FRAME_ECCE2'), # Series 7 Cell('FRAME_ECCE3'), # Ultrascale Cell('FRAME_ECCE4'), # Ultrascale+ # AXSS command access. Cell('USR_ACCESS_VIRTEX4'), Cell('USR_ACCESS_VIRTEX5'), Cell('USR_ACCESS_VIRTEX6'), Cell('USR_ACCESSE2'), # Series 7, Ultrascale # Misc. Cell('POST_CRC_INTERNAL'), # Spartan 6 Cell('SUSPEND_SYNC', keep=True), # Spartan 6 Cell('KEY_CLEAR', keep=True), # Virtex 5 Cell('MASTER_JTAG', keep=True), # Ultrascale Cell('SPI_ACCESS', keep=True), # Spartan 3AN Cell('EFUSE_USR'), # ADC. Cell('SYSMON', keep=True), # Virtex 5/6 Cell('XADC', keep=True), # Series 7 Cell('SYSMONE1', keep=True), # Ultrascale Cell('SYSMONE4', keep=True), # Ultrascale+ # Gigabit transceivers. # Spartan 6. Cell('GTPA1_DUAL'), # Virtex 2 Pro. # TODO: GT_* # TODO: GT10_* # Virtex 4. Cell('GT11_CUSTOM'), Cell('GT11_DUAL'), Cell('GT11CLK'), Cell('GT11CLK_MGT'), # Virtex 5. Cell('GTP_DUAL'), Cell('GTX_DUAL'), Cell('CRC32', port_attrs={'CRCCLK': ['clkbuf_sink']}), Cell('CRC64', port_attrs={'CRCCLK': ['clkbuf_sink']}), # Virtex 6. Cell('GTHE1_QUAD'), Cell('GTXE1'), Cell('IBUFDS_GTXE1', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('IBUFDS_GTHE1', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), # Series 7. Cell('GTHE2_CHANNEL'), Cell('GTHE2_COMMON'), Cell('GTPE2_CHANNEL'), Cell('GTPE2_COMMON'), Cell('GTXE2_CHANNEL'), Cell('GTXE2_COMMON'), Cell('IBUFDS_GTE2', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), # Ultrascale. Cell('GTHE3_CHANNEL'), Cell('GTHE3_COMMON'), Cell('GTYE3_CHANNEL'), Cell('GTYE3_COMMON'), Cell('IBUFDS_GTE3', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('OBUFDS_GTE3', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), Cell('OBUFDS_GTE3_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), # Ultrascale+. Cell('GTHE4_CHANNEL'), Cell('GTHE4_COMMON'), Cell('GTYE4_CHANNEL'), Cell('GTYE4_COMMON'), Cell('IBUFDS_GTE4', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('OBUFDS_GTE4', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), Cell('OBUFDS_GTE4_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), # Ultrascale+ GTM. Cell('GTM_DUAL'), # not in the libraries guide Cell('IBUFDS_GTM', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), Cell('OBUFDS_GTM', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), Cell('OBUFDS_GTM_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}), # High-speed ADC/DAC. Cell('HSDAC'), # not in libraries guide Cell('HSADC'), # not in libraries guide Cell('RFDAC'), # not in libraries guide Cell('RFADC'), # not in libraries guide # PCIE IP. Cell('PCIE_A1'), # Spartan 6 Cell('PCIE_EP'), # Virtex 5 Cell('PCIE_2_0'), # Virtex 6 Cell('PCIE_2_1'), # Series 7 Cell('PCIE_3_0'), # Series 7 Cell('PCIE_3_1'), # Ultrascale Cell('PCIE40E4'), # Ultrascale+ Cell('PCIE4CE4'), # Ultrascale+ v2 (not in the libraries guide) # Ethernet IP. Cell('EMAC'), # Virtex 4 Cell('TEMAC'), # Virtex 5 Cell('TEMAC_SINGLE'), # Virtex 6 Cell('CMAC'), # Ultrascale Cell('CMACE4'), # Ultrsacale+ # Hard memory controllers. Cell('MCB'), # Spartan 6 Memory Controller Block Cell('HBM_REF_CLK', keep=True), # not in liraries guide # not sure how the following relate to the hw Cell('HBM_SNGLBLI_INTF_APB', keep=True), # not in liraries guide Cell('HBM_SNGLBLI_INTF_AXI', keep=True), # not in liraries guide Cell('HBM_ONE_STACK_INTF', keep=True), # not in liraries guide Cell('HBM_TWO_STACK_INTF', keep=True), # not in liraries guide # PowerPC. # TODO PPC405 (Virtex 2) Cell('PPC405_ADV'), # Virtex 4 Cell('PPC440'), # Virtex 5 # ARM. Cell('PS7', keep=True), # The Zynq 7000 ARM Processor System (not in libraries guide). Cell('PS8', keep=True), # The Zynq Ultrascale+ ARM Processor System (not in libraries guide). # Misc hard IP. Cell('ILKN'), # Ultrascale Interlaken Cell('ILKNE4'), # Ultrascale+ Interlaken Cell('VCU', keep=True), # Zynq MPSoC Video Codec Unit (not in libraries guide). Cell('FE'), # Zynq RFSoC Forward Error Correction (not in libraries guide). ] class State(Enum): OUTSIDE = auto() IN_MODULE = auto() IN_OTHER_MODULE = auto() IN_FUNCTION = auto() IN_TASK = auto() def xtract_cell_decl(cell, dirs, outf): for dir in dirs: for ext in ['.v', '.sv']: fname = os.path.join(dir, cell.name + ext) try: with open(fname) as f: state = State.OUTSIDE found = False # Probably the most horrible Verilog "parser" ever written. module_ports = [] invertible_ports = set() for l in f: l = l.partition('//')[0] l = l.strip() if l == 'module {}'.format(cell.name) or l.startswith('module {} '.format(cell.name)): if found: print('Multiple modules in {}.'.format(fname)) sys.exit(1) elif state != State.OUTSIDE: print('Nested modules in {}.'.format(fname)) sys.exit(1) found = True state = State.IN_MODULE if cell.keep: outf.write('(* keep *)\n') outf.write('module {} (...);\n'.format(cell.name)) elif l.startswith('module '): if state != State.OUTSIDE: print('Nested modules in {}.'.format(fname)) sys.exit(1) state = State.IN_OTHER_MODULE elif l.startswith('task '): if state == State.IN_MODULE: state = State.IN_TASK elif l.startswith('function '): if state == State.IN_MODULE: state = State.IN_FUNCTION elif l == 'endtask': if state == State.IN_TASK: state = State.IN_MODULE elif l == 'endfunction': if state == State.IN_FUNCTION: state = State.IN_MODULE elif l == 'endmodule': if state == State.IN_MODULE: for kind, rng, port in module_ports: for attr in cell.port_attrs.get(port, []): outf.write(' (* {} *)\n'.format(attr)) if port in invertible_ports: outf.write(' (* invertible_pin = "IS_{}_INVERTED" *)\n'.format(port)) if rng is None: outf.write(' {} {};\n'.format(kind, port)) else: outf.write(' {} {} {};\n'.format(kind, rng, port)) outf.write(l + '\n') outf.write('\n') elif state != State.IN_OTHER_MODULE: print('endmodule in weird place in {}.'.format(cell.name, fname)) sys.exit(1) state = State.OUTSIDE elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE: if l.endswith((';', ',')): l = l[:-1] if ';' in l: print('Weird port line in {} [{}].'.format(fname, l)) sys.exit(1) kind, _, ports = l.partition(' ') for port in ports.split(','): port = port.strip() if port.startswith('['): rng, port = port.split() else: rng = None module_ports.append((kind, rng, port)) elif l.startswith('parameter ') and state == State.IN_MODULE: if 'UNPLACED' in l: continue if l.endswith((';', ',')): l = l[:-1] while ' ' in l: l = l.replace(' ', ' ') if ';' in l: print('Weird parameter line in {} [{}].'.format(fname, l)) sys.exit(1) outf.write(' {};\n'.format(l)) match = re.search('IS_([a-zA-Z0-9_]+)_INVERTED', l) if match: invertible_ports.add(match[1]) if state != State.OUTSIDE: print('endmodule not found in {}.'.format(fname)) sys.exit(1) if not found: print('Cannot find module {} in {}.'.format(cell.name, fname)) sys.exit(1) return except FileNotFoundError: continue print('Cannot find {}.'.format(cell.name)) sys.exit(1) if __name__ == '__main__': parser = ArgumentParser(description='Extract Xilinx blackbox cell definitions from ISE and Vivado.') parser.add_argument('vivado_dir', nargs='?', default='/opt/Xilinx/Vivado/2018.1') parser.add_argument('ise_dir', nargs='?', default='/opt/Xilinx/ISE/14.7') args = parser.parse_args() dirs = [ os.path.join(args.vivado_dir, 'data/verilog/src/xeclib'), os.path.join(args.vivado_dir, 'data/verilog/src/unisims'), os.path.join(args.vivado_dir, 'data/verilog/src/retarget'), os.path.join(args.ise_dir, 'ISE_DS/ISE/verilog/xeclib/unisims'), ] for dir in dirs: if not os.path.isdir(dir): print('{} is not a directory'.format(dir)) out = StringIO() for cell in CELLS: xtract_cell_decl(cell, dirs, out) with open('cells_xtra.v', 'w') as f: f.write('// Created by cells_xtra.py from Xilinx models\n') f.write('\n') f.write(out.getvalue())