KV260 进阶开发(PYNQ驱动开发+Pixel Pack)

目录

1. 简介

2. PixelPacker HLS 实现

2.1 PixelPacker HLS 源码

2.2 PixelPacker 功能简介

2.3 头文件介绍

2.4 启动间隔 II

2.5 Case V24 片段解释

3. PixelPacker Py 驱动

3.1 PixelPacker Py 源码

3.2 PixelPacker 类详解

3.3 property 装饰器

3.4 操作寄存器

3.5 DefaultIP 类源码

3.6 DefaultIP 类详解

4. Takeaways


1. 简介

  • 本文讨论在 PYNQ 框架下,使用 Python 驱动 Vitis HLS Kernel。
  • 使用 Registermap 也可以完成驱动,即直接操作所有寄存器。
  • 通过 Python 方式编写的驱动更直观,可以理解为对 Registermap 的封装
  • Registermap 和 Python 驱动,底层都是调用 MMIO 的读写。

 

2. PixelPacker HLS 实现

2.1 PixelPacker HLS 源码

Pixel Packericon-default.png?t=O83Ahttps://github.com/Xilinx/PYNQ/tree/master/boards/ip/hls/pixel_pack

#include <ap_fixed.h>
#include <ap_int.h>
#include "hls_stream.h"
#include <ap_axi_sdata.h>

typedef ap_axiu<24,1,0,0> narrow_pixel;
typedef ap_axiu<32,1,0,0> wide_pixel;

typedef hls::stream<narrow_pixel> narrow_stream;
typedef hls::stream<wide_pixel>   wide_stream;

#define V_24 	0
#define V_32 	1
#define V_8 	2
#define V_16 	3
#define V_16C 	4

void pixel_pack(narrow_stream& stream_in_24 ,
				  wide_stream& stream_out_32,
				  	  	   int mode,
				    ap_uint<8> alpha) {
#pragma HLS INTERFACE mode=axis register_mode=both depth=24 port=stream_in_24  register
#pragma HLS INTERFACE mode=axis register_mode=both depth=24 port=stream_out_32 register
#pragma HLS INTERFACE mode=s_axilite    port=mode  register
#pragma HLS INTERFACE mode=s_axilite    port=alpha register
#pragma HLS INTERFACE mode=ap_ctrl_none port=return

	bool last = false;
	bool delayed_last = false;
	narrow_pixel in_pixel;
	wide_pixel out_pixel;
	switch (mode) {
	case V_24:
		while (!delayed_last) {
#pragma HLS pipeline II=4
			delayed_last = last;
			ap_uint<96> buffer;
			ap_uint<4> has_last;
			ap_uint<4> has_user;
			for (int j = 0; j < 4; ++j) {
				if (!last) {
					stream_in_24.read(in_pixel);
					buffer(j*24 + 23, j*24) = in_pixel.data;
					has_user[j] = in_pixel.user;
					has_last[j] = in_pixel.last;
					last = in_pixel.last;
				}
			}
			if (!delayed_last) {
				for (int i = 0; i < 3; ++i) {
					out_pixel.data = buffer(i*32 + 31, i*32);
					out_pixel.user = has_user[i];
					out_pixel.last = has_last[i+1];
					stream_out_32.write(out_pixel);
				}
			}
		}
		break;
	case V_32:
		while (!last) {
#pragma HLS pipeline II=1
			ap_uint<32> data;
			stream_in_24.read(in_pixel);
			data(23, 0) = in_pixel.data;
			data(31, 24) = alpha;
			out_pixel.data = data;
			out_pixel.last = in_pixel.last;
			out_pixel.user = in_pixel.user;
			last = in_pixel.last;
			stream_out_32.write(out_pixel);

		}
		break;
	case V_8:
		while (!delayed_last) {
#pragma HLS pipeline II=4
			delayed_last = last;
			bool user = false;
			ap_uint<32> data;
			for (int i = 0; i < 4; ++i) {
				if (!last) {
					stream_in_24.read(in_pixel);
					user |= in_pixel.user;
					last = in_pixel.last;
					data(i*8 + 7, i * 8) = in_pixel.data(7,0);
				}
			}
			if (!delayed_last) {
				out_pixel.user = user;
				out_pixel.last = last;
				out_pixel.data = data;
				stream_out_32.write(out_pixel);
			}
		}
		break;
	case V_16:
		while (!last) {
#pragma HLS pipeline II=2
			bool user = false;
			ap_uint<32> data;
			for (int i = 0; i < 2; ++i) {
				stream_in_24.read(in_pixel);
				user |= in_pixel.user;
				last = in_pixel.last;
				data(i*16 + 15, i*16) = in_pixel.data(16,0);
			}
			out_pixel.user = user;
			out_pixel.last = last;
			out_pixel.data = data;
			stream_out_32.write(out_pixel);
		}
		break;
	case V_16C:
		while (!last) {
#pragma HLS pipeline II=2
			bool user = false;
			ap_uint<48> data;
			for (int i = 0; i < 2; ++i) {
				stream_in_24.read(in_pixel);
				user |= in_pixel.user;
				last = in_pixel.last;
				data(i*24 + 23, i*24) = in_pixel.data;
			}
			ap_uint<32> out_data;
			ap_uint<9> out_c1 = ap_uint<9>(data(15,8))  + ap_uint<9>(data(39,32));
			ap_uint<9> out_c2 = ap_uint<9>(data(23,16)) + ap_uint<9>(data(47,40));
			out_data(7,0) = data(7,0);
			out_data(15,8) = out_c1(8,1);
			out_data(23,16) = data(31,24);
			out_data(31,24) = out_c2(8,1);
			out_pixel.user = user;
			out_pixel.last = last;
			out_pixel.data = out_data;
			stream_out_32.write(out_pixel);
		}
		break;
	}
}

2.2 PixelPacker 功能简介

pixel_pack kernel,从一个输入流 stream_in_24 读取24位像素数据,并根据给定的模式 mode 将这些数据转换和打包成32位的数据,然后将转换后的数据写入到输出流 stream_out_32 中。

Kernel 中定义了五种模式:V_24, V_32, V_8, V_16, V_16C,每种模式都有其特定的处理逻辑。 

1). V_24: 这个模式将读取4个24位的像素,将它们合并成一个96位的缓冲区,然后从这个缓冲区中提取出3个32位的像素并写入到输出流中。

2). V_32: 在这个模式中,每个24位的输入像素被扩展到32位,通过在最高的8位加上一个 alpha 值(透明度信息)。然后将这32位的数据写入到输出流中。

3). V_8: 此模式将4个24位的输入像素的最低8位提取出来,并将这些8位数据打包成一个32位的像素。

4). V_16: 在这个模式下,每两个24位的输入像素被组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值