Program Listing for File xf_filter2d_aie.hpp
↰ Return to documentation for file (/tmp/ws/src/vitis_common/include/aie/imgproc/xf_filter2d_aie.hpp
)
/*
* Copyright 2021 Xilinx, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <adf.h>
//#include "../include.h"
#ifndef _AIE_FILTER2D_H_
#define _AIE_FILTER2D_H_
namespace xf {
namespace cv {
namespace aie {
int32_t kernel_coeff[16] = {64, 128, 64, 128, 256, 128, 64, 128, 64};
int image_width = 128;
int image_height = 32;
int stride = 128;
void filter2D_api(input_window_int32* img_in, output_window_int32* img_out) {
v8int32* restrict ptr_img_buffer = (v8int32*)img_in->ptr;
v8int32* restrict ptr_img_out = (v8int32*)img_out->ptr;
v32int32 data_buf;
v16int32 data_buf1;
v16int32 data_buf2;
v8int32 data_out;
v8acc80 acc;
v8int32* restrict ptr_coeff_buffer = (v8int32*)kernel_coeff;
v8int32 kernel_vec0 = *(ptr_coeff_buffer)++; // 1st 8 kernel values (0 .. 7)
v8int32 kernel_vec1 = *(ptr_coeff_buffer)++; // 2nd 8 kernel values (8 .. 15)
v8int32* restrict ptr0 = ptr_img_buffer;
v8int32* restrict ptr1 = ptr_img_buffer + 1 * stride / PARALLEL_FACTOR_32b;
v8int32* restrict ptr2 = ptr_img_buffer + 2 * stride / PARALLEL_FACTOR_32b;
v8int32* restrict ptr_out = ptr_img_out;
// 3x3 kernel positions
//
// 0 1 2
// 3 4 5
// 6 7 8
// **************************************************************************
// Unrolling loops over rows and columns to support the different image regions
// **************************************************************************
// **************************************************************************
// First row filtering, regions 6, 2, 7
// **************************************************************************
{
// **************************************************************************
// Region 6
// **************************************************************************
// row 1 data used twice (or we use 0)
data_buf = upd_w(data_buf, 0, *(ptr0++)); // r1:00++07|_________|_________|_________
acc = lmul8(data_buf, 0, 0x65432100, kernel_vec0, 0, 0); // kernel 0 (r1:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:00..07)
data_buf = upd_w(data_buf, 1, *(ptr0--)); // r1:00..07|r1:08++15|_________|_________
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec0, 2, 0); // kernel 2 (r1:01..08)
// 2nd row (uses same data as row 1)
acc = lmac8(acc, data_buf, 0, 0x65432100, kernel_vec0, 3, 0); // kernel 3 (r1:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r1:00..07)
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec0, 5, 0); // kernel 5 (r1:01..08)
// 3rd row (uses row 2 data)
data_buf = upd_w(data_buf, 0, *(ptr1++)); // r2:00++07|_________|_________|_________
acc = lmac8(acc, data_buf, 0, 0x65432100, kernel_vec0, 6, 0); // kernel 6 (r2:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 7, 0); // kernel 6 (r2:00..07)
data_buf = upd_w(data_buf, 1, *(ptr1--)); // r2:00..07|r1:08++15|_________|_________
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec1, 0, 0); // kernel 8 (r2:01..08)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
ptr0++;
ptr1++;
// **************************************************************************
// Region 2
// **************************************************************************
// row 1 data used twice (or we use 0)
for (int j = 0; j < image_width - 2 * PARALLEL_FACTOR_32b; j += PARALLEL_FACTOR_32b) // 8x samples per loop
chess_prepare_for_pipelining {
// row 1 data used twice (or we use 0)
data_buf1 = upd_w(data_buf1, 1, *(ptr0--)); // _________|r1:08++15|_________|_________
acc = lmul8(data_buf1, 8, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:08..15)
data_buf1 = upd_w(data_buf1, 0, *(ptr0)); // r1:00++07|r1:08..15|_________|_________
ptr0 = ptr0 + 2;
acc = lmac8(acc, data_buf1, 7, 0x76543210, kernel_vec0, 0, 0); // kernel 0 (r1:07..14)
data_buf1 = upd_w(data_buf1, 0, *(ptr0)); // r1:16++23|r1:08..15|_________|_________
ptr0 = ptr0 - 2;
acc = lmac8(acc, data_buf1, 9, 0x76543210, kernel_vec0, 2, 0); // kernel 2 (r1:09..16)
// 2nd row
acc = lmac8(acc, data_buf1, 9, 0x76543210, kernel_vec0, 5, 0); // kernel 5 (r1:09..16)
data_buf1 = upd_w(data_buf1, 0, *(ptr0)); // r1:00++07|r1:08..15|_________|_________
ptr0 = ptr0 + 2;
acc = lmac8(acc, data_buf1, 8, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r1:08..15)
acc = lmac8(acc, data_buf1, 7, 0x76543210, kernel_vec0, 3, 0); // kernel 3 (r1:07..14)
// 3rd row
data_buf2 = upd_w(data_buf2, 1, *(ptr1--)); // _________|r2:08++15|_________|_________
acc = lmac8(acc, data_buf2, 8, 0x76543210, kernel_vec0, 7, 0); // kernel 7 (r2:08..15)
data_buf2 = upd_w(data_buf2, 0, *(ptr1)); // r2:00++07|r2:08..15|_________|_________
ptr1 = ptr1 + 2;
acc = lmac8(acc, data_buf2, 7, 0x76543210, kernel_vec0, 6, 0); // kernel 6 (r2:07..14)
data_buf2 = upd_w(data_buf2, 0, *(ptr1)); // r2:16++23|r2:08..15|_________|_________
acc = lmac8(acc, data_buf2, 9, 0x76543210, kernel_vec1, 0, 0); // kernel 8 (r2:09..16)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
}
ptr0--;
ptr1--;
// **************************************************************************
// Region 7
// **************************************************************************
// row 1 data used twice (or we use 0)
data_buf = upd_w(data_buf, 0, *(ptr0++)); // r1:00++07|_________|_________|_________
data_buf = upd_w(data_buf, 1, *(ptr0)); // r1:00..07|r1:08++15|_________|_________
acc = lmul8(data_buf, 7, 0x76543210, kernel_vec0, 0, 0); // kernel 0 (r1:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec0, 2, 0); // kernel 2 (r1:09..15)
// 2nd row
acc = lmac8(acc, data_buf, 7, 0x76543210, kernel_vec0, 3, 0); // kernel 3 (r1:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r1:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec0, 5, 0); // kernel 5 (r1:09..15)
// 3rd row
data_buf = upd_w(data_buf, 0, *(ptr1++)); // r2:00++07|_________|_________|_________
data_buf = upd_w(data_buf, 1, *(ptr1)); // r2:00..07|r2:08++15|_________|_________
acc = lmac8(acc, data_buf, 7, 0x76543210, kernel_vec0, 6, 0); // kernel 6 (r2:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 7, 0); // kernel 7 (r2:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec1, 0, 0); // kernel 8 (r2:09..15)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
// Increment row pointers to next row
ptr0 = ptr_img_buffer;
ptr1 = ptr_img_buffer + 1 * stride / PARALLEL_FACTOR_32b;
ptr2 = ptr_img_buffer + 2 * stride / PARALLEL_FACTOR_32b;
}
// end of first row processing
// **************************************************************************
// Middle rows filtering, regions 4, 1, 5
// **************************************************************************
for (int i = 0; i < image_height - 2; i++) {
// **********************************************************************
// Region 4
// **********************************************************************
data_buf = upd_w(data_buf, 0, *(ptr0++)); // r1:00++07|_________|_________|_________
acc = lmul8(data_buf, 0, 0x65432100, kernel_vec0, 0, 0); // kernel 0 (r1:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:00..07)
data_buf = upd_w(data_buf, 1, *(ptr0--)); // r1:00..07|r1:08++15|_________|_________
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec0, 2, 0); // kernel 2 (r1:01..08)
// 2nd row
data_buf = upd_w(data_buf, 0, *(ptr1++)); // r2:00++07|_________|_________|_________
acc = lmac8(acc, data_buf, 0, 0x65432100, kernel_vec0, 3, 0); // kernel 3 (r2:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r2:00..07)
data_buf = upd_w(data_buf, 1, *(ptr1--)); // r2:00..07|r2:08++15|_________|_________
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec0, 5, 0); // kernel 5 (r2:01..08)
// 3rd row
data_buf = upd_w(data_buf, 0, *(ptr2++)); // r3:00++07|_________|_________|_________
acc = lmac8(acc, data_buf, 0, 0x65432100, kernel_vec0, 6, 0); // kernel 6 (r3:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 7, 0); // kernel 6 (r3:00..07)
data_buf = upd_w(data_buf, 1, *(ptr2--)); // r3:00..07|r3:08++15|_________|_________
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec1, 0, 0); // kernel 8 (r3:01..08)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
ptr0++;
ptr1++;
ptr2++;
// **********************************************************************
// Region 1: generic case, border effect free
// **********************************************************************
for (int j = 0; j < image_width - 2 * PARALLEL_FACTOR_32b; j += PARALLEL_FACTOR_32b) // 16x samples per loop
chess_prepare_for_pipelining {
// row 1 data used twice (or we use 0)
data_buf1 = upd_w(data_buf1, 1, *(ptr0--)); // _________|r1:08++15|_________|_________
acc = lmul8(data_buf1, 8, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:08..15)
data_buf1 = upd_w(data_buf1, 0, *(ptr0)); // r1:00++07|r1:08..15|_________|_________
ptr0 = ptr0 + 2;
acc = lmac8(acc, data_buf1, 7, 0x76543210, kernel_vec0, 0, 0); // kernel 0 (r1:07..14)
data_buf1 = upd_w(data_buf1, 0, *(ptr0)); // r1:16++23|r1:08..15|_________|_________
acc = lmac8(acc, data_buf1, 9, 0x76543210, kernel_vec0, 2, 0); // kernel 2 (r1:09..16)
// 2nd row
data_buf2 = upd_w(data_buf2, 1, *(ptr1--)); // _________|r2:08++15|_________|_________
acc = lmac8(acc, data_buf2, 8, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r1:08..15)
data_buf2 = upd_w(data_buf2, 0, *(ptr1)); // r2:00++07|r2:08..15|_________|_________
ptr1 = ptr1 + 2;
acc = lmac8(acc, data_buf2, 7, 0x76543210, kernel_vec0, 3, 0); // kernel 3 (r1:07..14)
data_buf2 = upd_w(data_buf2, 0, *(ptr1)); // r2:16++23|r2:08..15|_________|_________
acc = lmac8(acc, data_buf2, 9, 0x76543210, kernel_vec0, 5, 0); // kernel 5 (r1:09..16)
// 3rd row
data_buf1 = upd_w(data_buf1, 1, *(ptr2--)); // _________|r3:08++15|_________|_________
acc = lmac8(acc, data_buf1, 8, 0x76543210, kernel_vec0, 7, 0); // kernel 7 (r1:08..15)
data_buf1 = upd_w(data_buf1, 0, *(ptr2)); // r3:00++07|r3:08..15|_________|_________
ptr2 = ptr2 + 2;
acc = lmac8(acc, data_buf1, 7, 0x76543210, kernel_vec0, 6, 0); // kernel 6 (r1:07..14)
data_buf1 = upd_w(data_buf1, 0, *(ptr2)); // r3:16++23|r3:08..15|_________|_________
acc = lmac8(acc, data_buf1, 9, 0x76543210, kernel_vec1, 0, 0); // kernel 8 (r1:09..16)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
}
ptr0--;
ptr1--;
ptr2--;
// **********************************************************************
// Region 5
// **********************************************************************
// row 1 data used twice (or we use 0)
data_buf = upd_w(data_buf, 0, *(ptr0++)); // r1:00++07|_________|_________|_________
data_buf = upd_w(data_buf, 1, *(ptr0)); // r1:00..07|r1:08++15|_________|_________
acc = lmul8(data_buf, 7, 0x76543210, kernel_vec0, 0, 0); // kernel 0 (r1:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec0, 2, 0); // kernel 2 (r1:09..15)
// 2nd row
data_buf = upd_w(data_buf, 0, *(ptr1++)); // r2:00++07|_________|_________|_________
data_buf = upd_w(data_buf, 1, *(ptr1)); // r2:00..07|r2:08++15|_________|_________
acc = lmac8(acc, data_buf, 7, 0x76543210, kernel_vec0, 3, 0); // kernel 3 (r2:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r2:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec0, 5, 0); // kernel 5 (r2:09..15)
// 3rd row
data_buf = upd_w(data_buf, 0, *(ptr2++)); // r3:00++07|_________|_________|_________
data_buf = upd_w(data_buf, 1, *(ptr2)); // r3:00..07|r3:08++15|_________|_________
acc = lmac8(acc, data_buf, 7, 0x76543210, kernel_vec0, 6, 0); // kernel 6 (r3:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 7, 0); // kernel 7 (r3:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec1, 0, 0); // kernel 8 (r3:09..15)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
// Increment row pointers to next row
ptr0 = ptr_img_buffer + (i + 1) * stride / PARALLEL_FACTOR_32b;
ptr1 = ptr_img_buffer + (i + 2) * stride / PARALLEL_FACTOR_32b;
ptr2 = ptr_img_buffer + (i + 3) * stride / PARALLEL_FACTOR_32b;
}
// **************************************************************************
// Last row filtering, regions 8, 3, 9
// **************************************************************************
{
// **************************************************************************
// Region 8
// **************************************************************************
// 1st row
data_buf = upd_w(data_buf, 0, *(ptr0++)); // r1:00++07|_________|_________|_________
acc = lmul8(data_buf, 0, 0x65432100, kernel_vec0, 0, 0); // kernel 0 (r1:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:00..07)
data_buf = upd_w(data_buf, 1, *(ptr0--)); // r1:00..07|r1:08++15|_________|_________
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec0, 2, 0); // kernel 2 (r1:01..08)
// 2nd row
data_buf = upd_w(data_buf, 0, *(ptr1++)); // r2:00++07|_________|_________|_________
acc = lmac8(acc, data_buf, 0, 0x65432100, kernel_vec0, 3, 0); // kernel 3 (r2:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r2:00..07)
data_buf = upd_w(data_buf, 1, *(ptr1--)); // r2:00..07|r2:08++15|_________|_________
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec0, 5, 0); // kernel 5 (r2:01..08)
// 3rd row (uses row 2 data)
acc = lmac8(acc, data_buf, 0, 0x65432100, kernel_vec0, 6, 0); // kernel 6 (r3:00,00..06)
acc = lmac8(acc, data_buf, 0, 0x76543210, kernel_vec0, 7, 0); // kernel 7 (r3:00..07)
acc = lmac8(acc, data_buf, 1, 0x76543210, kernel_vec1, 0, 0); // kernel 8 (r3:01..08)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
ptr0++;
ptr1++;
// **************************************************************************
// Region 3
// **************************************************************************
for (int j = 0; j < image_width - 2 * PARALLEL_FACTOR_32b; j += PARALLEL_FACTOR_32b) // 8x samples per loop
chess_prepare_for_pipelining {
// 1st row
data_buf1 = upd_w(data_buf1, 1, *(ptr0--)); // _________|r1:08++15|_________|_________
acc = lmul8(data_buf1, 8, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:08..15)
data_buf1 = upd_w(data_buf1, 0, *(ptr0)); // r1:00++07|r1:08..15|_________|_________
ptr0 = ptr0 + 2;
acc = lmac8(acc, data_buf1, 7, 0x76543210, kernel_vec0, 0, 0); // kernel 0 (r1:07..14)
data_buf1 = upd_w(data_buf1, 0, *(ptr0)); // r1:16++23|r1:08..15|_________|_________
acc = lmac8(acc, data_buf1, 9, 0x76543210, kernel_vec0, 2, 0); // kernel 2 (r1:09..16)
// 2nd row
data_buf2 = upd_w(data_buf2, 1, *(ptr1--)); // _________|r2:08++15|_________|_________
acc = lmac8(acc, data_buf2, 8, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r1:08..15)
data_buf2 = upd_w(data_buf2, 0, *(ptr1)); // r2:00++07|r2:08..15|_________|_________
ptr1 = ptr1 + 2;
acc = lmac8(acc, data_buf2, 7, 0x76543210, kernel_vec0, 3, 0); // kernel 3 (r1:07..14)
data_buf2 = upd_w(data_buf2, 0, *(ptr1)); // r2:16++23|r2:08..15|_________|_________
ptr1 = ptr1 - 2;
acc = lmac8(acc, data_buf2, 9, 0x76543210, kernel_vec0, 5, 0); // kernel 5 (r1:09..16)
// 3rd row (uses row 2 data)
acc = lmac8(acc, data_buf2, 9, 0x76543210, kernel_vec1, 0, 0); // kernel 8 (r1:09..16)
data_buf2 = upd_w(data_buf2, 0, *(ptr1)); // r2:00++07|r2:08..15|_________|_________
ptr1 = ptr1 + 2;
acc = lmac8(acc, data_buf2, 8, 0x76543210, kernel_vec0, 7, 0); // kernel 7 (r1:08..15)
acc = lmac8(acc, data_buf2, 7, 0x76543210, kernel_vec0, 6, 0); // kernel 6 (r1:07..14)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
}
ptr0--;
ptr1--;
// **************************************************************************
// Region 9
// **************************************************************************
data_buf = upd_w(data_buf, 0, *(ptr0++)); // r1:00++07|_________|_________|_________
data_buf = upd_w(data_buf, 1, *(ptr0)); // r1:00..07|r1:08++15|_________|_________
acc = lmul8(data_buf, 7, 0x76543210, kernel_vec0, 0, 0); // kernel 0 (r1:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 1, 0); // kernel 1 (r1:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec0, 2, 0); // kernel 2 (r1:09..15)
// 2nd row
data_buf = upd_w(data_buf, 0, *(ptr1++)); // r2:00++07|_________|_________|_________
data_buf = upd_w(data_buf, 1, *(ptr1)); // r2:00..07|r2:08++15|_________|_________
acc = lmac8(acc, data_buf, 7, 0x76543210, kernel_vec0, 3, 0); // kernel 3 (r2:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 4, 0); // kernel 4 (r2:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec0, 5, 0); // kernel 5 (r2:09..15)
// 3rd row (uses row 2 data)
acc = lmac8(acc, data_buf, 7, 0x76543210, kernel_vec0, 6, 0); // kernel 6 (r2:07..14)
acc = lmac8(acc, data_buf, 8, 0x76543210, kernel_vec0, 7, 0); // kernel 7 (r2:08..15)
acc = lmac8(acc, data_buf, 9, 0x66543210, kernel_vec1, 0, 0); // kernel 8 (r2:09..15)
// Store result
data_out = srs(acc, SRS_SHIFT);
*(ptr_out++) = data_out;
}
}
} // aie
} // cv
} // xf
#endif