Program Listing for File xf_extra_utility.h

Return to documentation for file (/tmp/ws/src/vitis_common/include/imgproc/xf_extra_utility.h)

/*
 * Copyright 2019 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.
 */

#ifndef __XF_EXTRA_UTILITY_H__
#define __XF_EXTRA_UTILITY_H__

#include "../common/xf_common.hpp"
#include "../common/xf_video_mem.hpp"

namespace xf {
namespace cv {

// ======================================================================================
// Function to split hls::stream into 2 hls::stream
// ======================================================================================
template <int SRC_T, int ROWS, int COLS, int NPC>
void DuplicateStrm(hls::stream<XF_TNAME(SRC_T, NPC)>& _src_mat,
                   hls::stream<XF_TNAME(SRC_T, NPC)>& _dst1_mat,
                   hls::stream<XF_TNAME(SRC_T, NPC)>& _dst2_mat,
                   uint16_t img_height,
                   uint16_t img_width) {
    img_width = img_width >> XF_BITSHIFT(NPC);
    ap_uint<13> row, col;

Row_Loop:
    for (row = 0; row < img_height; row++) {
#pragma HLS LOOP_TRIPCOUNT min = ROWS max = ROWS
#pragma HLS LOOP_FLATTEN off
    Col_Loop:
        for (col = 0; col < img_width; col++) {
#pragma HLS LOOP_TRIPCOUNT min = COLS / NPC max = COLS / NPC
#pragma HLS pipeline
            XF_TNAME(SRC_T, NPC) tmp_src;
            tmp_src = _src_mat.read();
            _dst1_mat.write(tmp_src);
            _dst2_mat.write(tmp_src);
        }
    }
} // End of DuplicateStrm()
// ======================================================================================

// ======================================================================================
// Function to split hls::stream into 3 hls::stream
// ======================================================================================
template <int SRC_T, int ROWS, int COLS, int NPC>
void DuplicateStrm_3(hls::stream<XF_TNAME(SRC_T, NPC)>& _src_mat,
                     hls::stream<XF_TNAME(SRC_T, NPC)>& _dst1_mat,
                     hls::stream<XF_TNAME(SRC_T, NPC)>& _dst2_mat,
                     hls::stream<XF_TNAME(SRC_T, NPC)>& _dst3_mat,
                     uint16_t img_height,
                     uint16_t img_width) {
    img_width = img_width >> XF_BITSHIFT(NPC);
    ap_uint<13> row, col;

Row_Loop:
    for (row = 0; row < img_height; row++) {
#pragma HLS LOOP_TRIPCOUNT min = ROWS max = ROWS
#pragma HLS LOOP_FLATTEN off
    Col_Loop:
        for (col = 0; col < img_width; col++) {
#pragma HLS LOOP_TRIPCOUNT min = COLS / NPC max = COLS / NPC
#pragma HLS pipeline
            XF_TNAME(SRC_T, NPC) tmp_src;
            tmp_src = _src_mat.read();
            _dst1_mat.write(tmp_src);
            _dst2_mat.write(tmp_src);
            _dst3_mat.write(tmp_src);
        }
    }
} // End of DuplicateStrm_3()
// ======================================================================================

// ======================================================================================
// Function to split hls::stream into 4 hls::stream
// ======================================================================================
template <int SRC_T, int ROWS, int COLS, int NPC>
void DuplicateStrm_4(hls::stream<XF_TNAME(SRC_T, NPC)>& _src_mat,
                     hls::stream<XF_TNAME(SRC_T, NPC)>& _dst1_mat,
                     hls::stream<XF_TNAME(SRC_T, NPC)>& _dst2_mat,
                     hls::stream<XF_TNAME(SRC_T, NPC)>& _dst3_mat,
                     hls::stream<XF_TNAME(SRC_T, NPC)>& _dst4_mat,
                     uint16_t img_height,
                     uint16_t img_width) {
    img_width = img_width >> XF_BITSHIFT(NPC);
    ap_uint<13> row, col;

Row_Loop:
    for (row = 0; row < img_height; row++) {
#pragma HLS LOOP_TRIPCOUNT min = ROWS max = ROWS
#pragma HLS LOOP_FLATTEN off
    Col_Loop:
        for (col = 0; col < img_width; col++) {
#pragma HLS LOOP_TRIPCOUNT min = COLS / NPC max = COLS / NPC
#pragma HLS pipeline
            XF_TNAME(SRC_T, NPC) tmp_src;
            tmp_src = _src_mat.read();
            _dst1_mat.write(tmp_src);
            _dst2_mat.write(tmp_src);
            _dst3_mat.write(tmp_src);
            _dst4_mat.write(tmp_src);
        }
    }
} // End of DuplicateStrm_4()
// ======================================================================================

// ======================================================================================
// Function to split xf::cv::Mat into 2 xf::cv::Mat
// ======================================================================================
template <int SRC_T, int ROWS, int COLS, int NPC>
void duplicateMat(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _src,
                  xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst1,
                  xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst2) {
#pragma HLS inline off

#pragma HLS dataflow

    int _rows = _src.rows;
    int _cols = _src.cols;

    hls::stream<XF_TNAME(SRC_T, NPC)> src;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst1;

    for (int i = 0; i < _rows; i++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = ROWS
        for (int j = 0; j<(_cols)>> (XF_BITSHIFT(NPC)); j++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = COLS / NPC
#pragma HLS PIPELINE
#pragma HLS loop_flatten off
            src.write(_src.read(i * (_cols >> (XF_BITSHIFT(NPC))) + j));
        }
    }

    DuplicateStrm<SRC_T, ROWS, COLS, NPC>(src, dst, dst1, _rows, _cols);

    for (int i = 0; i < _rows; i++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = ROWS
        for (int j = 0; j<(_cols)>> (XF_BITSHIFT(NPC)); j++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = COLS / NPC
#pragma HLS PIPELINE
#pragma HLS loop_flatten off
            _dst1.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst.read());
            _dst2.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst1.read());
        }
    }
} // End of duplicateMat()
// ======================================================================================

// ======================================================================================
// Function to split xf::cv::Mat into 3 xf::cv::Mat
// ======================================================================================
template <int SRC_T, int ROWS, int COLS, int NPC>
void duplicateMat_3(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _src,
                    xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst1,
                    xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst2,
                    xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst3) {
#pragma HLS inline off

#pragma HLS dataflow

    int _rows = _src.rows;
    int _cols = _src.cols;

    hls::stream<XF_TNAME(SRC_T, NPC)> src;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst1;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst2;

    for (int i = 0; i < _rows; i++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = ROWS
        for (int j = 0; j<(_cols)>> (XF_BITSHIFT(NPC)); j++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = COLS / NPC
#pragma HLS PIPELINE
#pragma HLS loop_flatten off
            src.write(_src.read(i * (_cols >> (XF_BITSHIFT(NPC))) + j));
        }
    }

    DuplicateStrm_3<SRC_T, ROWS, COLS, NPC>(src, dst, dst1, dst2, _rows, _cols);

    for (int i = 0; i < _rows; i++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = ROWS
        for (int j = 0; j<(_cols)>> (XF_BITSHIFT(NPC)); j++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = COLS / NPC
#pragma HLS PIPELINE
#pragma HLS loop_flatten off
            _dst1.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst.read());
            _dst2.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst1.read());
            _dst3.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst2.read());
        }
    }
} // End of duplicateMat_3()
// ======================================================================================

// ======================================================================================
// Function to split xf::cv::Mat into 4 xf::cv::Mat
// ======================================================================================
template <int SRC_T, int ROWS, int COLS, int NPC>
void duplicateMat_4(xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _src,
                    xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst1,
                    xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst2,
                    xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst3,
                    xf::cv::Mat<SRC_T, ROWS, COLS, NPC>& _dst4) {
#pragma HLS inline off

#pragma HLS dataflow

    int _rows = _src.rows;
    int _cols = _src.cols;

    hls::stream<XF_TNAME(SRC_T, NPC)> src;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst1;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst2;
    hls::stream<XF_TNAME(SRC_T, NPC)> dst3;

    for (int i = 0; i < _rows; i++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = ROWS
        for (int j = 0; j<(_cols)>> (XF_BITSHIFT(NPC)); j++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = COLS / NPC
#pragma HLS PIPELINE
#pragma HLS loop_flatten off
            src.write(_src.read(i * (_cols >> (XF_BITSHIFT(NPC))) + j));
        }
    }

    DuplicateStrm_4<SRC_T, ROWS, COLS, NPC>(src, dst, dst1, dst2, dst3, _rows, _cols);

    for (int i = 0; i < _rows; i++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = ROWS
        for (int j = 0; j<(_cols)>> (XF_BITSHIFT(NPC)); j++) {
#pragma HLS LOOP_TRIPCOUNT min = 1 max = COLS / NPC
#pragma HLS PIPELINE
#pragma HLS loop_flatten off
            _dst1.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst.read());
            _dst2.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst1.read());
            _dst3.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst2.read());
            _dst4.write((i * (_cols >> (XF_BITSHIFT(NPC))) + j), dst3.read());
        }
    }
} // End of duplicateMat_4()
// ======================================================================================

// ======================================================================================
// Function to split xf::cv::Mat into 2 xf::cv::Mat
// ======================================================================================
template <int TYPE, int ROWS, int COLS, int NPPC>
void xFDuplicateMat(xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& in_mat,
                    xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat1,
                    xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat2) {
#pragma HLS INLINE OFF

    const int c_TRIP_COUNT = ROWS * COLS;
    int loopcount = in_mat.rows * (in_mat.cols >> XF_BITSHIFT(NPPC));

    for (int i = 0; i < loopcount; i++) {
#pragma HLS LOOP_TRIPCOUNT min = c_TRIP_COUNT max = c_TRIP_COUNT
#pragma HLS pipeline II = 1
        XF_TNAME(TYPE, NPPC) tmp = in_mat.read(i);
        out_mat1.write(i, tmp);
        out_mat2.write(i, tmp);
    }

} // End of xFDuplicateMat()
// ======================================================================================

// ======================================================================================
// Function to split xf::cv::Mat into 3 xf::cv::Mat
// ======================================================================================
template <int TYPE, int ROWS, int COLS, int NPPC>
void xFDuplicateMat_3(xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& in_mat,
                      xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat1,
                      xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat2,
                      xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat3) {
#pragma HLS INLINE OFF

    const int c_TRIP_COUNT = ROWS * COLS;
    int loopcount = in_mat.rows * (in_mat.cols >> XF_BITSHIFT(NPPC));

    for (int i = 0; i < loopcount; i++) {
#pragma HLS LOOP_TRIPCOUNT min = c_TRIP_COUNT max = c_TRIP_COUNT
#pragma HLS pipeline II = 1
        XF_TNAME(TYPE, NPPC) tmp = in_mat.read(i);
        out_mat1.write(i, tmp);
        out_mat2.write(i, tmp);
        out_mat3.write(i, tmp);
    }

} // End of xFDuplicateMat_3()
// ======================================================================================

// ======================================================================================
// Function to split xf::cv::Mat into 4 xf::cv::Mat
// ======================================================================================
template <int TYPE, int ROWS, int COLS, int NPPC>
void xFDuplicateMat_4(xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& in_mat,
                      xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat1,
                      xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat2,
                      xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat3,
                      xf::cv::Mat<TYPE, ROWS, COLS, NPPC>& out_mat4) {
#pragma HLS INLINE OFF

    const int c_TRIP_COUNT = ROWS * COLS;
    int loopcount = in_mat.rows * (in_mat.cols >> XF_BITSHIFT(NPPC));

    for (int i = 0; i < loopcount; i++) {
#pragma HLS LOOP_TRIPCOUNT min = c_TRIP_COUNT max = c_TRIP_COUNT
#pragma HLS pipeline II = 1
        XF_TNAME(TYPE, NPPC) tmp = in_mat.read(i);
        out_mat1.write(i, tmp);
        out_mat2.write(i, tmp);
        out_mat3.write(i, tmp);
        out_mat4.write(i, tmp);
    }

} // End of xFDuplicateMat_4()
// ======================================================================================

// ======================================================================================
// Function to set border in the extracted kernel sized block
// ======================================================================================
template <int K_ROWS, int K_COLS, typename SRC_T, int BORDER_T>
void xFSetBorder(xf::cv::Window<K_ROWS, K_COLS, SRC_T>& src_blk,
                 uint16_t _row,
                 uint16_t _col,
                 uint16_t _src_rows,
                 uint16_t _src_cols) {
#pragma HLS INLINE OFF

    uint16_t blk_t_idx, blk_b_idx;
    uint16_t blk_l_idx, blk_r_idx;

    blk_t_idx = (K_ROWS - _row - 1);
    blk_b_idx = (K_ROWS - (_row - _src_rows + 1) - 1);

    blk_l_idx = (K_COLS - _col - 1);
    blk_r_idx = (K_COLS - (_col - _src_cols + 1) - 1);

    for (uint16_t r = 0; r < K_ROWS; r++) {
#pragma HLS UNROLL
        for (uint16_t c = 0; c < K_COLS; c++) {
#pragma HLS UNROLL

            bool top_border = ((r < blk_t_idx) && (_row < K_ROWS - 1)) ? true : false;
            bool bottom_border = ((r > blk_b_idx) && (_row >= _src_rows)) ? true : false;
            bool left_border = ((c < blk_l_idx) && (_col < K_COLS - 1)) ? true : false;
            bool right_border = ((c > blk_r_idx) && (_col >= _src_cols)) ? true : false;

            uint16_t r_idx = r, c_idx = c;

            if (BORDER_T == XF_BORDER_REPLICATE) {
                r_idx = top_border ? blk_t_idx : bottom_border ? blk_b_idx : r;

            } else if (BORDER_T == XF_BORDER_CONSTANT) {
                r_idx = top_border ? (2 * blk_t_idx - r) : bottom_border ? (2 * blk_b_idx - r) : r;

            } else if (BORDER_T == XF_BORDER_CONSTANT) {
                r_idx = top_border ? (2 * blk_t_idx - r - 1) : bottom_border ? (2 * blk_b_idx - r + 1) : r;

            } else { // TODO: Need to add other modes support
                r_idx = r;
            }

            if (BORDER_T == XF_BORDER_REPLICATE) {
                c_idx = left_border ? blk_l_idx : right_border ? blk_r_idx : c;

            } else if (BORDER_T == XF_BORDER_CONSTANT) {
                c_idx = left_border ? (2 * blk_l_idx - c) : right_border ? (2 * blk_r_idx - c) : c;

            } else if (BORDER_T == XF_BORDER_CONSTANT) {
                c_idx = left_border ? (2 * blk_l_idx - c - 1) : right_border ? (2 * blk_r_idx - c + 1) : c;

            } else { // TODO: Need to add other modes support
                c_idx = c;
            }

            if ((top_border | bottom_border | left_border | right_border) && (BORDER_T == XF_BORDER_CONSTANT)) {
                src_blk.val[r][c] = 0;
            } else {
                src_blk.val[r][c] = src_blk.val[r_idx][c_idx];
            }
        }
    }

} // End of xFSetBorder()
  // ======================================================================================

} // namespace cv
} // namespace xf

#endif //__XF_EXTRA_UTILITY_H__