使用vitis实现硬件代码时,经常遇到不是整拍对齐的情况,比如:
ap_uint<128> a;
ap_uint<64> b10;
int pad,pos;
/// 计算pos,pad .....
a(pos-1,0) = bpad(63,pos);
a(63+pos,pos) = bpad+1;
a(127,64+pos)=bpad+2;
上述代码要3拍才能完成,如果做到1拍需要做以下优化
ap_uint<64>& get_one_pad(ap_uint<64>& data1,ap_uint<64>& data2,int pos)
{
ap_uint<64> data;
data(63-pos,0) = data1(63,pos);
data(63,64-pos)=data2(pos-1,0);
return data;
}
///**************************************************************************************
ap_uint<128> a;
ap_uint<64> b10;
int pad,pos;
/// 计算pos,pad .....
/// 1 这块代码的目的是将b中需要用到的数据copy出来,copy两份是为了后面赋值避免冲突
ap_uint<64> x13;
ap_uint<64> x23;
for( int i=0;i<2;i++)
{
x1i = bpad;
x2i = bpad;
}
/// 2这块代码的目的是将数据分别放到两个64bit区域
ap_uint<64> d2;
d0 = get_one_pad(x10,x21,pos);
d1 = get_one_pad(x11,x22,pos);
/// 3最终赋值
a(63,0) = d0;
a(127,64)=d1;
上述代码通过三步解决了每次数据操作都是整拍的问题,这样后续即使一拍无法完成,也可以流水打拍完成,比如a如果是ram,就可以方便的流水打拍了。
ps:在实现上述功能的时候发现vitis对函数inline是在verilog层次的,就是说它先把c代码编译成verilog在inline,这样导致本来函数在从c到verilog过程中可以优化的地方无法优化了。比如:get_one_pad函数如果inline就无法一拍完成了,这种情况也不能用pipeline,只能让编译器自动生成