Source code for wni.axi

"""Python interface for AXI IP blocks on the FPGA"""

from __future__ import absolute_import, division, print_function

import logging
import os
import math
import mmap
import struct

import wni.config as config

logger = logging.getLogger(__name__)


[docs]def float_to_int12(x): """ Change a float (between between -1 and 1) to an int12. """ import numpy as np f64 = np.asarray(x, dtype='float64') if not ((-1 <= f64) & (f64 <= 1)).all(): import warnings warnings.warn('All values must be between -1 and 1 (inclusive)') rounded = np.round(f64 * 0x7ff) int12 = rounded.astype('int32') return int12
[docs]def int12_to_float(x): import numpy as np i16 = np.asarray(x, dtype='int16') if not ((-0x7ff <= i16) & (i16 <= 0x7ff)).all(): import warnings warnings.warn("All values must be representable by an int12") f32 = i16.astype('float32') scaled = f32 / 0x7ff return scaled
[docs]class MmapRegion(object): def __init__(self, base, size): """ base (int): The base address where the memory map is opened. size (int): The number of bytes the memory should be mapped. """ self.base = base self.size = size self._fd = os.open('/dev/mem', os.O_RDWR) self._map = mmap.mmap( self._fd, length=size, flags=mmap.MAP_SHARED, prot=mmap.PROT_READ | mmap.PROT_WRITE, offset=base ) def _seek(self, offset): self._map.seek(offset, os.SEEK_SET)
[docs] def write_bytes(self, addr, bytes): self._seek(addr) return self._map.write(bytes)
[docs] def read_bytes(self, addr, size): self._seek(addr) return self._map.read(size)
# integer read methods
[docs] def read_int8(self, addr): """Returns an 8-bit signed integer at addr.""" bytes = self.read_bytes(addr, 1) integer, = struct.unpack('b', bytes) return integer
[docs] def read_int16(self, addr): """Returns a 16-bit signed integer at addr.""" bytes = self.read_bytes(addr, 2) integer, = struct.unpack('h', bytes) return integer
[docs] def read_int32(self, addr): """Returns a 32-bit signed integer at addr.""" bytes = self.read_bytes(addr, 4) integer, = struct.unpack('i', bytes) return integer
# unsigned integer read methods
[docs] def read_uint8(self, addr): """Returns an 8-bit unsigned integer at addr.""" bytes = self.read_bytes(addr, 1) integer, = struct.unpack('B', bytes) return integer
[docs] def read_uint16(self, addr): """Returns a 16-bit unsigned integer at addr.""" bytes = self.read_bytes(addr, 2) integer, = struct.unpack('H', bytes) return integer
[docs] def read_uint32(self, addr): """Returns a 32-bit unsigned integer at addr.""" bytes = self.read_bytes(addr, 4) integer, = struct.unpack('I', bytes) return integer
# signed integer write methods
[docs] def write_int8(self, addr, value): """Writes an 8-bit signed integer `value` to `addr`""" bytes = struct.pack('b', value) return self.write_bytes(addr, bytes)
[docs] def write_int16(self, addr, value): """Writes a 16-bit signed integer `value` to `addr`""" bytes = struct.pack('h', value) return self.write_bytes(addr, bytes)
[docs] def write_int32(self, addr, value): """Writes a 32-bit signed integer `value` to `addr`""" bytes = struct.pack('i', value) return self.write_bytes(addr, bytes)
# unsigned integer write methods
[docs] def write_uint8(self, addr, value): """Writes an 8-bit unsigned integer `value` to `addr`""" bytes = struct.pack('B', value) return self.write_bytes(addr, bytes)
[docs] def write_uint16(self, addr, value): """Writes a 16-bit unsigned integer `value` to `addr`""" bytes = struct.pack('H', value) return self.write_bytes(addr, bytes)
[docs] def write_uint32(self, addr, value): """Writes a 32-bit unsigned integer `value` to `addr`""" bytes = struct.pack('I', value) return self.write_bytes(addr, bytes)
read_int = read_int32 read_uint = read_uint32 write_int = write_int32 write_uint = write_uint32 def __repr__(self): return '{}({}, {})'.format( self.__class__.__name__, hex(self.base), hex(self.size))