Browse Source

Initial commit

Matthias Vogelgesang 6 years ago
commit
3cad082d7c
4 changed files with 157 additions and 0 deletions
  1. 3 0
      .gitignore
  2. 31 0
      build.py
  3. 74 0
      pci
  4. 49 0
      pci.py

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+lextab.py
+_pciffi.*
+*.pyc

+ 31 - 0
build.py

@@ -0,0 +1,31 @@
+from cffi import FFI, __version__ as cffi_version
+
+
+def get_header():
+    fix = 'struct timeval { uint32_t tv_sec; uint32_t tv_usec; };'
+    f = open('/usr/local/include/pcilib.h')
+    lines = [x for x in f if not x.startswith('#') and not 'logger' in x and not 'extern "C"' in x]
+
+    # cut last 4 lines because they contain the rest of the extern "C" bits
+    lines = lines[:-4]
+
+    # hack because we cannot figure out the system-dependent timeval structure
+    lines.insert(0, 'struct timeval { uint32_t tv_sec; uint32_t tv_usec; };')
+
+    return '\n'.join(lines)
+
+
+def build():
+    builder = FFI()
+    builder.set_source("_pciffi",
+        r"""
+        #include <sys/time.h>
+        #include <pcilib.h>
+        """,
+        libraries=['pcilib'])
+    builder.cdef(get_header())
+    builder.compile(verbose=True)
+
+
+if __name__ == '__main__':
+    build()

+ 74 - 0
pci

@@ -0,0 +1,74 @@
+#!/usr/bin/python
+
+import argparse
+import pci
+
+
+def cmd_read(device, args):
+    def mute(s):
+        return '\x1B[30;49m{}\x1B[0m'.format(s)
+
+    def colored_hex(x):
+        s = '{:08x}'.format(x)
+        return s if x != 0 else mute(s)
+
+    for i in range(args.addr, args.addr + args.size * 4, 16):
+        data = device.read(i, 4, pci.Types.UINT32)
+        out = '  '.join((colored_hex(x) for x in data))
+        addr = '{:04x}'.format(i)
+        print '    {}   {}'.format(mute(addr) if not any(data) else addr, out)
+
+
+def cmd_write(device, args):
+    device.write(args.addr, args.value)
+
+
+def cmd_dma(device, args):
+    device.start_dma()
+
+
+def NumberType(s):
+    if s.startswith('0x'):
+        return int(s, 16)
+    return int(s)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--verbose', action='store_true', 
+            help="Verbose messages")
+
+    cmd_parsers = parser.add_subparsers(title="Commands", dest='commands')
+    cmd_parsers.required = True
+
+    read_parser = cmd_parsers.add_parser('read',
+            help="Read register values")
+    read_parser.add_argument('--size', '-s',
+            type=int, default=1,
+            help="foo")
+    read_parser.add_argument('addr', 
+            type=NumberType,
+            help="Address")
+    read_parser.set_defaults(run=cmd_read)
+
+    write_parser = cmd_parsers.add_parser('write',
+            help="write register values")
+    write_parser.add_argument('addr', 
+            type=NumberType,
+            help="Address")
+    write_parser.add_argument('value', 
+            type=NumberType,
+            help="Value")
+    write_parser.set_defaults(run=cmd_write)
+
+    dma_parser = cmd_parsers.add_parser('dma',
+            help="Read from DMA")
+    dma_parser.add_argument('--size', '-s',
+            type=int,
+            help="foo")
+    dma_parser.set_defaults(run=cmd_dma)
+
+    args = parser.parse_args()
+
+    with pci.Device('pci') as device:
+        args.run(device, args)

+ 49 - 0
pci.py

@@ -0,0 +1,49 @@
+import numpy as np
+from _pciffi import ffi, lib
+
+
+class Error(Exception):
+    pass
+
+
+class Types(object):
+    # This enum also maps directly to the type size for now
+    UINT8   = 1
+    UINT32  = 4
+
+
+TYPE_NAMES = {
+    Types.UINT8: 'uint8_t',
+    Types.UINT32: 'uint32_t',
+}
+
+class Device(object):
+    def __init__(self, model, device='/dev/fpga0'):
+        self.handle = lib.pcilib_open(device, model)
+        self.dma_engine = lib.pcilib_find_dma_by_addr(self.handle, lib.PCILIB_DMA_BIDIRECTIONAL, 0xFF)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args):
+        self.close()
+
+    def read(self, addr, num, t=Types.UINT32):
+        data = ffi.new("{}[]".format(TYPE_NAMES[t]), num)
+
+        if lib.pcilib_read(self.handle, 0, addr, num, t, data) != 0:
+            raise Error("Could not read")
+
+        return list(data[0:len(data)])
+
+    def write(self, addr, value, t=Types.UINT32):
+        data = ffi.new("{}[]".format(TYPE_NAMES[t]), [value])
+
+        if lib.pcilib_write(self.handle, 0, addr, t, 1, data) != 0:
+            raise Error("Could not write")
+
+    def start_dma(self):
+        lib.pcilib_start_dma(self.handle, self.dma_engine, lib.PCILIB_DMA_FLAGS_DEFAULT)
+
+    def close(self):
+        lib.pcilib_close(self.handle)