FC2カウンター FPGAの部屋 HLSストリームの最終出力層(C ソースコード)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

HLSストリームの最終出力層(C ソースコード)

今回は、HLSストリームの最終出力層をやってみることにする。最終出力層は、CNN の 3 つの出力の内で、最大の値を出力した出力ポートのID を出力する。また、3 つの出力も出力する。

それでは、output_layer.h から貼っておく。

// output_layer.h
// 2018/03/11 by marsee
// 2018/03/12 : 出力フォーマットを変更
// 2018/04/30 : HLS Streamに変更
//

#ifndef __OUTPUT_LAYER_H__
#define __OUTPUT_LAYER_H__
#include <ap_fixed.h>

static const size_t NUMBER_OF_OUTPUT_LAYER = 3;

static const size_t W = 12;
static const size_t I = 7;

typedef struct {
    ap_fixed<W,I,AP_TRN,AP_WRAP> data [NUMBER_OF_OUTPUT_LAYER];
} mdata_type;

typedef struct {
    float data [NUMBER_OF_OUTPUT_LAYER];
} fmdata_type;

typedef ap_fixed<W,I,AP_TRN,AP_WRAP> out_affine_type;

typedef ap_uint<2> output_type;
#endif


次に、output_layer.cpp を貼っておく。

// output_layer.cpp
// 2018/03/11 by marsee
// 2018/03/12 : 出力フォーマットを変更
// 2018/04/30 : HLS Streamに変更
//

#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>

#include "layer_general.h"
#include "output_layer.h"

int output_layer(hls::stream<ap_fixed_axis<W,I,1,1> >& ins, output_type& output,
        out_affine_type dot2[NUMBER_OF_OUTPUT_LAYER]){
#pragma HLS ARRAY_PARTITION variable=dot2 complete dim=1
#pragma HLS DATA_PACK variable=ins

    ap_fixed_axis<W,I,1,1> stdata;
    mdata_type af2;
    int max_num;
    out_affine_type max_val;

    Loop1: do {
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
    // user が 1になった時にフレームがスタートする
        ins >> stdata;
    } while(stdata.user == 0);

    Loop2: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
#pragma HLS PIPELINE II=1
        if(i != 0)    // 最初の入力はすでに入力されている
            ins >> stdata;    // AXI4-Stream からの入力

        af2.data[i] = stdata.data[0];
    }

    max_val = 0;
    Loop3: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
#pragma HLS UNROLL
        dot2[i] = af2.data[i];
        if(i == 0){
            max_val = af2.data[0];
            max_num = 0;
        } else if (max_val < af2.data[i]){
            max_val = af2.data[i];
            max_num = i;
        }
    }

    output = output_type(max_num);

    return(0);
}


output_layer_tb.cpp を貼っておく。

// output_layer_tb.cpp
// 2018/03/12 by marsee
// 2018/03/12 : 出力フォーマットを変更
// 2018/04/30 : HLS Streamに変更
//

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <math.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>

#include "layer_general.h"
#include "output_layer.h"
#include "affine_layer2_output.h"

int output_layer(hls::stream<ap_fixed_axis<W,I,1,1> >& ins, output_type& output,
        out_affine_type dot2[NUMBER_OF_OUTPUT_LAYER]);

int output_layer_soft(hls::stream<float_axis<1,1> >& ins, output_type& output,
        float dot2[NUMBER_OF_OUTPUT_LAYER]);

int main(){
    using namespace std;

    hls::stream<ap_fixed_axis<W,I,1,1> > ins;
    hls::stream<float_axis<1,1> > ins_soft;

    ap_fixed_axis<W,I,1,1> pix;
    float_axis<1,1> fpix;
    output_type out, out_soft;
    out_affine_type dot2[NUMBER_OF_OUTPUT_LAYER];
    float fdot2[NUMBER_OF_OUTPUT_LAYER];

    // ins に入力データを用意する
    for(int i=0; i<5; i++){    // dummy data
        pix.user = 0;
        pix.data[0] = (out_affine_type)i;
        ins << pix;

        fpix.user = 0;
        fpix.data[0] = (float)i;
        ins_soft << fpix;
    }

    // 1 画面分のデータを ins、ins_soft に入力する
    for(int i=0; i < NUMBER_OF_OUTPUT_LAYER; i++){
        pix.data[0] = affine2_out[i];
        fpix.data[0] = affine2_fout[i];

        if (i == 0){    // 最初のデータの時に TUSER を 1 にする
            pix.user = 1;
            fpix.user = 1;
        } else {
            pix.user = 0;
            fpix.user = 0;
        }

        if (i == NUMBER_OF_OUTPUT_LAYER-1){ // 行の最後でTLASTをアサートする
            pix.last = 1;
            fpix.last = 1;
        } else {
            pix.last = 0;
            fpix.last = 0;
        }

        ins << pix;
        ins_soft << fpix;
    }

    output_layer(ins, out, dot2);
    output_layer_soft(ins_soft, out_soft, fdot2);

    // out と out_soft を比較する
    cout << "out" << " = " << int(out) << " out_soft" " = " << int(out_soft) << endl;
    for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
        cout << "dot2[" << i << "] = " << float(dot2[i]) << " fdot2[" << i << "] = " << fdot2[i] << endl;
    }
    if(out != out_soft){
        cout << "error: out" << " = " << int(out) << " out_soft" " = " << int(out_soft) << endl;
        //return(1);
    }

    return(0);
}

int output_layer_soft(hls::stream<float_axis<1,1> >& ins, output_type& output,
        float dot2[NUMBER_OF_OUTPUT_LAYER]){

    float_axis<1,1> stdata;
    fmdata_type af2;
    int max_num;
    float max_val;

    Loop1: do {
    // user が 1になった時にフレームがスタートする
        ins >> stdata;
    } while(stdata.user == 0);

    Loop2: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
        if(i != 0)    // 最初の入力はすでに入力されている
            ins >> stdata;    // AXI4-Stream からの入力

        af2.data[i] = stdata.data[0];
    }

    max_val = 0;
    Loop3: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
        dot2[i] = af2.data[i];
        if(i == 0){
            max_val = af2.data[0];
            max_num = 0;
        } else if (max_val < af2.data[i]){
            max_val = af2.data[i];
            max_num = i;
        }
    }

    output = output_type(max_num);

    return(0);
}


なお、layer_general.h はここにある
  1. 2018年04月30日 09:04 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/4151-ef53e333
この記事にトラックバックする(FC2ブログユーザー)