HLS:has an unsynthesizable type (possible cause(s): pointer to pointer or global pointer).

我的函数:float FuzzyPID::realize(float t,float a) ;

其中t --> target value , a --> actual value; 

该函数变量为指针形式,且为被多次访问的指针; 因此查阅ug902文档解释:

1 此代码产生的RTL设计将读取1次输入端口,写入1次输出端口。与任何标准C语言编译器一样,Vivado HLS将优化掉多余的指针访问。要按照“预期”实现对两个变量的多次读写,必须将指针指定为volatile类型。

2 <ref:C语言volatile关键字—最易变的关键字_C语言中文网 (biancheng.net)>

volatile 是易变的,不稳定的;其修饰的变量表示可以被某些编译器未知的因素更改,如OS,硬件或其他线程等。 遇到这个关键字声明的变量,编译器对访问的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

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<T>对象,需要包含hls_stream.h头文件。数据对象流传输是通过指定类型和变量名称来定义的。其中数据类型T可以为:任何C++原生数据类型,HLS任意精度类型如ap_int<>或ap_ufixed<>,用户定义的结构体。PS:用户自定义的通用类或结构,所含方法、成员函数,不应用作为流传输变量的类型T。

 

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小菜鸡变形记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值