// affine_layer1_tb.cpp
// 2018/02/26 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 "affine_layer1.h"
#include "max_pooling_output.h"
#include "af1_weight.h"
#include "af1_bias.h"
int affine_layer1(hls::stream<ap_fixed2_axis<16,6,1,1,1> >& ins,
hls::stream<ap_fixed1_axis<19,7,1,1,1> >& outs);
int affine_layer1_soft(hls::stream<float2_axis<1,1,1> >& ins,
hls::stream<float1_axis<1,1,1> >& outs);
int main(){
using namespace std;
hls::stream<ap_fixed2_axis<16,6,1,1,1> > ins;
hls::stream<ap_fixed1_axis<19,7,1,1,1> > outs;
hls::stream<float2_axis<1,1,1> > ins_soft;
hls::stream<float1_axis<1,1,1> > outs_soft;
mdata_type dot;
fmdata_type fdot;
ap_fixed2_axis<16,6,1,1,1> pix;
float2_axis<1,1,1> fpix;
ap_fixed1_axis<19,7,1,1,1> pdata;
float1_axis<1,1,1> fpdata;
// ins に入力データを用意する
for(int i=0; i<5; i++){ // dummy data
pix.user = 0;
pix.data.data0 = (affine_type)i;
pix.data.data1 = (affine_type)i;
ins << pix;
fpix.user = 0;
fpix.data.data0 = (float)i;
fpix.data.data1 = (float)i;
ins_soft << fpix;
}
// 1 画面分のデータを ins、ins_soft に入力する
for(int j=0; j < V_PRE_LAYER_HIGHT; j++){
for(int i=0; i < H_PRE_LAYER_WIDTH; i++){
pix.data.data0 = mp_out[j*H_PRE_LAYER_WIDTH+i][0];
pix.data.data1 = mp_out[j*H_PRE_LAYER_WIDTH+i][1];
fpix.data.data0 = mp_fout[j*H_PRE_LAYER_WIDTH+i][0];
fpix.data.data1 = mp_fout[j*H_PRE_LAYER_WIDTH+i][1];
if (j==0 && i==0){ // 最初のデータの時に TUSER を 1 にする
pix.user = 1;
fpix.user = 1;
} else {
pix.user = 0;
fpix.user = 0;
}
if (i == H_PRE_LAYER_WIDTH-1){ // 行の最後でTLASTをアサートする
pix.last = 1;
fpix.last = 1;
} else {
pix.last = 0;
fpix.last = 0;
}
ins << pix;
ins_soft << fpix;
}
}
affine_layer1(ins, outs);
affine_layer1_soft(ins_soft, outs_soft);
// outs, outs_soft を dot[] と fdot[] に代入して比較する
for(int i=0; i<NUMBER_OF_MIDDLE_LAYER; i++){
outs >> pdata;
outs_soft >> fpdata;
dot.data[i] = pdata.data.data0;
fdot.data[i] = fpdata.data.data0;
printf("i = %d, HW = %f, SW = %f\n", i, (float)dot.data[i], fdot.data[i]);
if((double)pow((double)dot.data[i]-(double)fdot.data[i], (double)2) > 4){ // 2乗誤差が4よりも大きい
printf("ERROR HW and SW results mismatch i = %d, HW = %f, SW = %f\n", i, (float)dot.data[i], fdot.data[i]);
//return(1);
}
}
// max_pooling の結果をヘッダファイルに出力
ofstream OH("affine_layer1_output.h");
OH << "// affine_layer1_output.h" << endl;
time_t now = time(0);
struct tm* localNow = localtime(&now);
OH << "// " << localNow->tm_year+1900 << "/" << localNow->tm_mon+1 << "/" << localNow->tm_mday;
OH << " " << setw(2) << setfill('0') << localNow->tm_hour << ":" << localNow->tm_min << ":" << localNow->tm_sec << " by marsee" << endl;
OH << "//" << endl;
OH << endl;
OH << "#ifndef __AFFINE_LAYER1_OUTPUT_H__" << endl;
OH << "#define __AFFINE_LAYER1_OUTPUT_H__" << endl;
OH << endl;
OH << "const float affine1_fout[" << NUMBER_OF_MIDDLE_LAYER << "] = {" << endl;
for (int i=0; i<NUMBER_OF_MIDDLE_LAYER ; i++){
OH << " " << fixed << setprecision(14) << fdot.data[i];
if (i == NUMBER_OF_MIDDLE_LAYER-1)
OH << endl;
else
OH << "," << endl;
}
OH << "};" << endl << endl;
OH << "const ap_fixed<19,7,AP_TRN,AP_WRAP> affine1_out[" << NUMBER_OF_MIDDLE_LAYER << "] = {" << endl;
for (int i=0; i<NUMBER_OF_MIDDLE_LAYER ; i++){
OH << " " << fixed << setprecision(14) << (float)dot.data[i];
if (i == NUMBER_OF_MIDDLE_LAYER-1)
OH << endl;
else
OH << "," << endl;
}
OH << "};" << endl << endl;
OH << "#endif" << endl;
return(0);
}
int affine_layer1_soft(hls::stream<float2_axis<1,1,1> >& ins,
hls::stream<float1_axis<1,1,1> >& outs){
float2_axis<1,1,1> stdata;
float dot[100];
float1_axis<1,1,1> outd;
Loop1: do {
// user が 1になった時にフレームがスタートする
ins >> stdata;
} while(stdata.user == 0);
Loop2: for (int y=0; y<V_PRE_LAYER_HIGHT; y++){
Loop3: for (int x=0; x<H_PRE_LAYER_WIDTH; x++){
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> stdata; // AXI4-Stream からの入力
Loop4: for (int col=0; col<100; col++){
if (x==0 && y==0) // 最初は 0 にクリアする
dot[col] = 0;
dot[col] += stdata.data.data0 * af1_fweight[y*H_PRE_LAYER_WIDTH+x][col];
dot[col] += stdata.data.data1 * af1_fweight[V_PRE_LAYER_HIGHT*H_PRE_LAYER_WIDTH+y*H_PRE_LAYER_WIDTH+x][col];
if (y==V_PRE_LAYER_HIGHT-1 && x==H_PRE_LAYER_WIDTH-1){ // 最後はバイアスを加算する
dot[col] += af1_fbias[col];
outd.data.data0 = dot[col];
if(col == 0)
outd.user = 1;
else
outd.user = 0;
if(col == NUMBER_OF_MIDDLE_LAYER-1)
outd.last = 1;
else
outd.last = 0;
outs << outd;
}
}
}
}
return(0);
}
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |