cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
wgabor
Contributor
Contributor
1,855 Views
Registered: ‎01-22-2019

Vitis HLS aggregates xf::cv::ap_axiu

Due to the new synthesis defaults of Vitis HLS 2020.1 (in contrary to Vivado HLS), I see the following (using Vitis Vision library):

From this minimal test code to trigger the problem:

void test(hls::stream<xf::cv::ap_axiu<24,1,1,1>>&input, ap_uint<24> &output){
#pragma HLS INTERFACE s_axilite port = return
#pragma HLS INTERFACE s_axilite port = output
#pragma HLS INTERFACE axis register both port = input name = in
  xf::cv::ap_axiu<24,1,1,1> rd;
  input>>rd;
  output=rd.data;
}

We get the Verilog module interface:

 

module test (
ap_clk,
ap_rst_n,
in_r_TDATA,
in_r_TVALID,
in_r_TREADY,
s_axi_control_AWVALID,
s_axi_control_AWREADY,
s_axi_control_AWADDR,
s_axi_control_WVALID,
s_axi_control_WREADY,
s_axi_control_WDATA,
s_axi_control_WSTRB,
s_axi_control_ARVALID,
s_axi_control_ARREADY,
s_axi_control_ARADDR,
s_axi_control_RVALID,
s_axi_control_RREADY,
s_axi_control_RDATA,
s_axi_control_RRESP,
s_axi_control_BVALID,
s_axi_control_BREADY,
s_axi_control_BRESP,
interrupt
);

As you can see, no separate TUSER, TLAST, etc. thus using such IP in a Vivado video pipeline can only be done by using an AXI stream subset converter.

Is there any way to turn this off?

12 Replies
preusser
Adventurer
Adventurer
1,842 Views
Registered: ‎05-19-2014

It looks like Vitis would prune the `.last` signal because you are not using it. At some point, it will have to be done unless you bring it back into the computation as by adding

rd.data(0) ^= rd.last;

before the output.

0 Kudos
wgabor
Contributor
Contributor
1,810 Views
Registered: ‎01-22-2019

That's not true (I've already tested it before providing a minimal example):

void test(hls::stream<xf::cv::ap_axiu<24,1,1,1>>&input, ap_uint<24> &output){
#pragma HLS INTERFACE s_axilite port = return
#pragma HLS INTERFACE s_axilite port = output
#pragma HLS INTERFACE axis register both port = input name = in
xf::cv::ap_axiu<24,1,1,1> rd;
input>>rd;
output=rd.data^rd.user^rd.last;
}

will generate a 96-bit TDATA, without tlast and tuser.

And if you look into the generated Verilog sources you will see that TLAST will be TDATA[56], TUSER is TDATA[48].

 

wgabor
Contributor
Contributor
1,709 Views
Registered: ‎01-22-2019

It would be nice if a Xilinx employee check this, it makes vitis HLS mostly unusable for streaming applications.

And since Vitis Vision libraries won't work with vivado HLS because of a different bug, and HLS video library is removed from 2020.1 no usable solution exists for streaming video accelerators.

wgabor
Contributor
Contributor
1,584 Views
Registered: ‎01-22-2019

And still no solution for this. One would think that Vitis Vision is important for Xilinx, but not even core functionality works for now.

durmusk
Observer
Observer
1,469 Views
Registered: ‎09-13-2019

Still no response to this?

Just yesterday I deleted all previous versions and switched to 2020.1 tools, only to encounter this issue. This is really frustrating as mentioned there is no hls_video library to fall back to either.

What is the preferred method for creating streaming IPs with this new design approach?

0 Kudos
wgabor
Contributor
Contributor
1,467 Views
Registered: ‎01-22-2019

My "high quality" "solution" was to put and AXI stream subset converter to merge/alter the incoming signals.

I know, it is ugly, but at least better than the nothing proposed by Xilinx.

0 Kudos
durmusk
Observer
Observer
1,438 Views
Registered: ‎09-13-2019

Hi wgabor,

I gave up on Vitis HLS and tried Vivado HLS. It worked.

I see that you said "Vitis Vision libraries won't work with vivado HLS because of a different bug". Not sure what the problem was for you, but the same design flow worked for me, setting include paths and all that.

Here is a working thresholding example of streaming IP using Vitis vision library:

xf_threshold_config.h

 

 

#ifndef _XF_THRESHOLD_CONFIG_H_
#define _XF_THRESHOLD_CONFIG_H_

#include "hls_stream.h"

#include "common/xf_common.hpp"
#include "common/xf_utility.hpp"
#include "common/xf_infra.hpp"

#include "imgproc/xf_threshold.hpp"

#define DATA_WIDTH 8
#define NPIX XF_NPPC1

/*  set the height and width  */
#define HEIGHT 1024
#define WIDTH 1280

typedef xf::cv::ap_axiu<DATA_WIDTH,1,1,1> interface_t;
typedef hls::stream<interface_t> stream_t;

typedef xf::cv::Mat<XF_8UC1, HEIGHT, WIDTH, NPIX> img_t;

void threshold_accel(stream_t& stream_in, stream_t& stream_out, uint8_t thresh);

#endif // end of _XF_THRESHOLD_CONFIG_H_

 

 

 

xf_threshold_accel.cpp

 

 

#include "xf_threshold_config.h"

void threshold_accel(stream_t& stream_in, stream_t& stream_out, uint8_t thresh)
{
#pragma HLS INTERFACE axis register both port=stream_in
#pragma HLS INTERFACE axis register both port=stream_out
#pragma HLS INTERFACE ap_ctrl_none port=return

	img_t img_in;
	img_t img_out;
#pragma HLS STREAM variable=img_in depth=64 dim=1
#pragma HLS STREAM variable=img_out depth=64 dim=1

#pragma HLS DATAFLOW

    xf::cv::AXIvideo2xfMat<DATA_WIDTH, XF_8UC1, HEIGHT, WIDTH, NPIX>(stream_in, img_in);
    xf::cv::Threshold<XF_THRESHOLD_TYPE_BINARY, XF_8UC1, HEIGHT, WIDTH, NPIX>(img_in, img_out, thresh, 255);
    xf::cv::xfMat2AXIvideo<DATA_WIDTH, XF_8UC1, HEIGHT, WIDTH, NPIX>(img_out, stream_out);
}

 

 

cflags: -I$(PATH_TO_VITIS_LIBS)/vision/L1/include -I./. -D__SDSVHLS__ -std=c++0x

This gets synthesized and creates proper AXI stream ports.

 

Of course, the issue with Vitis HLS should definitely be looked at for the next version.

Cheers.

0 Kudos
wgabor
Contributor
Contributor
1,434 Views
Registered: ‎01-22-2019

0 Kudos
dimiter
Contributor
Contributor
1,303 Views
Registered: ‎06-10-2018

@durmusk 

I tested the IP you have posted and it does not work with Vivado HLS. The AXI stream interface gets generated with sidebands but it stalls on the DMA receive side.

The design is a simple dma loopback with the threshold IP in the middle.

Also, Vitis_hls complains about these two lines:

#pragma HLS STREAM variable=img_in depth=64 dim=1
#pragma HLS STREAM variable=img_out depth=64 dim=1

I have not been able to get a working streaming interface with Vitis_hls or Vivado_hls 2020.1.

The thing is , CSYNTH works but on HW it fails.

I tried other IP's as shown here:

https://discuss.pynq.io/t/vitis-vision-core-fails-on-pynq-v2-5-1/1822

 

unless I am missing something , all 2020.1 Vitis vision cores do not work in streaming mode

 

@wgabor 

The bug you are referring to was fixed a couple of weeks ago.

 

 

0 Kudos
durmusk
Observer
Observer
1,279 Views
Registered: ‎09-13-2019

@dimiter 

I've tested most of the vision examples in streaming mode and I'm currently using some of them. Which chip are you using? At what frequency?

I'm using Zynq 7020 @142 MHz for these streaming IPs.

Have you also verified co-simulation?

I suggest you start a new topic. That way you can get more attention.

0 Kudos
dimiter
Contributor
Contributor
1,257 Views
Registered: ‎06-10-2018

@durmusk 

I think it's related to this issue so hepefully I'm not hijacking the thread.  I'm using ZYNQ 7020 at 50MHz.  I have not verified cosimulation.  I simply generated an IP with the source you provided and added a test bench. And then started the IP from PYNQ. 

Also tested the resize IP and erosion IP. Same issue.  The generated IP has sidebands (TSRB and TKEEP).

I have encountered the same issue with all other IPs as shown here:

https://forums.xilinx.com/t5/High-Level-Synthesis-HLS/Vitis-Vision-cores-AXI4-Stream-buggy/m-p/1168941

 

Am I missing something?  I have used the same procedure since version 2019 using xfopencv and it worked then.

 

1.png2.png

#!/usr/bin/env python
# coding: utf-8

# In[1]:

import numpy as np

import cv2
import matplotlib.pyplot as plt
import pynq.lib.dma
from pynq import DefaultHierarchy, Overlay, Xlnk


# In[2]:


overlay = Overlay('threshold.bit')



thresh =  overlay.threshold_accel_0

# In[5]:

thresh.write(0x10, 100)

# In[6]:


def execute(img):
        in_buffer = Xlnk().cma_array(shape=(img.shape[0] * img.shape[1]), dtype=np.uint8)
        out_buffer = Xlnk().cma_array(shape=(img.shape[0] * img.shape[1]), dtype=np.uint8)
        for i, v in enumerate(np.reshape(img, (img.shape[0] * img.shape[1]))):
            in_buffer[i] = v
        overlay.axi_dma_0.sendchannel.transfer(in_buffer)
        overlay.axi_dma_0.recvchannel.transfer(out_buffer)
        thresh.write(0x00,0x81) # start
        overlay.axi_dma_0.sendchannel.wait()
        overlay.axi_dma_0.recvchannel.wait()
        result = np.reshape(out_buffer, img.shape)
        return result


# In[7]:


img = cv2.imread('lena.png', 0)
plt.figure(figsize=(4, 4))
plt.imshow(img, 'gray')


# In[5]:
get_ipython().run_cell_magic('time', '', 'result = overlay.memory.execute(img)')
# In[8]:
result = execute(img)
# In[6]:
plt.figure(figsize=(4, 4))
plt.imshow(result, 'gray')
0 Kudos
dimiter
Contributor
Contributor
1,010 Views
Registered: ‎06-10-2018

Just to confirm for anyone else. This is related to this bug issue:

https://github.com/Xilinx/Vitis_Libraries/issues/28

All Vitis vision cores with streaming interface need a custom type to work with the above PYNQ test.

 

struct axis_t {
ap_uint<8> data;
ap_int<1> last;
};