我的函数:float FuzzyPID::realize(float t,float a) ;
其中t --> target value , a --> actual value;
该函数变量为指针形式,且为被多次访问的指针; 因此查阅ug902文档解释:
1 此代码产生的RTL设计将读取1次输入端口,写入1次输出端口。与任何标准C语言编译器一样,Vivado HLS将优化掉多余的指针访问。要按照“预期”实现对两个变量的多次读写,必须将指针指定为volatile类型。
2
3 后面ug902又指出:
强烈建议使用hls::stream类实现所需要的行为。
4 查阅HLS流传输库
数据流传输的数据样本从第一个样本开始按照顺序发送。流传输不需要地址管理。C中很难对使用流传输数据的设计进行建模。使用指针执行多次读取和/或写入访问的方法可能会引发问题,因为其中隐含了类型限定符以及测试激励文件构造方式的要求。
hls::stream类只限定在C++设计中使用,不支持流传输数组。
5 看结构体的用法(因为在hls解决pointer的问题种指出使用结构体定义指针变量的方法,但我对结构体的base knowledgement又忘掉了):
1 C语言中,结构体允许将不同类型数据组成组合型的数据结构。因此,当想把不同类型的关联数据存放在一起时,可以采用结构体的数据结构。
在参考资料中出现的结构体定义类型属于:在声明的同时定义变量
一般形式为:
struct 结构体类型名{
成员表列;
}变量名表列;
//1 声明和定义变量放在一起,
struct UDP_Server_Thread_Para{
void *pData;
int Len;
}UDPThreadPara1,UDPThreadPara2;
int main(){
UDPThreadPara1.pData="hello";
UDPThreadPara1.len=1;
UDPThreadPara2.pData="world";
UDPThreadPara2.len=2;
struct UDP_Server_Thread_Pata UDPThreadPara3; //新增该结构体类型变量
UDPThreadPara3.pData="!!";
UDPThreadPara3.len=3;
return 0;
}
//2 结构体变量的初始化
struct UDP_Server_Thread_Para{
void *pData;
int len;
}UDPThreadPara1={"I LOVE CHINA", 12}, UDPThreadPara2={"O O O", 21};
//也可以这样初始化
struct UDP_Server_Thread_Para{
void *pData;
int Len;
}UDPThreadPara1,UDPThreadPara2;
UDPThreadPara1.pData="hello";
UDPThreadPara1.len=1;
UDPThreadPara2.pData="world";
UDPThreadPara2.len=2;
6 HLS中接口综合和多次访问指针
使用多次访问的指针可能会在综合后引发意外行为。
#include "pointer_stream_better.h"
void pointer_stream_better(volatile dout_t *d_o, volatile din_t *d_i){
din_t acc=0;
acc+=*d_i;
axx+=*d_i;
*d_o=acc;
acc+=*d_i;
acc+=*d_i;
*d_o=acc;
}
该段代码,在测试激励文件上,除了为d_i提供一个值之外,无法执行其他任何操作,或者除了写入之外,无法验证对d_o的写入,尽管支持多次访问指针,但仍旧强烈建议使用hls::srteam类实现所需要的行为。
7 HLS流传输库
(1)流传输库是一种数据传输形式,其中数据样本从第一个样本开始按照顺序发送。流传输不需要地址管理。 在C中很难使用流传输数据的设计进行建模,使用指针执行多次读取/写入访问的方法可能会引发问题,其中隐含了类型限定符以及测试激励文件构造方式的要求。
(2)VivadoHLS提供了hls::stream<>用于对流传输数据结构进行建模。
hls::stream<>的行为与无限深度的FIFO相似。无需定义hls::stream<>的大小;
按顺序对其执行读取和写入。从hls::stream<>读取数据之后,无法再次对其进行读取。
顶层接口上的hls::stream<>默认情况下使用ap_fifo接口来实现;
设计内部的hls::stream<>作为FIFO来实现,深度为2,最优化指令STREAM用于更改此默认大小。
hls::stream类应时钟在函数之间 作为C++ 参考实参 来进行传递。
hls::stream类 仅限在C++设计中使用,不支持流传输数组!!!
7.2 C语言建模与RTL实现
数据流在软件、测试激励文件中进行RTL协同仿真期间,作为无限队列来建模。在C++中对数据流进行仿真无需满足任意深度。数据流可以在函数内部使用,也可以在函数接口使用。内部数据流可作为函数参数来进行传递。
数据流仅限于在C++的设计中使用,每个hls::stream<>对象都仅限单一进程写入,且仅限单一进程读取。如果在顶层接口上使用hls::stream,默认在RTL中会将其作为FIFO接口(ap_fifo)来实现,但可选择将其作为握手接口ap_hs或作为AXI_stream接口(axis)来实现。
如果在设计函数中使用hls::stream并将其综合到硬件中,那么会将其作为FIFO实现,且默认深度为2.在某些情况下如使用内插时,可能必须增大FIFO深度以确保FIFO可保存硬件生成的所有元素。如果无法确保FIFO大小足以保存硬件生成的所有数据样本,则可能导致设计停滞。 FIFO深度可使用STREAM指令搭配depth选项调整。(这些在HSL GUI中可以自行设计,easy thing, little case.
如果使用hls:stream在不同任务(子函数或循环)间传输数据,应立即考量在不同任务间存在数据流传输的DATAFLOW区域内实现这些任务。默认非DATAFLOW行为是完成每一项任务后再开始下一项任务,在此情况下必须确保用于实现hls::stream变量的FIFO大小足以保存生产者任务所生成的所有数据采样。否则会出现ERROR:[ XFORM 203-7633]
数据传输可定义为局部或全局。局部流传输始终作为内部FIFO实现。全局流传输可作为内部FIFO或端口来实现:
1 仅读取或者仅写入的全局定义的流传输推断为顶层RTL块的外部端口;
2 支持读取和写入的全局定义的流传输,位于顶层函数下的层级内,作为内部FIFO实现。
全局作用域内定义的流传输遵循的规则与任何其他全局变量相同。
8 使用HLS流传输
使用hls::stream