我试图查看是否可以实例化vivado_hls中具有hls :: stream <>引用成员的类,以便我可以直接读取/写入流,而不必将流作为参数传递给呼叫链。
注意:这是在vivado_hls 2018.2中,此项目的顶级模块是“ ModuleX” 考虑下面的简化方案:
#include <hls_stream.h>
#include <ap_int.h>
using hls_int = ap_uint<32>;
class X
{
private:
hls::stream<hls_int> &s1;
hls::stream<hls_int> &s2;
public:
X(hls::stream<hls_int> &_s1, hls::stream<hls_int> &_s2) :
s1(_s1), s2(_s2)
{}
void Run()
{
hls_int s = s2.read();
hls_int out = s * 2;
s1.write(out);
}
};
void ModuleX(hls::stream<hls_int> &s1, hls::stream<hls_int> &s2)
{
#pragma HLS INTERFACE ap_ctrl_none PORT=return
#pragma HLS STREAM VARIABLE=s1 DEPTH=1
#pragma HLS STREAM VARIABLE=s2 DEPTH=1
static X x {s1, s2};
x.Run();
}
使用这种方法时,出现以下错误:ERROR: [SYNCHK 200-11] ClassWithStreamRefs.cpp:18: Constant 'x.s2.V.V' has an unsynthesizable type 'i32P*' (possible cause(s): pointer to pointer or global pointer).
我了解到,在后台,编译器可能会将引用存储为指向流的指针,但就我所考虑的情况而言,这应该是该工具的一个错误,因为它被阻塞了,我认为是有效的HLS。
希望有另一种方法可以实现我要查找的内容(引用,而不是值存储在类中)。
我尝试过的其他方法如下。但是,这是非常不希望的,因为该方法增加了2个时钟周期的延迟(在入站和出站每个都有1个时钟周期-毫无道理)。
#include <hls_stream.h>
#include <ap_int.h>
using hls_int = ap_uint<32>;
class X
{
public:
hls::stream<hls_int> s1;
hls::stream<hls_int> s2;
X()
{
#pragma HLS STREAM VARIABLE=s1 DEPTH=1
#pragma HLS STREAM VARIABLE=s2 DEPTH=1
}
void Run()
{
hls_int s = s2.read();
hls_int out = s * 2;
s1.write(out);
}
};
void ModuleX(hls::stream<hls_int> &s1, hls::stream<hls_int> &s2)
{
#pragma HLS INTERFACE ap_ctrl_none PORT=return
#pragma HLS INLINE
static X x;
x.s2.write(s2.read());
x.Run();
s1.write(x.s1.read());
}
这是一个示例tcl脚本(尽管它基本上只是由vivado_hls自动生成的)
open_project ClassWithStreamRef
set_top ModuleX
add_files ClassWithStreamRefs.cpp -cflags "-std=c++11"
open_solution "solution1"
set_part {xczu19eg-ffvc1760-2-i} -tool vivado
create_clock -period 10 -name default
csynth_design
答案 0 :(得分:0)
我不确定底层机制,但是删除static
限定符会使Vivado HLS 2018.2合成示例。但是,这会在每次顶级函数调用时创建一个X
的新实例,因此其字段不会保留。下面的示例通过在顶部函数中添加另一个用于持久化的静态变量并将其通过引用传递给X
的构造函数来解决。
#include <hls_stream.h>
#include <ap_int.h>
using hls_int = ap_uint<32>;
struct State
{
hls_int counter;
};
class X
{
private:
hls::stream<hls_int> &s1;
hls::stream<hls_int> &s2;
State& state;
public:
X(hls::stream<hls_int> &_s1, hls::stream<hls_int> &_s2, State& _state) :
s1(_s1), s2(_s2), state(_state)
{}
void Run()
{
hls_int s = s2.read();
s1.write(s + state.counter++);
}
};
void ModuleX(hls::stream<hls_int> &s1, hls::stream<hls_int> &s2)
{
#pragma HLS INTERFACE ap_ctrl_none PORT=return
#pragma HLS STREAM VARIABLE=s1 DEPTH=1
#pragma HLS STREAM VARIABLE=s2 DEPTH=1
static State state {0};
X x {s1, s2, state};
x.Run();
}