// output_layer.h
// 2018/03/11 by marsee
//
#ifndef __OUTPUT_LAYER_H__
#define __OUTPUT_LAYER_H__
#include <ap_fixed.h>
template<int W, int I, int U, int TI, int TD>
struct ap_fixed1_axis{
struct data {
ap_fixed<W,I,AP_TRN,AP_WRAP> data0;
} data;
ap_uint<(W+7)/8> keep;
ap_uint<(W+7)/8> strb;
ap_uint<U> user;
ap_uint<1> last;
ap_uint<TI> id;
ap_uint<TD> dest;
};
template<int U, int TI, int TD>
struct float1_axis{
struct data {
float data0;
} data;
ap_uint<1> keep;
ap_uint<1> strb;
ap_uint<U> user;
ap_uint<1> last;
ap_uint<TI> id;
ap_uint<TD> dest;
};
#define NUMBER_OF_OUTPUT_LAYER 3
typedef struct {
ap_fixed<12,7,AP_TRN,AP_WRAP> data [NUMBER_OF_OUTPUT_LAYER];
} mdata_type;
typedef struct {
float data [NUMBER_OF_OUTPUT_LAYER];
} fmdata_type;
typedef struct {
ap_uint<1> data [NUMBER_OF_OUTPUT_LAYER];
} out_data_type;
typedef ap_fixed<12,7,AP_TRN,AP_WRAP> out_affine_type;
typedef ap_uint<1> output_type;
#endif
// output_layer.cpp
// 2018/03/11 by marsee
//
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <hls_video.h>
#include "output_layer.h"
int output_layer(hls::stream<ap_fixed1_axis<12,7,1,1,1> >& ins,
out_data_type& output){
#pragma HLS DATA_PACK variable=output
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE axis register both port=ins
ap_fixed1_axis<12,7,1,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.data0;
}
max_val = 0;
Loop3: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
#pragma HLS UNROLL
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;
}
}
Loop4: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
#pragma HLS UNROLL
if(i == max_num)
output.data[i] = output_type(1);
else
output.data[i] = output_type(0);
}
return(0);
}
// output_layer_tb.cpp
// 2018/03/12 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 "output_layer.h"
#include "affine_layer2_output.h"
int output_layer(hls::stream<ap_fixed1_axis<12,7,1,1,1> >& ins,
out_data_type& output);
int output_layer_soft(hls::stream<float1_axis<1,1,1> >& ins,
out_data_type& output);
int main(){
using namespace std;
hls::stream<ap_fixed1_axis<12,7,1,1,1> > ins;
hls::stream<float1_axis<1,1,1> > ins_soft;
ap_fixed1_axis<12,7,1,1,1> pix;
float1_axis<1,1,1> fpix;
out_data_type out, out_soft;
// ins に入力データを用意する
for(int i=0; i<5; i++){ // dummy data
pix.user = 0;
pix.data.data0 = (out_affine_type)i;
ins << pix;
fpix.user = 0;
fpix.data.data0 = (float)i;
ins_soft << fpix;
}
// 1 画面分のデータを ins、ins_soft に入力する
for(int i=0; i < NUMBER_OF_OUTPUT_LAYER; i++){
pix.data.data0 = affine2_out[i];
fpix.data.data0 = 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);
output_layer_soft(ins_soft, out_soft);
// out と out_soft を比較する
for(int i=0; i < NUMBER_OF_OUTPUT_LAYER; i++){
cout << "out" << "[" << i << "] = " << int(out.data[i]) << " out_soft" << "[" << i << "] = " << int(out_soft.data[i]) << endl;
if(out.data[i] != out_soft.data[i]){
cerr << "Error: out" << "[" << i << "] = " << int(out.data[i]) << " out_soft" << "[" << i << "] = " << int(out_soft.data[i]) << endl;
// return(1);
}
}
return(0);
}
int output_layer_soft(hls::stream<float1_axis<1,1,1> >& ins,
out_data_type& output){
float1_axis<1,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.data0;
}
max_val = 0;
Loop3: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; 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;
}
}
Loop4: for(int i=0; i<NUMBER_OF_OUTPUT_LAYER; i++){
if(i == max_num)
output.data[i] = output_type(1);
else
output.data[i] = output_type(0);
}
return(0);
}
// affine_layer2_output.h
// 2018/4/25 21:25:42 by marsee
//
#ifndef __AFFINE_LAYER2_OUTPUT_H__
#define __AFFINE_LAYER2_OUTPUT_H__
const float affine2_fout[3] = {
-1.87331771850586,
0.88871324062347,
-1.42323863506317
};
const ap_fixed<12,7,AP_TRN,AP_WRAP> affine2_out[3] = {
-3.87500000000000,
1.21875000000000,
-2.71875000000000
};
#endif
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 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 | - | - | - | - | - | - |