FC2カウンター FPGAの部屋 Duplicate IP の製作1(ソースコード)
FC2ブログ

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

FPGAの部屋

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

Duplicate IP の製作1(ソースコード)

SqueezeNet4mnist をVivado HLSのテンプレートで実装しようと思ったときに、1つのHLSストリームを 2 つのHLSストリームに分ける Duplicate IP と 2 つのHLSストリームを 1 つのHLSストリームにする Concatenate IP が必要となる。
今回は、Duplicate IP を作ってみよう。

まずは、duplicate_template.h を貼っておく。

// duplicate_template.h
// 2018/08/23 by marsee
//

#ifndef __DUPLICATE_TEMPLATE_H___
#define __DUPLICATE_TEMPLATE_H___

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

#include "layer_general.h"

#define TO_LITERAL(x) #x
#define PRAGMA_HLS(tok) _Pragma(TO_LITERAL(HLS tok)) // @hiyuhさんから

template<
    const size_t IN_W,     // 入力のビット幅、2つの入力のビット幅と小数点位置は合わせる
    const size_t IN_I,     // 入力の小数点位置
    const size_t NUMBER_OF_IN_CHANNELS,
    const size_t HORIZONTAL_PIXEL_WIDTH,
    const size_t VERTICAL_PIXEL_WIDTH
>int duplicate_template(hls::stream<ap_fixed_axis<IN_W,IN_I,NUMBER_OF_IN_CHANNELS,1> >&ins,
    hls::stream<ap_fixed_axis<IN_W,IN_I,NUMBER_OF_IN_CHANNELS,1> >&outs0,
    hls::stream<ap_fixed_axis<IN_W,IN_I,NUMBER_OF_IN_CHANNELS,1> >&outs1
){
    ap_fixed_axis<IN_W,IN_I,NUMBER_OF_IN_CHANNELS,1> in;
    ap_fixed_axis<IN_W,IN_I,NUMBER_OF_IN_CHANNELS,1> out;

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

    Loop_y : for(int y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        Loop_x : for(int x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
            if(!(x==0 && y==0)){
                ins >> in;
            }

            Loop_cp : for(int i=0; i<NUMBER_OF_IN_CHANNELS; i++){
                if(i<NUMBER_OF_IN_CHANNELS){
                    out.data[i] = in.data[i];
                }
            }

            out.user = in.user;
            out.last = in.last;

            outs0 << out;
            outs1 << out;
        }
    }
    return(0);
}

#endif


HLSストリームを 2 つのHLSストリームに分けるだけの記述になっている。

次に、duplicate_template.h をインスタンスする duplicate1.cpp を貼っておく。

// duplicate1.cpp
// 2018/08/23 by marsee
//

#include "duplicate_template.h"

int duplicate1(hls::stream<ap_fixed_axis<16,6,2,1> >& ins,
        hls::stream<ap_fixed_axis<16,6,2,1> >& outs0,
        hls::stream<ap_fixed_axis<16,6,2,1> >& outs1){
    return(duplicate_template<16,6,2,28,28>(ins, outs0, outs1));
}



最後にテストベンチの duplicate1_tb.cpp を貼っておく。

// duplicate1_tb.cpp
// 2018/08/23 by marsee
//

#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"

static const size_t NW = 16;
static const size_t NI = 6;
static const size_t NUMBER_OF_KERNEL = 2;
static const size_t HORIZONTAL_PIXEL_WIDTH = 28;
static const size_t VERTICAL_PIXEL_WIDTH = 28;

int duplicate1(hls::stream<ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> >& ins,
        hls::stream<ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> >& outs0,
        hls::stream<ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> >& outs1);

int main(){
    using namespace std;

    hls::stream<ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> > ins;
    hls::stream<ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> > outs0;
    hls::stream<ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> > outs1;
    ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> in;
    ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> out0;
    ap_fixed_axis<NW,NI,NUMBER_OF_KERNEL,1> out1;

    typedef ap_fixed<NW,NI,AP_TRN,AP_WRAP> ap_fixed_type;

    // ins に入力データを用意する
    for(int i=0; i<5; i++){    // dummy data
        in.user = 0;
        for(int k=0; k<NUMBER_OF_KERNEL; k++){
            in.data[k] = ap_fixed_type(float(k+i)/100.0);
        }
        ins << in;
    }

    // 1 画面分のデータを insに入力する
    for(int j=0; j < VERTICAL_PIXEL_WIDTH; j++){
        for(int i=0; i < HORIZONTAL_PIXEL_WIDTH; i++){
            for(int k=0; k<NUMBER_OF_KERNEL; k++){
                in.data[k] = ap_fixed_type((float)(k+HORIZONTAL_PIXEL_WIDTH*j+i)/100.0);
            }

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

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

    duplicate1(ins, outs0, outs1);

    // outs0 と outs1 を比較する
    int error = 0;
    for(int j=0; j < VERTICAL_PIXEL_WIDTH; j++){
        for(int i=0; i < HORIZONTAL_PIXEL_WIDTH; i++){
            outs0 >> out0;
            outs1 >> out1;
            for(int k=0; k<NUMBER_OF_KERNEL; k++){
                if(out0.data[k] != out1.data[k]){
                    printf("Error : out0.data[%d] = %f, out1.data[%d] = %f\n", k, float(out0.data[k]), k, float(out1.data[k]));
                    error = 1;
                }
            }

            if(j==0 && i==0){
                if(out0.user==1 && out1.user==1) ;
                else{
                    printf("j==0 && i==0 : out0.user = %d, out1.user = %d\n", out0.user, out1.user);
                    error = 1;
                }
            } else {
                if(out0.user==0 && out1.user==0) ;
                else{
                    printf("j!=0 || i!=0 : out0.user = %d, out1.user = %d\n", out0.user, out1.user);
                    error = 1;
                }
            }

            if(i == HORIZONTAL_PIXEL_WIDTH-1){
                if(out0.last==1 && out1.last==1) ;
                else{
                    printf("Horizontal last data : out0.last = %d, out1.last = %d\n", out0.last, out1.last);
                    error = 1;
                }
            }
        }
    }
    if(error == 0)
        printf("No Error\n");

    return(0);
}


テストベンチはHLSストリームのデータを用意して duplicate1 を呼び出して、出力された 2 つのHLSストリームの outs0, outs1 を比べて同一かどうか?をテストするテストベンチとなっている。
  1. 2018年08月29日 05:17 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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