#include
#include "HLS/hls.h"
component int dut(int a, int *b, int i) {
return a*b[i];
}
int main()
{
int a=3;
int b[4] = {1,2,3,4};
int ret;
ret = dut(3,b,2);
printf("ret:%d\n",ret);
return 0;
}
通过字节使能ff 低8bit为有效,为什么是0000000400000003 因为从i=2后的地址读取数据了,但是因为字节使能的原因 ,所以 03 有效与a=3相乘,结果为9
如果组件dut把busy信号拉高,那么调用dut的模块需要把start信号拉高直到busy拉低;如果dut的下游部件把stall信号拉高,那么dut需要将done信号拉高直到stall信号拉低。
白嫖知识:
#include
#include "HLS/hls.h"
// Blocking read
component void foo (ihc::stream_in<int> &a) {
int x = a.read(); //阻塞从组件内部使用的读调用
}
// Non-blocking read
component void foo_nb (ihc::stream_in<int> &a) {
bool success = false;
/*从组件内部使用的非阻塞读调用。
如果读取是有效的,则将success bool设置为true。
如果使用tryRead,则组件的x86-64结果可能与FPGA结果不匹配,因为仿真没有建模阻塞和非阻塞读取的硬件行为。*/
int x = a.tryRead(success);
if (success) {
// x is valid
}
}
int main() {
ihc::stream_in<int> a;
ihc::stream_in<int> b;
for (int i = 0; i < 10; i++) {
a.write(i); //从测试台中使用阻塞写入调用来填充要发送到组件的FIFO
b.write(i);
}
foo(a);
foo_nb(b);
}
#include
#include "HLS/hls.h"
// Blocking write
component void foo (ihc::stream_out<int> &a) {
static int count = 0;
for(int idx = 0; idx < 5; idx ++){
a.write(count++); // Blocking write 阻塞组件的写调用
}
}
// Non-blocking write
component void foo_nb (ihc::stream_out<int> &a) {
static int count = 0;
for(int idx = 0; idx < 5; idx ++){
bool success = a.tryWrite(count++); // Non-blocking write 组件的非阻塞写调用。返回值表示写入是否成功。
if (success) {
// write was successful
}
}
}
int main() {
ihc::stream_out<int> a;
ihc::stream_out<int> b;
foo(a); // or foo_nb(a);
foo_nb(b);
// copy output to an array
int outputData[5];
for (int idx = 0; idx < 5; idx++) {
outputData[idx] = a.read(); //从测试台中使用阻塞读调用从组件中读回数据
}
int outputData_b[5];
for (int idx = 0; idx < 5; idx++) {
outputData_b[idx] = b.read(); //从测试台中使用非阻塞读调用从组件中读回数据
}
}
在流接口上公开starttofpacket和endofpacket边带信号,可以被基于读写的包访问
仅当设置了usesPackets时可用。
用带外的starttofpacket和endofpacket信号阻塞读取。
#include
#include "HLS/hls.h"
component int reduce_sum(
ihc::stream_in<int,ihc::usesPackets<true> > &int_in
)
{
int val; int sum = 0;
bool start_of_packet = false;
bool end_of_packet = false;
while(!start_of_packet)
val = int_in.read(start_of_packet,end_of_packet);
sum += val;
while(!end_of_packet)
{
val = int_in.read(start_of_packet,end_of_packet);
sum += val;
}
return sum;
}
int main()
{
ihc::stream_in<int,ihc::usesPackets<true> > a;
int sum;
for (int i = 0; i < 5; i++) {
bool start_of_packet = (i==0);
bool end_of_packet = (i==5-1);
a.write(i,start_of_packet,end_of_packet); //从测试台中使用阻塞写入调用来填充要发送到组件的FIFO
}
sum = reduce_sum(a);
printf("sum:%d\n",sum);
return 0;
}
组件可以通过Avalon内存映射与外部内存接口mm_master<>。您可以使用函数指针参数或引用参数隐式指定Avalon MM Master接口,也可以显式使用“HLS/hls .h”头文件中定义的mm_master<>类。
下面的代码示例仲裁加载和存储指令,这些指令来自组件顶级模块上单个接口的两个指针解引用。这个接口的数据总线宽度为64位,地址宽度为64位,固定延迟为1。
#include
#include
component void dut(int *prt1,int *prt2)
{
*prt1 += *prt2;
*prt2 += prt1[1];
}
int main()
{
int x[2]={0,1};
int y = 2;
dut(x,&y);
return 0;
}
这个示例演示了如何使用显式mm_master类为特定内存接口优化前面的代码片段。mm_master类有一个已定义的模板,它具有以下特征:
通过定义这些特征,可以声明系统在两个时钟周期之后返回有效的读数据,并且接口在读写时从不停止,但是系统必须能够提供两个不同的内存。一个唯一的空间被期望对应一个唯一的物理内存。如果将具有相同空间的多个Avalon-MM Master接口连接到相同的物理内存,那么Intel HLS编译器无法确保任何内存依赖项的功能正确性。
#include
#include
// #ifndef DEBUG_TYPEDEF
#define DEBUG_TYPEDEF 1
// #endif
//组件的每个参数都会生成地址的输入(参数)管道
#if DEBUG_TYPEDEF
typedef ihc::mm_master< int,ihc::dwidth<256>,
ihc::awidth<32>,
ihc::aspace<1>,
ihc::latency<2> >Master1;
typedef ihc::mm_master< int,ihc::dwidth<256>,
ihc::awidth<32>,
ihc::aspace<4>,
ihc::latency<2> >Master2;
component void dut(Master1 &mm1,Master2 &mm2)
{
*mm1 += *mm2;
*mm2 += mm1[1];
}
#else
component void dut(
ihc::mm_master< int,ihc::dwidth<256>,ihc::awidth<32>,ihc::aspace<1>,ihc::latency<2> > &mm1,
ihc::mm_master< int,ihc::dwidth<256>,ihc::awidth<32>,ihc::aspace<4>,ihc::latency<2> > &mm2)
{
*mm1 += *mm2;
*mm2 += mm1[1];
}
#endif
int main()
{
int x[2]={1,2};
int y = 3;
//使用Avalon内存映射(MM)主类实例的组件
//(mm_master<>)来描述它们的内存接口,
//必须在testbench中为每个mm_master参数创建一个mm_master<>对象。
//创建构造函数,来实例化mm_master<>对象
//ihc::mm_master mm(void* ptr, int size, bool use_socket=false);
#if DEBUG_TYPEDEF
Master1 mm_x(x,2*sizeof(int),false);
Master2 mm_y(&y,1*sizeof(int),false);
#else
ihc::mm_master<int,ihc::dwidth<256>,ihc::awidth<32>,ihc::aspace<1>,ihc::latency<2> > mm_x(x,2*sizeof(int),false);
ihc::mm_master<int,ihc::dwidth<256>,ihc::awidth<32>,ihc::aspace<4>,ihc::latency<2> > mm_y(&y,1*sizeof(int),false);
#endif
//调用组件
dut(mm_x,mm_y);
return 0;
}
Intel HLS Compiler提供了两种不同类型的从接口,您可以在组件中使用它们。一般来说,较小的标量输入应该使用从寄存器。如果您打算将大数组复制到组件中或从组件中复制出来,那么应该使用从属内存。
#include
#include
hls_avalon_slave_component
component int dut(int a,int b)
{
return a*b;
}
int main()
{
int a=2;
int b=3;
int y;
y = dut(a,b);
printf("y=%d",y);
return 0;
}
#include
#include
hls_avalon_slave_component
component int dut(
int a,
hls_avalon_slave_register_argument int b)
{
return a*b;
}
int main()
{
int a=2;
int b=3;
int y;
y = dut(a,b);
printf("y=%d",y);
return 0;
}
#include
#include
hls_avalon_slave_component
component int dut(
hls_avalon_slave_memory_argument(5*sizeof(int)) int *a,
hls_avalon_slave_memory_argument(5*sizeof(int)) int *b
)
{
int i;
int sum=0;
for(i=0;i<5;i++)
{
sum = sum + a[i] * b[i];
//printf("a[%d]%d",i,a[i]);
}
return sum;
}
int main()
{
int a[5] = {1,2,3,4,5};
int b[5] = {1,2,3,4,5};
int sum;
sum = dut(a,b);
printf("sum=%d",sum);
return 0;
}
#include
#include
component int dut(
hls_stable_argument int a,
hls_stable_argument int b
)
{
return a*b;
}
int main()
{
int a=2;
int b=3;
int ret;
ret = dut(a,b);
return 0;
}
Feature | Description |
---|---|
hls_conduit_argument | Implement the argument as an input conduit that is synchronous to the component call (start and busy).将参数实现为与组件调用(start和busy)同步的输入管道。 |
hls_avalon_slave_register_argument | Implement the argument as a register that can be read from and written to over an Avalon-MM slave interface.将参数实现为一个可以通过Avalon-MM从接口读写的寄存器。 |
hls_avalon_slave_memory_argument | Implement the argument, in on-chip memory blocks, which can be read from or written to over a dedicated slave interface.在片上内存块中实现参数,它可以在专用的从接口上读取或写入。 |
hls_stable_argument | A stable argument is an argument that does not change while there is live data in the component (that is, between pipelined function invocations).稳定参数是当组件中有实时数据时(即在管道函数调用之间)不发生更改的参数。 |