600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 实验项目5.1 深度学习算法与硬件加速器

实验项目5.1 深度学习算法与硬件加速器

时间:2024-06-23 09:12:56

相关推荐

实验项目5.1 深度学习算法与硬件加速器

实验对CPU的修改不多,如果完全按照RISC-V的要求设计CPU,将mul归类为R-Type的话,改动较多。但是我们可以单独设计一跟op_mul电线,然后单独设计乘法指令。

乘法指令的实现,直接使用其提供的乘法部件即可:

wire [31: 0] Result_MUL = RF_rdata1*RF_rdata2;

随后在选数里增加一项MUL的指令:

assign RF_wdata = {32{op_shift}}&shift_result|{32{op_J_Type}}&PC_4|{32{op_lui}}&extend|{32{op_auipc}}&(PC_temp+extend)|{32{(op_I_Type|op_R_Type)&~op_shift}}&ALU_result|{32{op_lw}}&load_word|{32{op_lb }}& {{24{load_byte[7]}},load_byte}|{32{op_lbu}}& {{24{1'b0}},load_byte}|{32{op_lh}}& {{16{load_half[15]}},load_half}|{32{op_lhu}}& {{16{1'b0}},load_half}|{32{op_mul}}& Result_MUL;

并按照R-Type的指令设计,设计自动机的转移:

`state_EX : beginif(op_B_Type)next_state = `state_IF;else if(op_R_Type|op_I_Type|op_U_Type|op_J_Type|op_mul)next_state = `state_WB;else if(op_S_Type)next_state = `state_ST;else if(op_L_Type)next_state = `state_LD;else next_state= `state_EX; end

其次是DNN相关的代码:

按照定义,需要设计几种中间变量:

short bias;short num_out;//outputshort num_in;//inputshort y,x,ky,kx;short k_square=1+mul(weight_size.d2,weight_size.d3);short in_square=mul(input_fm_h,input_fm_w);

bias指的是偏移量,存在 F i l t e r [ i ] [ 0 ] [ 0 ] Filter\left[i\right]\left[0\right]\left[0\right] Filter[i][0][0]位置。

其次num_in和num_out分别是吗枚举读入的图片通道数和输出的特征图片通道数。

x、y枚举的是当前图像处理的像素点位置,kx、ky指的是每一次卷积操作的时候卷积核的相对位置。

k_square和in_square是计算下标的中间变量。

在设计out的赋值时我发现,其赋值规律是顺序的,所以可以设计一个outoffset来计算位置。

int out_offset=0;short bias_offset=mul(rd_size.d1,k_square);

在第一重循环,枚举的是当前输出的通道数,在这一层可以计算bias的值。在第二层,枚举输入的通道数,随后枚举当前通道这张图片的像素点位置。在这种过程中,更据定义,需要增加当前图片间的步长Stride_X、Stride_Y。对于每个卷积核,其每个方块的由kx、ky两个块进行枚举。在这里由于存在边界填充,所以存在一个pad的偏移,于是在这里需要作差的得到iw和ih。随后求出当前的像素值和卷积的权重,随后便可以计算卷积后的结果,在这里中间变量需要用32位整数存储。在这里,值得注意的是16位定点数的符号位需要由32位定点数的符号位求出。最后,由于发现输出特征图的像素顺序是良序的,所以可以直接不断加1得到结果。另外一个比较重要的步骤是池化操作,池化操作本质是取最大值,所以实现起来比较简单。

池化操作的计算也就是找到对应像素点位置,然后比个大小就可以了。注意到这里最大值max的初始值是0x8000,这在16位定点数里表示最小值,因此一定会被更大的数所替换。

硬件加速器就很简单了:

#ifdef USE_HW_ACCELvoid launch_hw_accel(){volatile int* gpio_start = (void*)(GPIO_START_ADDR);volatile int* gpio_done = (void*)(GPIO_DONE_ADDR);* gpio_start =(* gpio_start )|0x01;while(1){if((*(volatile char*)gpio_done)&0x01)break;}return;}#endif

按照流程图,如果开始将对应位置低位赋值1,如果检测到结束位置低位赋值1就结束。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。