Skip to content

Memory access

Matthijs van Duin edited this page Jul 25, 2019 · 4 revisions

Device memory regions

The uio.device.MemRegion class represents a region of memory (or memory-mapped registers) associated with an uio device. You can access the top-level memory regions of an uio.device.Uio instance dev by name or by index:

  • dev.region( name ) -> MemRegion
  • dev.region( index ) -> MemRegion
  • dev.region() -> MemRegion is the default region, i.e. index 0.

You can also create subregions of an existing region rgn:

  • rgn.subregion( offset, size, name ) -> MemRegion (name is optional and defaults to None)
  • dev.subregion( offset, size, name ) -> MemRegion creates a subregion of dev.region()

Public attributes of MemRegion objects:

  • rgn.address : int — physical address of start of region
  • rgn.size : int — region size in bytes
  • rgn.end : int — physical address of end of region (== rgn.address + rgn.size)
  • rgn.mappable : int — mappable size of region in bytes
  • rgn.parent : MemRegion (or None)
  • rgn.name : str (or None)
  • rgn.uio : Uio (or None if not a top-level region of an uio device)
  • rgn.index : int (or None if not a top-level region of an uio device)

Reading and writing device memory

If the memory region is mappable, there are various ways of accessing it:

(For all of these methods, offset is optional and defaults to zero.)

rgn.write( data, offset ) writes data into the memory region at given offset. data must be an object that implements the buffer protocol, such as:

rgn.read( length, offset ) -> bytes reads a given number of bytes from the memory region at given offset. The data is returned as a bytes object.

rgn.read( type, offset ) -> type where type is a ctypes data type object reads an instance of this type from the memory region at given offset. For example, rgn.read( ctypes.c_uint32 * 4, offset ) would read four 32-bit unsigned integers.

As a shorthand, you can read from / write to the default region of a device using dev.read( ... ) / dev.write( ... ).

Direct mapping of device memory

rgn.map() -> memoryview returns a memoryview which directly represents the memory region.

rgn.map( length, offset ) -> memoryview returns a slice thereof.

rgn.map( type, offset ) -> type where type is a ctypes data type object maps an instance of this type in the memory region at given offset. Unlike rgn.read, the returned ctypes data object does not contain a copy of the data but directly represents device memory, i.e.:

data = rgn.map( ctypes.c_uint32 * 4 )
print( data[0] )   # <-- this reads from device memory
data[1] = 42       # <-- this writes to device memory

As a shorthand, you can map (part of) the default region of a device using dev.map( ... ).

Clone this wiki locally