PYNQ: PYTHON PRODUCTIVITY

Why is HLS generating two ports for a single interface?

Hello all,
I have the following kernel


extern "C" {
	void main_accel(ap_uint<PTR_WIDTH>* img_in, ap_uint<PTR_WIDTH>* img_out,
					unsigned char* process_shape, const int threshold,
					const int im_height, const int im_width) {
		// clang-format off
	#pragma HLS INTERFACE m_axi      port=img_in  offset=slave bundle=BUS_IN depth=__XF_DEPTH
	#pragma HLS INTERFACE m_axi      port=img_out offset=slave bundle=BUS_OUT depth=__XF_DEPTH
	#pragma HLS INTERFACE m_axi      port=process_shape offset=slave bundle=BUS_KERNEL depth=9
	#pragma HLS INTERFACE s_axilite  port=threshold
	#pragma HLS INTERFACE s_axilite  port=im_height
	#pragma HLS INTERFACE s_axilite  port=im_width
	#pragma HLS INTERFACE s_axilite  port=return
		// clang-format on

		xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPC1> imgInput(im_height, im_width);
		xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPC1> tmp(im_height, im_width);
		xf::cv::Mat<TYPE, HEIGHT, WIDTH, NPC1> imgOutput(im_height, im_width);

		// Copy the shape data:
		unsigned char _kernel[FILTER_SIZE * FILTER_SIZE];
		for (unsigned int i = 0; i < FILTER_SIZE * FILTER_SIZE; ++i) {
		// clang-format off
			#pragma HLS PIPELINE
			// clang-format on
			_kernel[i] = process_shape[i];
		}

		// clang-format off
		#pragma HLS DATAFLOW
		// clang-format on
		// Retrieve xf::cv::Mat objects from img_in data:
		xf::cv::Array2xfMat<PTR_WIDTH, TYPE, HEIGHT, WIDTH, NPC1>(img_in, imgInput);
		// Run xfOpenCV kernel:
		xf::cv::Threshold<XF_THRESHOLD_TYPE_BINARY, TYPE, HEIGHT, WIDTH, NPC1>(imgInput, tmp, threshold, 255);
		close<XF_BORDER_CONSTANT, TYPE, HEIGHT, WIDTH, KERNEL_SHAPE,
			FILTER_SIZE, FILTER_SIZE, ITERATIONS, NPC1>(tmp, imgOutput, _kernel);
		// Convert imgOutput xf::cv::Mat object to output array:
		xf::cv::xfMat2Array<PTR_WIDTH, TYPE, HEIGHT, WIDTH, NPC1>(imgOutput, img_out);
	};
}

The issue iā€™m having is that Vitis HLS is generating two ports *_1 and *_2 for all m_axi interfaces for img_in, img_out and process_shape.

Is this correct? How should these interfaces be used?

Note:

PTR_WIDTH = 8
__XF_DEPTH = (HEIGHT * WIDTH * (XF_PIXELWIDTH(TYPE, NPC1)) / / (PTR_WIDTH / 8);

Newer version of HLS by default create 64-bit addresses this shows up as two 32-bit registers in the register map. In PYNQ (on embedded platforms) pynq.allocate will only create buffers in the lower 32-bits regardless of the memory on the board so you can write the device_address to _1 and leave _2 as 0.

Peter

1 Like