HLS中数据的合并与拆分
在用HLS生成IP的过程中,由于需要充分使用接口的带宽,所以一般我们在输入端将高位宽的数据拆分后作为输入使用,在输出端对数据进行合并后再进行输出。这是我们在设计IP中经常出现的问题,本文总结一下自己在最近的工作中进行数据拆分和合并的经验。
数据拆分
1、拆分后的数据类型与原数据类型一致
//输入的数据数量为IMAGE_SIZE,输出的数据数量为(IMAGE_SIZE<<5)
void data_split(ap_uint<512> *data_in,ap_uint<16> *data_out){
int m,n;
int start_addr = 0;
ap_uint<16> data_out_temp;
ap_uint<512> data_in_temp;
for(m = 0;m < IMAGE_SIZE; m++){
memcpy(&data_in_temp, &data_in[start_addr], 32 * sizeof(ap_uint<16>));
for(n = 0; n < 32; n++){
data_out_temp = data_in_temp(((n+1)<<4)-1,(n<<4));
data_out[(m<<5)+n] = data_out_temp;
}
start_addr = start_addr + 1;
}
}
2、拆分后的数据类型与原数据类型不一致
//输入的数据数量为IMAGE_SIZE,输出的数据数量为(IMAGE_SIZE<<5)
void data_split(ap_uint<512> *data_in,ap_ufixed<16, 1, AP_TRN, AP_WRAP> *data_out){
int m,n;
int start_addr = 0;
ap_uint<16> data_mid_temp;
ap_ufixed<16, 1, AP_TRN, AP_WRAP> data_out_temp;
ap_uint<512> data_in_temp;
for(m = 0;m < IMAGE_SIZE; m++){
memcpy(&data_in_temp, &data_in[start_addr], 32 * sizeof(ap_uint<16>));
for(n = 0; n < 32; n++){
data_mid_temp = data_in_temp(((n+1)<<4)-1,(n<<4));
data_out_temp(15,0) = data_mid_temp(15,0);
data_out[(m<<5)+n] = data_out_temp;
}
start_addr = start_addr + 1;
}
}
注意数据类型不一致的时候需要再加一个中间变量data_out_temp
。
数据合并
1、合并后的数据类型与原数据类型一致
//输入的数据数量为IMAGE_SIZE,输出的数据数量为(IMAGE_SIZE>>5)
void data_merge(ap_uint<16> *data_in,ap_uint<512> *data_out){
int i ,j;
ap_uint<16> data_in_temp;
ap_uint<512> data_out_temp;
for(i = 0;i < (IMAGE_SIZE>>5); i++){
for(j = 0; j < 32 ; j++){
data_in_temp = data_in[(i<<5)+j];
data_out_temp(((j+1)<<4)-1,(j<<4)) = data_in_temp(15,0);
}
data_out[i] = data_out_temp;
}
}
2、合并后的数据类型与原数据类型不一致
//输入的数据数量为IMAGE_SIZE,输出的数据数量为(IMAGE_SIZE>>5)
void data_merge(ap_ufixed<16, 1, AP_TRN, AP_WRAP> *data_in,ap_uint<512> *data_out){
int i ,j ,k;
ap_ufixed<16, 1, AP_TRN, AP_WRAP> data_in_temp;
ap_uint<16> data_mid_temp;
ap_uint<512> data_out_temp;
ap_uint<1> bool_temp;
for(i = 0;i < (IMAGE_SIZE>>5); i++){
for(j = 0; j < 32 ; j++){
data_in_temp = data_in[(i<<5)+j];
for(k = 0; k < 16; k++){
bool_temp = data_in_temp(k,k);
data_mid_temp(k,k) = bool_temp;
}
data_out_temp(((j+1)<<4)-1,(j<<4)) = data_mid_temp(15,0);
}
data_out[i] = data_out_temp;
}
}
经验之谈
自己总结的经验就是在做数据间位宽和类型的转换时,必须要保持其中的一项属性与原数据相同;数据合并也是同理。