当前位置:   article > 正文

HLS第一课(template,数据类型)_ap_axiu

ap_axiu

HLS对标准C和C++都做了扩展,使得用户可以自定义任意精度的整数数据类型和定点数据类型。用户在使用时,只需要包含特定的头文件即可。
对于C,
#include “ap_cint.h”

对于C语言,头文件“ap_cint.h”定义了任意精度整数类型[u]int。使用方法如下:

  1. 在用户的源代码中加入头文件“ap_cint.h”

  2. 用int<N>或者uint<N>定义变量,N的取值范围为1-1024

对于C++,
#include “ap_int.h”

对于C++语言,头文件“ap_int.h”定义了任意精度整数类型ap_[u]int。使用方法如下:

  1. 在用户的源代码中加入头文件“ap_int.h”

  2. 用ap_int<N>或者ap_uint<N>定义变量,N的取值范围为1-1024

注意:这些头文件在Vivado中,是以独立的package形式提供的,它们放置在Vivado HLS的安装目录include文件夹里面,通常名字为“xilinx_hls_lib_.tgz”。另外,这些头文件只能用于VivadoHLS,不能使用标准C编译器编译!

对于ap_axiu这个结构体模板,定义如下:

template<int D,int U,int TI,int TD>
  struct ap_axiu{
    ap_uint<D>       data;
    ap_uint<(D+7)/8> keep;
    ap_uint<(D+7)/8> strb;
    ap_uint<U>       user;
    ap_uint<1>       last;
    ap_uint<TI>      id;
    ap_uint<TD>      dest;
  };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

例如
ap_axiu<DW,1,1,1>后面三个1,是用于VideoIP中的配置。

对于ap_axis这个结构体模板,定义如下:

template<int D,int U,int TI,int TD>
struct ap_axis{
ap_int<D> data;
ap_uint<D/8> keep;
ap_uint<D/8> strb;
ap_uint<U> user;
ap_uint<1> last;
ap_uint<TI> id;
ap_uint<TD> dest;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

例如
ap_axis<DW,1,1,1>后面三个1,是用于VideoIP中的配置。

通常为了方便使用,会定义成宏来使用,例如;

#define DATA_WIDTH(T, N)	((T) * (N))
#define T_UINT(T, N) 		ap_uint<DATA_WIDTH(T, N)>
#define T_AXIU(T, N)		ap_axiu<DATA_WIDTH(T, N), 1, 1, 1>
#define T_AXIS(T, N)		ap_axis<DATA_WIDTH(T, N), 1, 1, 1>

  • 1
  • 2
  • 3
  • 4
  • 5

例如
ap_axis<DW,1,1,1>后面三个1,是用于VideoIP中的配置。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
补充:
(1) stdint
#include <stdint.h>
stdint.h是c99中引进的一个标准C库的头文件.
stdint.h中定义了一些整数类型,规则如下(其中N可以为8,16,32,64)
intN_t, int_leastN_t, int_fastN_t表示长度为N位的整型数;
uintN_t, uint_leastN_t, uint_fastN_t表示长度为N位的无符号整型数 ;

int64_t数的输出:%lld ;
uint64_t数的输出:%llu ;
uint64_t数十六进制输出:%llx ;
uint64_t数八进制输出:%llo ;

按照posix标准,一般整型对应的*_t类型为:
1字节 uint8_t
2字节 uint16_t
4字节 uint32_t
8字节 uint64_t

2)stdio
#include <stdio.h>

下面是头文件 stdio.h 中定义的变量类型:
序号 变量 & 描述
1 size_t
这是无符号整数类型,它是 sizeof 关键字的结果。

size_t的真实类型与操作系统有关。
在32位架构中被普遍定义为:
typedef unsigned int size_t;
而在64位架构中被定义为:
typedef unsigned long size_t;

与int固定四个字节不同有所不同,size_t的取值range是目标平台下最大可能的数组尺寸,一些平台下size_t的范围小于int的正数范围,又或者大于unsigned int. 使用Int既有可能浪费,又有可能范围不够大。

2 FILE
这是一个适合存储文件流信息的对象类型。
3 fpos_t
这是一个适合存储文件中任何位置的对象类型。

标准函数
int getchar()//从标准输入设备写入一个字符
int putchar()//向标准输出设备读出一个字符
int scanf(charformat[,argument…])//从标准输入设备读入格式化后的数据
int printf(char
format[,argument…])//向标准输出设备输出格式化字符串
char* gets(charstring)//从标准输入设备读入一个字符串
int puts(char
string)//向标准输出设备输出一个字符串
int sprintf(charstring,charformat[,…])//把格式化的数据写入某个字符串缓冲区

文件访问
fopen
freopen
fflush
fclose

二进制输入/输出
fread
fwrite

非格式化输入/输出
fgetc/getc
fputc/putc
ungetc
fgets
fputs

文件定位
ftell
fseek
fgetpos
fsetpos
rewind

3)stdlib
#include < stdlib.h>

stdlib 头文件即standard library标准库头文件。
stdlib.h里面定义了五种类型、一些宏和通用工具函数。
类型例如size_t、wchar_t、div_t、ldiv_t和lldiv_t;
宏例如
EXIT_FAILURE、EXIT_SUCCESS、
RAND_MAX和MB_CUR_MAX等等;
常用的函数如
malloc()、calloc()、realloc()、free()、
system()、
atoi()、atol()、
rand()、srand()、
exit()等等。
++++++++++++++++++++++++++++++++++++++++++++++++++++
stream class

#include “hls_stream.h”

Vivado HLS 提供了 C++ 模板类
hls::stream<>, 用于对流传输数据结构进行建模。使用 hls::stream<> 类实现的流传输具有如下属性。

在 C 语言代码中, hls::stream<> 的行为与无限深度的 FIFO 相似。
无需定义 hls::stream<> 的大小。
按顺序对其执行读取和写入。即, 从 hls::stream<> 读取数据之后, 无法再次对其进行读取。
顶层接口上的 hls::stream<> 默认情况下使用 ap_fifo 接口来实现。
设计内部的 hls::stream<> 作为 FIFO 来实现, 深度为 2。最优化指令 STREAM 用于更改此默认大小
注释: hls::stream 类应始终在函数之间作为 C++ 参考实参来进行传递。例如,
&my_stream。
重要提示! hls::stream 类仅限在 C++ 设计中使用。不支持流传输数组。

数据流在软件中(以及在测试激励文件中进行 RTL 协同仿真期间) 作为无限FIFO来建模。
数据流可在函数内部使用, 也可在函数接口上使用。
内部数据流可作为函数参数来进行传递。
每个 hls::stream<> 对象都仅限单一进程写入, 且仅限单一进程读取。
如果在顶层接口上使用 hls::stream, 默认在 RTL 中会将其作为 FIFO 接口 (ap_fifo) 来实现, 但可选择将其作为握手接口 (ap_hs) 或作为 AXI-Stream 接口 (axis) 来实现。

如果使用 hls::stream 在不同任务(子函数或循环) 间传输数据, 应考量在不同任务间存在数据流传输的DATAFLOW 区域内实现这些任务。
默认(非 DATAFLOW) 行为是完成每一项任务后再开始下一项任务, 在此情况下必须确保用于实现 hls::stream 变量的 FIFO 大小足以保存生产者任务所生成的所有数据采样。

局部流传输始终作为内部 FIFO 来实现。全局流传输可作为内部 FIFO 或端口来实现:
仅读取或者仅写入的全局定义的流传输推断为顶层 RTL 块的外部端口。
支持读取和写入的全局定义的流传输(位于顶层函数下的层级内) 作为内部 FIFO 来实现。

数据对象流传输是通过指定类型和变量名称来定义的。
给定指定为 hls::stream 的流传输的情况下, 类型 T 可以是:
任何 C++ 原生数据类型
Vivado HLS 任意精度类型(例如, ap_int<> 或 ap_ufixed<>)
用户定义的结构体struct(包含以上任意类型)

stream命名为可选操作,给定以下 2 个流传输的情况下:
stream<uint8_t> bytestr_in1;
stream<uint8_t> bytestr_in2(“input_stream2”);
命名的好处:容易在警告信息中定位问题。

函数传入或传出的流传输必须按引用传递,

void stream_function (
	hls::stream<uint8_t> &strm_out,
	hls::stream<uint8_t> &strm_in,
	uint16_t strm_len
)
  • 1
  • 2
  • 3
  • 4
  • 5

Vivado HLS 支持阻塞访问方式和非阻塞访问方式。

非阻塞访问只能作为 FIFO 接口来实现。
作为 ap_fifo 端口实现并以 AXI4-Stream 资源定义的流传输端口不得使用非阻塞访问。

阻塞读写/Blocking Reads and Writes
对hls::stream<> 对象的基本访问为阻塞读取/写入。这些访问是使用类方法完成的。这些方法会停止(阻止) 对空的流传输 FIFO 的读操作以及对满的流传输 FIFO 的写操作, 直至相应的ap_hs 接口协议的流传输完成握手为止。

//Blocking Write Methods
// Usage of void write(const T & wdata)
hls::stream my_stream;
int src_var = 42;
my_stream.write(src_var); // or my_stream << src_var;
  • 1
  • 2
  • 3
  • 4
  • 5

“<<”运算符已重载, 可按相似方式应用于 C++ 流传输(例如, iostreams 和 filestreams) 的流插入运算符。要写入的
hls::stream<> 对象将作为左侧实参提供, 而变量则作为右侧实参写入。

//Blocking Read Methods
// Usage of void read(T &rdata)
hls::stream my_stream;
int dst_var;
my_stream.read(dst_var); //or int dst_var = my_stream.read(); //or my_stream >> dst_var;
  • 1
  • 2
  • 3
  • 4
  • 5

或者, 通过将流传输赋值(例如, 使用 = 或 +=) 给左侧对象, 可读取流传输中的下一个对象。
或者,“>>”运算符已重载, 支持以相似方式用于 C++ 流传输(例如, iostreams 和 filestreams) 的流提取运算符。

//Non-Blocking Writes
//此方法会尝试将 src_var 变量推送到 my_stream 流传输, 如果成功, 则返回布尔值 true。否则返回 false, 队列
不受影响。
// Usage of void write_nb(const T & wdata)
hls::stream my_stream;
int src_var = 42;
if (my_stream.write_nb(src_var)) {
// Perform standard operations
…
} else {
// Write did not occur
return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Fullness Test
bool full(void)
仅当 hls::stream<> 对象已满时返回 true。

// Usage of bool full(void)
hls::stream my_stream;
int src_var = 42;
bool stream_full;
stream_full = my_stream.full();
  • 1
  • 2
  • 3
  • 4
  • 5

Non-Blocking Read
bool read_nb(T & rdata)
此方法会尝试从流传输中读取值, 成功则返回 true。否则返回 false, 队列不受影响。

Emptiness Test
bool empty(void)
如果 hls::stream<> 为空, 则返回 true。

// Usage of bool empty(void)
hls::stream my_stream;
int dst_var;
bool stream_empty;
stream_empty = my_stream.empty();
  • 1
  • 2
  • 3
  • 4
  • 5

控制 RTL FIFO 深度
对于使用流传输数据的大部分设计, 默认 RTL FIFO 深度 2 足矣。每次仅处理一个采样的流传输数据。
对于执行实现所需的 FIFO 深度大于 2 的多速率设计, 必须判定(并使用 STREAM 指令设置) 完成 RTL 仿真所需的深
度。如果 FIFO 深度不足, RTL 协同仿真将停滞。
对于包含已声明的 hls::stream<> 对象(或者实参列表中已使用或包含该对象) 的函数, 右键单击并执行以下操作:
• 选中 STREAM 指令。
• 使用流传输变量的名称手动填充 variable 字段。
或者可以:
• 在 directives.tcl 文件中手动指定 STREAM 指令, 或
• 在 source 中添加该指令作为编译指示。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/425738
推荐阅读
相关标签
  

闽ICP备14008679号