卷积函数的FPGA实现(九)WBRAM的重新实现

背景:实测IPcore在FPGA上运行时,错误语句集中于get_9_weights_to_buffer之中,极有可能是WBRAM尺寸的设定出现了问题。

目的:找出WBRAM尺寸设定的问题,更改代码。

前期工作:

ZynqNet解析(七)实现于BRAM上的Cache https://blog.csdn.net/weixin_36474809/article/details/83860624

卷积函数的FPGA实现(三)加入HLS预编译指令 https://blog.csdn.net/weixin_36474809/article/details/84580456

目录

一、zynqNet的WBRAM的实现

1.1 zynqNet的WBRAM实现方法

1.2 BRAM 32k的尺寸

二、卷积IPcore的尺寸的推断

2.1 已有资源

2.2 总的网络占用

2.3 已有BRAM的实验

三、更改方法

3.1 尺寸的确定

3.2 WBRAM尺寸的确定

3.3 当前WBRAM的地址

3.4 程序之中的更改

3.5 synthesis报告及验证


一、zynqNet的WBRAM的实现

1.1 zynqNet的WBRAM实现方法

wegiht_cache.cpp与hpp之中,可能7045的BRAM为BRAM 32k,而我们7035的BRAM为BRAM 18k

其源码尺寸实现为四个维度

data_t WeightsCache::WBRAM[N_PE][NUM_BRAMS_PER_PE][BLOCK_SIZE][9];
// Depth of single BRAM36 in (1K x 32b) configuration
const int BLOCK_SIZE = 1024;
// Number of BRAM36 needed per PE
const int NUM_BRAMS_PER_PE =
    (CEIL_DIV(((MAX_WEIGHTS_PER_LAYER) / 8), BLOCK_SIZE) / N_PE);

MAX_WEIGHTS_PER_LAYER为最大的层的weight的bit数目,除以8得到byte数目。

然后除以PE的个数,和block_size的个数即为NUM_BRAMS_PER_PE的个数。

1.2 BRAM 32k的尺寸

为32k个bit,即32*1024个bit,所以有32kb,即4kB

每个浮点数为4byte,即32bit,所以每个BRAM刚好能存1024个浮点数

由此推算,BRAM 18k能存 512个浮点数。

即 0.5k*32bit=16kb<18kb

二、卷积IPcore的尺寸的推断

2.1 已有资源

BRAM具体尺寸应该查数据手册,但是我们根据目前已有的项目情况和实验推出

BRAM 32k即 32kbit,能存1024个浮点数,

BRAM 18k即18k bit,能存512个浮点数。

2.2 总的网络占用

我们打出过MTCNN网络最大需要卷积的尺寸。

3*3滤波器的个数最多为16384,即Onet最后一层128*128*3*3的尺寸。128*128=16384

在此尺寸之下,设为8PE并行,则每个PE上需要2048个filter,BRAM 18k显然存不下。

2.3 已有BRAM的实验

OBRAM设为8个并行,每个BRAM的大小为 MAX_CO /N_PE,OBRAM的最大的输出通道设置为512,每个PE上所存的浮点数为 512/8= 64个。

下表中这样理解,为了更好的并行,每个OBRAM在PE上实现为2个BRAM 18k,每个PE上存64个浮点数,则每个BRAM上面32个浮点数,即每两个BRAM 18k在一个PE上,有64个浮点数(words),每个浮点数(word)占用32bit(4byte*8bit)

卷积函数的FPGA实现(九)WBRAM的重新实现_第1张图片

关于IBRAM,最初的程序之中最大为3904,现在为8704。(3904的实现,HLS用了8个BRAM来实现)每个BRAM上488个浮点数字。这里,word就被当作了字节。

但是对于WBRAM而言,报告里面生成了64*2个WBRAM 18k.,每两个WBRAM存有了1024个浮点数。

64*1024=65536个浮点数,与预想的权重浮点数 8PE*1024per_PE*9=73728相比少了。WBRAM的内存溢出。

三、更改方法

3.1 尺寸的确定

我们需要确定最终需要的尺寸的大小,

// ==========================
// = Architecture Constants =
// ==========================
// Number of Image Cache Lines (need 3, use 4 for simplified Addressing HW)
const int NUM_IMG_CACHE_LINES = 4;
// Number of Processing Elements
const int N_PE = 8;

//1G=268,435,465*sizeof(float) = 1,073,741,824byte=8,589,934,592bit
const int DRAM_DEPTH = 268435465;

//IBRAM, OBRAM, WBRAM size (this value need to be changed by network)
const int MAX_IMAGE_CACHE_SIZE = 8704;
const int MAX_NUM_CHOUT = 128;
//const int MAX_CO_PER_PE=8;
// const int MAX_2D_FILTERS_PER_PE=1024;
const int MAX_2D_FILTERS_PER_PE= 2048;

此尺寸下可以在主程序之中正常运行MTCNN的网络,按照此尺寸构建IPcore。

3.2 WBRAM尺寸的确定

8N_PE * 2048个filters

多一个维度需要 8 N_PE * 4 BRAMS_PER_FILTERLOC_PER_PE * 512 MAX_FLOAT_SIZE_PER_PE * 9

我们将WBRAM设成此四维实现。

extern float WBRAM[N_PE][BRAMS_PER_FILTERLOC_PER_PE][MAX_FLOAT_SIZE_PER_PE][9];

float WeightsCache::WBRAM[N_PE][BRAMS_PER_FILTERLOC_PER_PE][MAX_FLOAT_SIZE_PER_PE][9];

3.3 当前WBRAM的地址

卷积函数的FPGA实现(九)WBRAM的重新实现_第2张图片

void WeightsCache::get_WBRAM_addr(const int cur_ci, const int cur_co,
									int &PEID, int &BRAM_ID, int &BRAM_loc){
#pragma HLS INLINE
	PEID=cur_co%N_PE;
	int filterID=(cur_co/N_PE)*inChannelNum+cur_ci;
	BRAM_ID=filterID/MAX_FLOAT_SIZE_PER_PE;
	BRAM_loc=filterID%MAX_FLOAT_SIZE_PER_PE;
}

3.4 程序之中的更改

WBRAM地址的映射函数如上,所有调用此函数的函数都需要更改。

//get 9 weights from IBRAM to buffer
void WeightsCache::get_9_weights_to_buffer(int cur_ci, int cur_co,float weight_buffer[9]){
#pragma HLS FUNCTION_INSTANTIATE variable = cur_co
#pragma HLS inline
#pragma HLS pipeline
// Array Partitioning
#pragma HLS ARRAY_PARTITION variable = WBRAM complete dim = 1    // PE ID
#pragma HLS ARRAY_PARTITION variable = WBRAM complete dim = 2    // BRAM ID
#pragma HLS ARRAY_PARTITION variable = WBRAM complete dim = 4    // filter loc
#pragma HLS RESOURCE variable = WBRAM core = RAM_S2P_BRAM latency = 3

#pragma HLS ARRAY_PARTITION variable = weight_buffer complete dim = 0
	int PEID,BRAM_ID,BRAM_loc;
	get_WBRAM_addr(cur_ci,cur_co,PEID,BRAM_ID,BRAM_loc);
	for(int i=0;i<9;i++){
		weight_buffer[i]=WBRAM[PEID][BRAM_ID][BRAM_loc][i];
	}
}
//load weights from DRAM to BRAM
void WeightsCache::load_WBRAM_from_DRAM(volatile float * weight_ptr){
#pragma HLS inline
	int PEID,BRAM_ID,BRAM_loc;
	float *WBRAM_ptr;volatile float *weight_DRAM_ptr;
	for(int cur_co=0;cur_co

 程序正确性验证,嵌套入主程序之中验证通过,嵌套入c-simulation验证通过。

3.5 synthesis报告及验证

卷积函数的FPGA实现(九)WBRAM的重新实现_第3张图片

卷积函数的FPGA实现(九)WBRAM的重新实现_第4张图片

WBRAM的个数为[8][4] [512][9]个

分别表示PEID,BRAM_ID, BRAM_loc, filter_loc。

synthesis获得了预想的结果,运行无误。

你可能感兴趣的:(FPGA,机器学习,c/c++)