车牌识别BMP版本
一、开发工具
Quartus prime 18.1
作为HLS实验环境搭建的必要软件之一,经验证Quartus Prime 17.1以及18.1版本可支持HLS开发。该软件可在Intel官网上注册后直接下载并按默认选项安装即可。
Modelsim Starter Edition 10.5b
ModelSim是Quartus Prime的附加软件之一。安装Quartus Prime的同时也会安装相应版本的ModelSim,所以无需专门安装该软件。
在此次HLS实验中,使用的版本是ModelSim Starter Edition 10.5b,此为HLS的默认调用版本并且不需要License。
Microsoft Visual Studio 2010 (Visual C++, 未使用license)
在整个HLS实验环境搭建中,建议安装使用Microsoft Visual Studio 2010因为经验证更新后的版本将不支持HLS开发。其中Profession、Ultimate、Standard三个版本均可从网上下载安装并未使用License,但是需要注意的是Standard版本仅支持HLS 18.1以及HLS 19.1,所以到时候需要手动匹配HLS版本方可运行。此外,在安装过程中需确保Visual C++被成功勾选。
在此次HLS实验中,使用的版本是Microsoft Visual Studio 2010 Ultimate。
(需要注意的是在全部软件安装完成后,环境变量都已自动被设置,故而无需再手动设置。)
C5MB_GHRD的黄金参考工程
二、利用HLS编译相关算子
重要说明:
Width 输入图像宽度
Height 输入图像高度
OutDir 如果是1的话,将卷积结果存放在LocalMap中;如果是0保存在Result中
Accmulate 如果是1表示需要累加
maps weight localmap result分别是4块独立的内存区域
一下代码的int main() 这个函数可以加可不加
如图下面四个C文件
文件名 | 描述 |
---|---|
conv.c | 卷积算子 |
biasrelu.c | 偏置算子 |
pooling.c | 池化算子 |
full_connecttion.c | 全连接算子 |
1.conv.c
#include <HLS/stdio.h>
#include "HLS/hls.h"
component void AccConvolution(int Width,
int Height,
int OutDir,
int Accmulate,
ihc::mm_master<float> &maps,
ihc::mm_master<float> &Weight,
ihc::mm_master<float> &LocalMap,
ihc::mm_master<float> &Result) {
float temp;
int _height = Height - 2;
int _width = Width - 2;
int index = 0;
for(int h = 0;h < _height ;h++) {
for(int w = 0;w < _width ;w++) {
temp = maps[ (h ) * Width + w ] * Weight[0] +
maps[ (h ) * Width + w + 1 ] * Weight[1] +
maps[ (h ) * Width + w + 2 ] * Weight[2] +
maps[ (h + 1) * Width + w ] * Weight[3] +
maps[ (h + 1) * Width + w + 1 ] * Weight[4] +
maps[ (h + 1) * Width + w + 2 ] * Weight[5] +
maps[ (h + 2) * Width + w ] * Weight[6] +
maps[ (h + 2) * Width + w + 1 ] * Weight[7] +
maps[ (h + 2) * Width + w + 2 ] * Weight[8] ;
index = h * (Width - 2) + w;
if(Accmulate)
temp += LocalMap[index];
if(OutDir)
LocalMap[index] = temp;
else
Result[index] = temp;
}
}
}
int main()
{
int Width = 5;
int Height = 5;
int OutDir = 1; //输出特征图保存在LocalMap
int Accmulate = 0; //不叠加LocalMap
float maps[5*5] = { //保存输入特征图
1,1,1,0,0,
0,1,1,1,0,
0,0,1,1,1,
0,0,1,1,0,
0,1,1,0,0
};
float Weight[3*3] = { //卷积窗3*3
1,0,1,
0,1,0,
1,0,1
};
float LocalMap[3*3] = {0.0}; //输出特征图尺寸3*3
float Result[3*3] = {0.0} ;//输出特征图尺寸3*3
//打印输入的特征图
printf("input picture:\n");
for(int i=0;i<25;i++)
{
printf("%.1f ",maps[i]);
if((i+1)%5==0)
{
printf("\n");
}
}
//打印输入的权重
printf("input Weight:\n");
for(int i=0;i<9;i++)
{
printf("%.1f ",Weight[i]);
if((i+1)%3==0)
{
printf("\n");
}
}
ihc::mm_master<float> mm_maps(maps,sizeof(float)*25);
ihc::mm_master<float> mm_Weight(Weight,sizeof(float)*9);
ihc::mm_master<float> mm_LocalMap(LocalMap,sizeof(float)*9);
ihc::mm_master<float> mm_Result(Result,sizeof(float)*9);
//调用component
AccConvolution(Width,Height,OutDir,Accmulate,mm_maps,mm_Weight,mm_LocalMap,mm_Result);
//打印Result中的结果
printf("result in LocalMap:\n");
for(int i=0;i<9;i++)
{
printf("%.1f ",LocalMap[i]);
if((i+1)%3==0)
{
printf("\n");
}
}
return 0;
}
2.biasrelu.c
#include <HLS/stdio.h>
#include "HLS/hls.h"
component void AccBiasRelu(int Width,
int Height,
int InDir,
int OutDir,
ihc::mm_master<float> &LocalMap,
ihc::mm_master<float> &maps,
ihc::mm_master<float> &Result,
ihc::mm_master<float> &Weight) {
int Exit = Width * Height;
float temp;
float *temp1;
float *inputbuffer;
if(InDir)
inputbuffer = LocalMap;
else
inputbuffer = maps;
if(OutDir)
temp1 = LocalMap;
else
temp1 = Result;
#pragma ivdep
for(int i = 0;i < Exit;i++) {
temp = inputbuffer[i] + Weight[0];
temp1[i] = (temp > 0) ? temp : 0;
}
}
int main()
{
int Width = 3;
int Height = 3;
int InDir = 1; //从LocalMap取数据(也就是卷积后的数据)
int OutDir = 1; //从LocalMap取数据(加偏置后的数据)
float LocalMap[3*3] = { //激活后的结果保存在LocalMap里面,激活的输入数据来自于私有存储器
4.0 ,3.0, 4.0,
2.0 ,4.0, 3.0,
2.0 ,3.0, 4.0
};
//打印输入的图片
printf("input picture:\n");
for(int i=0;i<9;i++)
{
printf("%.1f ",LocalMap[i]);
if((i+1)%3==0)
{
printf("\n");
}
}
float maps[3*3] = {0.0};
float Result[3*3] = {0.0};
float Weight[3*3] = { //加载偏置数据到FPGA的Weight存储器中
1.0 ,0.0, 1.0,
0.0 ,1.0, 0.0,
1.0 ,0.0, 1.0
};
//打印输入的权重
printf("input Weight:\n");
for(int i=0;i<9;i++)
{
printf("%.1f ",Weight[i]);
if((i+1)%3==0)
{
printf("\n");
}
};
ihc::mm_master<float> mm_maps(maps,sizeof(float)*9);
ihc::mm_master<float> mm_Weight(Weight,sizeof(float)*9);
ihc::mm_master<float> mm_LocalMap(LocalMap,sizeof(float)*9);
ihc::mm_master<float> mm_Result(Result,sizeof(float)*9);
//调用component
AccBiasRelu(Width,Height,InDir,OutDir,mm_LocalMap, mm_maps,mm_Result,mm_Weight);
//打印LocalMap中的结果
printf("LocalMap data:\n");
for(int i=0;i<9;i++)
{
printf("%.1f ",LocalMap[i]);
if((i+1)%3==0)
{
printf("\n");
}
}
return 0;
}
3.pooling.c
#include <HLS/stdio.h>
#include "HLS/hls.h"
#include <HLS/stdio.h>
#include "HLS/hls.h"
component void AccPool( int Width,
int Height,
int InDir,
int OutDir,
ihc::mm_master<float>&LocalMap,
ihc::mm_master<float>&maps,
ihc::mm_master<float>&Result) {
float PoolWindow[2][2];
float temp0;
float temp1;
float temp2;
int _height = Height >> 1;
int _width = Width >> 1;
int index = 0;
int _index = 0;
int _index_1 = 0;
float *input;
float *output;
if(InDir)
input = LocalMap;
else
input = maps;
if(OutDir)
output = LocalMap;
else
output = Result;
for(int h = 0;h < _height;h++) {
#pragma ivdep
for(int w = 0;w < _width;w++) {
_index = h * 2 * Width + w * 2;
_index_1 = (h * 2 + 1) * Width + w * 2;
PoolWindow[0][0] = input[ _index ];
PoolWindow[0][1] = input[ _index + 1];
PoolWindow[1][0] = input[ _index_1 ];
PoolWindow[1][1] = input[ _index_1 + 1];
temp0 = (PoolWindow[0][0] > PoolWindow[0][1]) ? PoolWindow[0][0] : PoolWindow[0][1];
temp1 = (PoolWindow[1][0] > PoolWindow[1][1]) ? PoolWindow[1][0] : PoolWindow[1][1];
temp2 = (temp0 > temp1) ? temp0 : temp1;
output[h*_width + w] = temp2;
}
}
}
int main()
{
int Width = 4;
int Height = 4;
int InDir = 1; //从 Localmap 读取图片数据
int OutDir = 0; //将输出结果放到 Result中
float LocalMap[4*4] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
2, 2, 3, 4
};
//打印从LocalMap获取的数据
printf("input LocalMap:\n");
for(int i=0;i<16;i++)
{
printf("%.1f ",LocalMap[i]);
if((i+1)%4==0)
{
printf("\n");
}
}
float maps[4*4] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
2, 2, 3, 4
};
float Result[2*2] = {0.0};
ihc::mm_master<float> mm_maps(maps,sizeof(float)*16);
ihc::mm_master<float> mm_LocalMap(LocalMap,sizeof(float)*16);
ihc::mm_master<float> mm_Result(Result,sizeof(float)*4);
//调用组件
AccPool(Width, Height,InDir, OutDir,mm_LocalMap,mm_maps,mm_Result);
//打印 Result 内存中的结果
printf("pooling result:\n");
for(int i=0;i<4;i++)
{
printf("%.1f ",Result[i]);
if((i+1)%2==0)
{
printf("\n");
}
}
return 0;
}
4.full_connection.c
#include <HLS/stdio.h>
#include "HLS/hls.h"
component void AccFullConnect(ihc::mm_master<float>&maps,
ihc::mm_master<float>&Weight,
ihc::mm_master<float>&Result) {
float temp[16];
float tmp = 0.0;
float *result;
result = Result;
#pragma unroll
for(int i = 0;i < 16;i++)
{
temp[i] = maps[i] * Weight[i];
}
#pragma unroll
for(int i=0; i< 16;i++)
{
tmp += temp[i];
}
result[0] = tmp;
}
int main()
{
float maps[16]={1,1,1,0,0,1,1,1,0,0,1,1,0,0,1,1};
//打印maps中的数据
printf("input maps:\n");
for(int i=0;i<16;i++)
{
printf("%.1f ",maps[i]);
}
printf("\n");
float Weight[16] = {1,0,1,1,0,1,0,0,1,0,1,1};
//打印Weight中的数据
printf("input Weight:\n");
for(int i=0;i<16;i++)
{
printf("%.1f ",Weight[i]);
}
printf("\n");
float Result[16] = {0.0f};
ihc::mm_master<float> mm_maps(maps,16*sizeof(float));
ihc::mm_master<float> mm_Weight(Weight,16*sizeof(float));
ihc::mm_master<float> mm_Result(Result,16*sizeof(float));
//调用组件
AccFullConnect(mm_maps,mm_Weight,mm_Resu