Program Listing for File xf_hog_descriptor_hist_norm.hpp

Return to documentation for file (/tmp/ws/src/vitis_common/include/imgproc/xf_hog_descriptor_hist_norm.hpp)

/*
 * 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_HOG_DESCRIPTOR_HIST_NORM_HPP_
#define _XF_HOG_DESCRIPTOR_HIST_NORM_HPP_

#ifndef __cplusplus
#error C++ is needed to include this header
#endif

#include "xf_hog_descriptor_compute_hist.hpp"
#include "xf_hog_descriptor_norm.hpp"

/*******************************************************************************
 *                       xFDHOGDescriptorKernel
 *******************************************************************************
 *
 * _phase_strm :phase computed image of depth XF_9UP.
 *
 *  _mag_strm :magnitude computed image of depth XF_9UP.
 *
 *  _block_strm : block  (O) desc data written to this stream
 *
 *******************************************************************************/

template <int ROWS,
          int COLS,
          int DEPTH_SRC,
          int DEPTH_DST,
          int NPC,
          int WORD_WIDTH_SRC,
          int WORD_WIDTH_DST,
          int WIN_HEIGHT,
          int WIN_WIDTH,
          int WIN_STRIDE,
          int CELL_HEIGHT,
          int CELL_WIDTH,
          int NOB,
          int NOHCPB,
          int NOVCPB,
          int NOVW,
          int NOHW,
          int NOVC,
          int NOHC,
          int NOVB,
          int NOHB,
          int BIN_STRIDE,
          bool USE_URAM>
void xFDHOGDescriptorKernel(hls::stream<XF_SNAME(WORD_WIDTH_SRC)>& _phase_strm,
                            hls::stream<XF_SNAME(WORD_WIDTH_SRC)>& _mag_strm,
                            hls::stream<XF_SNAME(WORD_WIDTH_DST)>& _block_strm,
                            uint16_t _height,
                            uint16_t _width,
                            uint16_t novw,
                            uint16_t nohw,
                            uint16_t novc,
                            uint16_t nohc,
                            uint16_t novb,
                            uint16_t nohb) {
    // array to store the histogram computed data
    ap_uint<25> HA_1[NOHC][NOB], HA_2[NOHC][NOB], HA_3[NOHC][NOB];

    // partitioning across the dim-2 to restrict the BRAM utilization
    if (USE_URAM) {
// clang-format off
        #pragma HLS ARRAY_RESHAPE variable=HA_1 cyclic factor=9 dim=2
        #pragma HLS ARRAY_RESHAPE variable=HA_2 cyclic factor=9 dim=2
        #pragma HLS ARRAY_RESHAPE variable=HA_3 cyclic factor=9 dim=2
        #pragma HLS RESOURCE variable=HA_1 core=RAM_S2P_URAM
        #pragma HLS RESOURCE variable=HA_2 core=RAM_S2P_URAM
        #pragma HLS RESOURCE variable=HA_3 core=RAM_S2P_URAM
        // clang-format on
    } else {
// clang-format off
        #pragma HLS ARRAY_PARTITION variable=HA_1 complete dim=2
        #pragma HLS ARRAY_PARTITION variable=HA_2 complete dim=2
        #pragma HLS ARRAY_PARTITION variable=HA_3 complete dim=2
// clang-format on
// specifying the dual-port BRAM
// clang-format off
        #pragma HLS RESOURCE variable=HA_1 core=RAM_S2P_BRAM
        #pragma HLS RESOURCE variable=HA_2 core=RAM_S2P_BRAM
        #pragma HLS RESOURCE variable=HA_3 core=RAM_S2P_BRAM
        // clang-format on
    }

    // array to hold the sum of squared values of each cell
    ap_uint<48> ssv_1[NOHC], ssv_2[NOHC], ssv_3[NOHC];
// clang-format off
    #pragma HLS RESOURCE variable=ssv_1 core=RAM_S2P_BRAM
    #pragma HLS RESOURCE variable=ssv_2 core=RAM_S2P_BRAM
    #pragma HLS RESOURCE variable=ssv_3 core=RAM_S2P_BRAM
    // clang-format on

    // bin center computation, in the Q9.7 format
    uint16_t bin_center[NOB];
// clang-format off
    #pragma HLS ARRAY_PARTITION variable=bin_center complete dim=0
    // clang-format on

    uint16_t offset = ((BIN_STRIDE << 7) >> 1), bi = 0;
    for (uchar_t i = 0; i < NOB; i++) {
// clang-format off
        #pragma HLS PIPELINE
        // clang-format on

        bin_center[i] = offset;
        offset += (BIN_STRIDE << 7);
    }

    ap_uint<2> idx;

    // computing two horizontal cell rows
    xFDHOGcomputeHist<ROWS, COLS, DEPTH_SRC, NPC, WORD_WIDTH_SRC, CELL_HEIGHT, CELL_WIDTH, NOHC,
                      (COLS >> XF_BITSHIFT(NPC)), WIN_STRIDE, BIN_STRIDE, NOB>(_phase_strm, _mag_strm, HA_1, ssv_1,
                                                                               bin_center, nohc);
    xFDHOGcomputeHist<ROWS, COLS, DEPTH_SRC, NPC, WORD_WIDTH_SRC, CELL_HEIGHT, CELL_WIDTH, NOHC,
                      (COLS >> XF_BITSHIFT(NPC)), WIN_STRIDE, BIN_STRIDE, NOB>(_phase_strm, _mag_strm, HA_2, ssv_2,
                                                                               bin_center, nohc);
    idx = 2;

// loop running for vertical block number of times
verticalBlockLoop:
    for (bi = 0; bi < (novb - 1); bi++) {
// clang-format off
        #pragma HLS LOOP_TRIPCOUNT min=NOVB-1 max=NOVB-1
        // clang-format on
        if (idx == 2) {
            xFDHOGcomputeHist<ROWS, COLS, DEPTH_SRC, NPC, WORD_WIDTH_SRC, CELL_HEIGHT, CELL_WIDTH, NOHC,
                              (COLS >> XF_BITSHIFT(NPC)), WIN_STRIDE, BIN_STRIDE, NOB>(_phase_strm, _mag_strm, HA_3,
                                                                                       ssv_3, bin_center, nohc);

            xFDHOGNormalize<ROWS, COLS, DEPTH_DST, NPC, WORD_WIDTH_DST, NOHC, NOHCPB, NOVCPB, NOHW, NOVW,
                            (NOB * NOHCPB * NOVCPB), WIN_HEIGHT, WIN_WIDTH, CELL_HEIGHT, CELL_WIDTH, NOHB, NOB>(
                HA_1, HA_2, ssv_1, ssv_2, _block_strm, bi, nohb, nohc);

            idx = 0;
        } else if (idx == 0) {
            xFDHOGcomputeHist<ROWS, COLS, DEPTH_SRC, NPC, WORD_WIDTH_SRC, CELL_HEIGHT, CELL_WIDTH, NOHC,
                              (COLS >> XF_BITSHIFT(NPC)), WIN_STRIDE, BIN_STRIDE, NOB>(_phase_strm, _mag_strm, HA_1,
                                                                                       ssv_1, bin_center, nohc);

            xFDHOGNormalize<ROWS, COLS, DEPTH_DST, NPC, WORD_WIDTH_DST, NOHC, NOHCPB, NOVCPB, NOHW, NOVW,
                            (NOB * NOHCPB * NOVCPB), WIN_HEIGHT, WIN_WIDTH, CELL_HEIGHT, CELL_WIDTH, NOHB, NOB>(
                HA_2, HA_3, ssv_2, ssv_3, _block_strm, bi, nohb, nohc);

            idx = 1;
        } else {
            xFDHOGcomputeHist<ROWS, COLS, DEPTH_SRC, NPC, WORD_WIDTH_SRC, CELL_HEIGHT, CELL_WIDTH, NOHC,
                              (COLS >> XF_BITSHIFT(NPC)), WIN_STRIDE, BIN_STRIDE, NOB>(_phase_strm, _mag_strm, HA_2,
                                                                                       ssv_2, bin_center, nohc);

            xFDHOGNormalize<ROWS, COLS, DEPTH_DST, NPC, WORD_WIDTH_DST, NOHC, NOHCPB, NOVCPB, NOHW, NOVW,
                            (NOB * NOHCPB * NOVCPB), WIN_HEIGHT, WIN_WIDTH, CELL_HEIGHT, CELL_WIDTH, NOHB, NOB>(
                HA_3, HA_1, ssv_3, ssv_1, _block_strm, bi, nohb, nohc);

            idx = 2;
        }
    }
    if (idx == 2) {
        xFDHOGNormalize<ROWS, COLS, DEPTH_DST, NPC, WORD_WIDTH_DST, NOHC, NOHCPB, NOVCPB, NOHW, NOVW,
                        (NOB * NOHCPB * NOVCPB), WIN_HEIGHT, WIN_WIDTH, CELL_HEIGHT, CELL_WIDTH, NOHB, NOB>(
            HA_1, HA_2, ssv_1, ssv_2, _block_strm, bi, nohb, nohc);
    } else if (idx == 0) {
        xFDHOGNormalize<ROWS, COLS, DEPTH_DST, NPC, WORD_WIDTH_DST, NOHC, NOHCPB, NOVCPB, NOHW, NOVW,
                        (NOB * NOHCPB * NOVCPB), WIN_HEIGHT, WIN_WIDTH, CELL_HEIGHT, CELL_WIDTH, NOHB, NOB>(
            HA_2, HA_3, ssv_2, ssv_3, _block_strm, bi, nohb, nohc);
    } else {
        xFDHOGNormalize<ROWS, COLS, DEPTH_DST, NPC, WORD_WIDTH_DST, NOHC, NOHCPB, NOVCPB, NOHW, NOVW,
                        (NOB * NOHCPB * NOVCPB), WIN_HEIGHT, WIN_WIDTH, CELL_HEIGHT, CELL_WIDTH, NOHB, NOB>(
            HA_3, HA_1, ssv_3, ssv_1, _block_strm, bi, nohb, nohc);
    }
}

/******************************************************************************
 * xFDHOGDescriptor: This function acts as a wrapper function for the
 *      HoG descriptor function
 *****************************************************************************/
template <int WIN_HEIGHT,
          int WIN_WIDTH,
          int WIN_STRIDE,
          int CELL_HEIGHT,
          int CELL_WIDTH,
          int NOB,
          int NOHCPB,
          int NOVCPB,
          int ROWS,
          int COLS,
          int DEPTH_SRC,
          int DEPTH_DST,
          int NPC,
          int WORDWIDTH_SRC,
          int WORDWIDTH_DST,
          bool USE_URAM>
void xFDHOGDescriptor(hls::stream<XF_SNAME(WORDWIDTH_SRC)>& _phase_strm,
                      hls::stream<XF_SNAME(WORDWIDTH_SRC)>& _mag_strm,
                      hls::stream<XF_SNAME(WORDWIDTH_DST)>& _block_strm,
                      uint16_t _height,
                      uint16_t _width) {
#ifndef __SYNTHESIS__
    assert((DEPTH_SRC == XF_16UP) && "DEPTH_DST must be XF_16UP");
    assert((DEPTH_DST == XF_16UP) && "DEPTH_DST must be XF_16UP");
    assert(((NPC == XF_NPPC1) || (NPC == XF_NPPC8) || (NPC == XF_NPPC16)) &&
           "NPC must be XF_NPPC1, XF_NPPC8 or XF_NPPC16");
    assert(((WORDWIDTH_SRC == XF_16UW) || (WORDWIDTH_SRC == XF_128UW) || (WORDWIDTH_SRC == XF_256UW)) &&
           "WORDWIDTH_SRC must be XF_16UW, XF_128UW or XF_256UW");
    assert((WORDWIDTH_DST == XF_576UW) && "WORDWIDTH_DST must be XF_576UW");
    assert(((WIN_HEIGHT % CELL_HEIGHT) == 0) && "WIN_HEIGHT must be a multiple of CELL_HEIGHT");
    assert(((WIN_WIDTH % CELL_WIDTH) == 0) && "WIN_WIDTH must be a multiple of CELL_WIDTH");
    assert(((_height % CELL_HEIGHT) == 0) && "Image HEIGHT must be a multiple of CELL_HEIGHT");
    assert(((_width % CELL_WIDTH) == 0) && "Image WIDTH must be a multiple of CELL_WIDTH");
    assert(((WIN_HEIGHT <= ROWS) || (WIN_WIDTH <= COLS)) &&
           "WIN_HEIGHT and WIN_WIDTH must be less than or equal to the image _height and image _width respectively");
    assert((((ROWS - WIN_HEIGHT) % WIN_STRIDE == 0) || ((COLS - WIN_WIDTH) % WIN_STRIDE == 0)) &&
           "The number of windows must not extend the image boundary limit");
    assert((NOB == 9) && "NOB must be 9");
    assert(((NOHCPB == 2) && (NOVCPB == 2)) && "number of horizontal and vertical cells per block must be 2");
#endif

    uint16_t novw = (((_height - WIN_HEIGHT) / WIN_STRIDE) + 1);
    uint16_t nohw = (((_width - WIN_WIDTH) / WIN_STRIDE) + 1);
    uint16_t novc = (_height / CELL_HEIGHT);

    uint16_t nohc = (_width / CELL_WIDTH);
    uint16_t novb = ((_height / CELL_HEIGHT) - 1);
    uint16_t nohb = ((_width / CELL_WIDTH) - 1);

    xFDHOGDescriptorKernel<ROWS, COLS, DEPTH_SRC, DEPTH_DST, NPC, WORDWIDTH_SRC, WORDWIDTH_DST, WIN_HEIGHT, WIN_WIDTH,
                           WIN_STRIDE, CELL_HEIGHT, CELL_WIDTH, NOB, NOHCPB, NOVCPB,
                           (((ROWS - WIN_HEIGHT) / WIN_STRIDE) + 1), (((COLS - WIN_WIDTH) / WIN_STRIDE) + 1),
                           (ROWS / CELL_HEIGHT), (COLS / CELL_WIDTH), ((ROWS / CELL_HEIGHT) - 1),
                           ((COLS / CELL_WIDTH) - 1), (180 / NOB), USE_URAM>(
        _phase_strm, _mag_strm, _block_strm, _height, _width, novw, nohw, novc, nohc, novb, nohb);
}

#endif // _XF_HOG_DESCRIPTOR_KERNEL_HPP_