Hi @marioruiz @briansune ,
I finally solved the problem! Simply put, there is a BUG in the source code of PYNQ 2.7:
Firstly, lets review the error:
ValueError Traceback (most recent call last)
<ipython-input-29-3b813cdecb5c> in <module>
18 decouple.write(DATA_OFFSET, 0x0000_0001)
19 pb = Bitstream("add_pblock_partial.bit", None, True)
---> 20 pb.download()
21 decouple.write(DATA_OFFSET, 0x0000_0000)
22
/usr/local/share/pynq-venv/lib/python3.8/site-packages/pynq/bitstream.py in download(self, parser)
185
186 """
--> 187 self.device.download(self, parser)
188
189 def remove_dtbo(self):
/usr/local/share/pynq-venv/lib/python3.8/site-packages/pynq/pl_server/embedded_device.py in download(self, bitstream, parser)
576 if parser is None:
577 from .xclbin_parser import XclBin
--> 578 parser = XclBin(DEFAULT_XCLBIN)
579
580 if not bitstream.binfile_name:
/usr/local/share/pynq-venv/lib/python3.8/site-packages/pynq/pl_server/xclbin_parser.py in __init__(self, filename, xclbin_data)
369 def __init__(self, filename="", xclbin_data=None):
370 self.ip_dict, self.mem_dict, self.clock_dict = \
--> 371 _xclbin_to_dicts(filename, xclbin_data)
372 self.gpio_dict = {}
373 self.interrupt_controllers = {}
/usr/local/share/pynq-venv/lib/python3.8/site-packages/pynq/pl_server/xclbin_parser.py in _xclbin_to_dicts(filename, xclbin_data)
276 def _xclbin_to_dicts(filename, xclbin_data=None):
277 if xclbin_data is None:
--> 278 with open(filename, 'rb') as f:
279 xclbin_data = bytearray(f.read())
280 sections, xclbin_uuid = parse_xclbin_header(xclbin_data)
ValueError: embedded null byte
It turns out, that an embedded null byte in the filename, and I found that this filename is actually DEFAULT_XCLBIN.
Somehow, in the PYNQ 2.7, the following line of code cannot execute correctly.
DEFAULT_XCLBIN = (Path(__file__).parent / 'default.xclbin').read_bytes()
Location:
/PYNQ-image_v2.7/pynq/pl_server/embedded_device.py
My Solution is, by using Method Overriding, I rewrite these Classes:
class DebugXclBin(XclBin):
class DebugBitstream(Bitstream):
Now my full_test code is:
from pynq import Overlay, Bitstream, allocate, GPIO, MMIO
import pynq.lib.dma
from pynq.lib.dma import *
import numpy as np
######### Method Overriding #########
from pynq.pl_server.embedded_device import EmbeddedDevice, DEFAULT_XCLBIN, _get_bitstream_handler
from pynq.pl_server.xclbin_parser import XclBin, _xclbin_to_dicts
class DebugXclBin(XclBin):
def __init__(self, filename="", xclbin_data=None):
super().__init__(filename, xclbin_data)
self.xclbin_data = xclbin_data
class DebugBitstream(Bitstream):
def download(self, parser=None):
if parser is None:
bitfile_path = self.bitfile_name
# Create the bitstream handler
bitstream_handler = _get_bitstream_handler(bitfile_path)
# Get parser without partial
parser = bitstream_handler.get_parser()
if parser is None:
parser = DebugXclBin(xclbin_data=DEFAULT_XCLBIN)
if not hasattr(parser, 'xclbin_data'):
raise AttributeError("Parser object has no attribute 'xclbin_data'")
if parser.xclbin_data is None:
raise ValueError("Parser object has xclbin_data set to None")
super().download(parser)
######### Method Overriding #########
DATA_OFFSET = 0x0000
overlay = Overlay("dpr.bit")
decouple = MMIO(0xA000_0000, 0x1000)
decouple_status = MMIO(0xA001_0000, 0x1000)
dma_in1 = overlay.dma_in1
dma_in2 = overlay.dma_in2
dma_out = overlay.dma_out
decouple.write(DATA_OFFSET, 0x0000_0001)
pb = DebugBitstream("add_pblock_partial.bit", None, True)
pb.download()
decouple.write(DATA_OFFSET, 0x0000_0000)
in1_data = allocate(shape=(4,), dtype=np.uint32)
in2_data = allocate(shape=(4,), dtype=np.uint32)
out_data = allocate(shape=(4,), dtype=np.uint32)
in1_data[:] = np.array([2, 4, 6, 100], dtype=np.uint32)
in2_data[:] = np.array([1, 2, 3, 70], dtype=np.uint32)
dma_in1.sendchannel.transfer(in1_data)
dma_in2.sendchannel.transfer(in2_data)
dma_in1.sendchannel.wait()
dma_in2.sendchannel.wait()
dma_out.recvchannel.transfer(out_data)
dma_out.recvchannel.wait()
print(out_data)
decouple.write(DATA_OFFSET, 0x0000_0001)
pb = DebugBitstream("sub_pblock_partial.bit", None, True)
pb.download()
decouple.write(DATA_OFFSET, 0x0000_0000)
in1_data = allocate(shape=(4,), dtype=np.uint32)
in2_data = allocate(shape=(4,), dtype=np.uint32)
out_data = allocate(shape=(4,), dtype=np.uint32)
in1_data[:] = np.array([2, 4, 6, 100], dtype=np.uint32)
in2_data[:] = np.array([1, 2, 3, 70], dtype=np.uint32)
dma_in1.sendchannel.transfer(in1_data)
dma_in2.sendchannel.transfer(in2_data)
dma_in1.sendchannel.wait()
dma_in2.sendchannel.wait()
dma_out.recvchannel.transfer(out_data)
dma_out.recvchannel.wait()
print(out_data)
The output is:
[ 3 6 9 170]
[ 1 2 3 30]
Problem solved!