Skip to content

Commit

Permalink
* Bugfix for buffers where they are now freed when deleted/go out of …
Browse files Browse the repository at this point in the history
…scope.
  • Loading branch information
STFleming authored and skalade committed Sep 28, 2022
1 parent 2c83310 commit c37ce17
Showing 1 changed file with 42 additions and 54 deletions.
96 changes: 42 additions & 54 deletions pynq/buffer.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,19 @@
# Copyright (c) 2016, Xilinx, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

__author__ = "Peter Ogden"
__copyright__ = "Copyright 2019, Xilinx"
__email__ = "[email protected]"
# SPDX-License-Identifier: BSD-3-Clause


import numpy as np
import warnings

import numpy as np

from pynq._3rdparty import ert, xrt

import ctypes
libc = ctypes.CDLL("libc.so.6")
libc.munmap.argtypes = [ctypes.c_void_p, ctypes.c_size_t]
libc.munmap.restype = ctypes.c_int


class PynqBuffer(np.ndarray):
"""A subclass of numpy.ndarray which is allocated using
physically contiguous memory for use with DMA engines and
Expand All @@ -54,14 +34,17 @@ class PynqBuffer(np.ndarray):
Whether the buffer is coherent
"""
def __new__(cls, *args, device=None, device_address=0,
bo=0, coherent=False, **kwargs):

def __new__(
cls, *args, device=None, device_address=0, bo=0, coherent=False, **kwargs
):
self = super().__new__(cls, *args, **kwargs)
self.device_address = device_address
self.coherent = coherent
self.bo = bo
self.device = device
self.offset = 0
self.freed = False
return self

def __array_finalize__(self, obj):
Expand All @@ -87,10 +70,17 @@ def freebuffer(self):
to the array exist prior to freeing.
"""
if hasattr(self, 'pointer') and self.pointer:
if self.return_to:
self.return_to.return_pointer(self.pointer)
self.pointer = 0
if hasattr(self, "memory"):
if hasattr(self, "pointer") and self.pointer:
if self.return_to:
self.return_to.return_pointer(self.pointer)
self.pointer = 0
else:
if not self.freed:
self.freed = True
libc.munmap(ctypes.cast(self.virtual_address, ctypes.c_void_p), self.nbytes)
xrt.xclFreeBO(self.device.handle, self.bo)


@property
def cacheable(self):
Expand All @@ -102,31 +92,26 @@ def physical_address(self):

@property
def virtual_address(self):
return self.__array_interface__['data'][0]
return self.__array_interface__["data"][0]

def close(self):
"""Unused - for backwards compatibility only
"""
"""Unused - for backwards compatibility only"""
warnings.warn(
".close no longer functional - use scopes to manage buffers",
DeprecationWarning)
DeprecationWarning,
)

def flush(self):
"""Flush the underlying memory if necessary
"""
"""Flush the underlying memory if necessary"""
if not self.coherent:
self.device.flush(self.bo, self.offset,
self.virtual_address, self.nbytes)
self.device.flush(self.bo, self.offset, self.virtual_address, self.nbytes)

def invalidate(self):
"""Invalidate the underlying memory if necessary
"""
"""Invalidate the underlying memory if necessary"""
if not self.coherent:
self.device.invalidate(self.bo, self.offset,
self.virtual_address, self.nbytes)
self.device.invalidate(
self.bo, self.offset, self.virtual_address, self.nbytes
)

def sync_to_device(self):
"""Copy the contents of the host buffer into the mirrored
Expand All @@ -150,7 +135,7 @@ def __exit__(self, exc_type, exc_value, traceback):
return 0


def allocate(shape, dtype='u4', target=None, **kwargs):
def allocate(shape, dtype="u4", target=None, **kwargs):
"""Allocate a PYNQ buffer
This API mimics the numpy ndarray constructor with the following
Expand All @@ -167,6 +152,9 @@ def allocate(shape, dtype='u4', target=None, **kwargs):
"""
from .pl_server import Device

if target is None:
target = Device.active_device
return target.allocate(shape, dtype, **kwargs)


0 comments on commit c37ce17

Please sign in to comment.