zoukankan      html  css  js  c++  java
  • lab4:VGG16 及 如何把c的for转成verliog状态机

    准备工作:

    (1)维度:

    卷积维度 粉红色最后的卷积结果矩阵维度=绿色矩阵维数-橙色矩阵维数+1

    池化的最终的结论是要把原来的维度减少到1/n

    padding:周围维一圈0 => 粉=绿+2-3+1=绿 维数可以不减(在卷积核维数是3时)

    (2)vgg 16结构

       附件的vgg16.txt

       Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) :3通道,每通道64个(64*3的矩阵),步长1,补01圈

      从矩阵可以看出并行和分块的思路。

      nn.ReLU() 
      这个表示使用ReLU激活函数,里面有一个参数inplace,默认设置为False,表示新创建一个对象对其修改,也可以设置为True,表示直接对这个对象进行修改

      MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1)) :pooling 相邻2*2矩阵选最小值,步长2

    (3)总结构:2+2+3+3+3+3=16

    数据

       (下面省略了bias和RU,每次卷积核全连接都要激活)

    state1

      (1)64*3(3*3)@ 3*1(224*224)=  64*1*(224*224=3211264)

    (2)64*64(3*3=36864)@ 64*1(224*224)= 64*1(224*224)

    (3)=64*1(112*112)

    state2

      (4)128*64(3*3)@ 64*1(112*112)=128*1(112*112=1605632) 

    (5)128*128(3*3=147456)@ 128*1(112*112)=128*1(112*112)

    (6)=128*1(56*56)

    state3

      (7)256*128(3*3)@ 128*1(56*56)=256*1(56*56)

    (8)256*256(3*3=589824)@ 256*1(56*56)=256*1(56*56)

    (9)256*256(3*3)@ 256*1(56*56)=256*1(56*56)

    (10)=256*1(28*28)

    state4

      (11)512*256(3*3)@ 256*1(28*28)=512*1(28*28=401408)

    (12)512*512(3*3=2359296)@ 512*1(28*28)=512*1(28*28)

    (13)512*512(3*3)@ 512*1(28*28)=512*1(28*28)

    (14)=512*1(14*14)

    state5

      (15)512*512(3*3)@512*1(14*14)=512*1(14*14)

    (16)512*512(3*3)@512*1(14*14)=512*1(14*14)

    (17)512*512(3*3)@512*1(14*14)=512*1(14*14)

    (18)=512*1(7*7)= 25088*1

    state6

      (19)(4096*25088=102760448) @ (25088*1)= (4096*1)

    state7

      (20)(4096*4096=16777216)@(4096*1)=(4096*1)

    state8

      (21)(1000*4096)@(4096*1)=(1000*1)

    经验和错误

    1.状态机不好拆分地话可以先写成嵌套for循环再拆:

    (1)写c并验证 

    下面是最基本的写法,要改粒度的话改一下自加的步长,换循环方式交换ij都可以实现并行计算。

    #include "stdio.h"
    /*
    
    son_num_list={0,2,2,3,3,3}
    
    命名规则
    cov_state_ cov状态机需要的参数
    cov_xxx_i cov状态机的xxx循环变量 
    cov_state cov的状态 
    cov_state_start 状态机开始信号
    cov_state_finish  状态机完成信号 
    
    full 前连接层 
    
    */
    
    FILE *out;
     
    int cov_state_son_num,cov_state_data_dimension,
    cov_state_row,cov_state_col,
    weightAddr,dataRAddr,dataWAddr;
    
    int axi_start,axi_finish;
    
    int full_state_row,full_state_col;
    
    void axi_read(){
        axi_finish=1;
    }
    void loadWeight(){
    }
    void loadData(){
    }
    void cov(){
    }
    void rectMul(){
    }
    void addToAns(){
    } 
    
    int flag=0,exit=0;
    int main(){
        
        out=fopen("out.txt","w");
    
        for(int global_state=1;global_state<=9;global_state++){
         //卷积 
             if(global_state==1,2,3,4,5){
                cov_state_son_num=global_state<=2?2:3;
                cov_state_data_dimension=224/global_state;//data的维数 
                for(int cov_son_i=0;cov_son_i<cov_state_son_num;cov_son_i++){
                    //初始化数据
                    axi_start=1;
                    axi_read();
                     while(axi_finish==0);//等待数据初始化完成,初始化完成后跳出 
                     axi_finish=0;
                     axi_start=0; 
                     //data维度
                    cov_state_data_dimension=224/global_state;   
                    //weight行数
                    //weight列数 
                    switch(global_state){
                        case 1:cov_state_row=64;cov_state_col=cov_son_i==0?3:64;break;
                        case 2:cov_state_row=128;cov_state_col=cov_son_i==0?64:128;break;
                        case 3:cov_state_row=256;cov_state_col=cov_son_i==0?128:256;break;
                        case 4:cov_state_row=512;cov_state_col=cov_son_i==0?256:512;break;
                        case 5:cov_state_row=512;cov_state_col=512;break;
                        default:;
                    } 
                    //开始cov状态机
                    for(int cov_weight_i=0;cov_weight_i<cov_state_row;cov_weight_i++){
                        //取bias 
                        int bias=0; 
                        for(int cov_weight_j=0;cov_weight_j<cov_state_col;cov_weight_j++){
                            //weight的起始地址,连续load9个 
                            weightAddr=cov_weight_i*cov_state_col+cov_weight_j; 
                            loadWeight();
                            //data 行cov_data_i 列cov_data_j 
                            for(int cov_data_i=0;cov_data_i<cov_state_data_dimension;cov_data_i++){
                                for(int cov_data_j=0;cov_data_j<cov_state_data_dimension;cov_data_j++){
                                    //data的左上角地址,load上下3*3 
                                    dataRAddr=cov_data_i*cov_state_data_dimension+cov_data_j;
                                    loadData(); //注意补0,先判断addr 
                                    //卷积计算
                                    cov(); 
                                    //累加 位置:cov行的 
                                    int ans_base=cov_weight_i*cov_state_data_dimension*cov_state_data_dimension;
                                    int ans_i=cov_data_i;
                                    int ans_j=cov_data_j;
                                    dataWAddr=ans_base+ans_i*cov_state_data_dimension+ans_j;
                                    addToAns();
                                }
                            }
                        } 
                    } 
                }
                //pool,pool的结果加bias
                int t=0;
                for(int pool_num=0;pool_num<cov_state_row;pool_num++){
                    int pool_r_base=pool_num*cov_state_data_dimension*cov_state_data_dimension;
                    int pool_w_base=pool_num*(cov_state_data_dimension/2)*(cov_state_data_dimension/2);
                    for(int pool_i=0;pool_i<cov_state_data_dimension;pool_i+=2){
                            for(int pool_j=0;pool_j<cov_state_data_dimension;pool_j+=2){
                                dataRAddr=pool_i*cov_state_data_dimension+pool_j+pool_r_base;
                                //dataWVal=loadPool()+bias;//取相邻2*2 选最大值
                                dataWAddr=(pool_i/2)*(cov_state_data_dimension/2)+pool_j/2+pool_w_base;
                                
                            }
                        
                    }
                    
                } 
                    
             }     
         //全连接
            if(global_state==6,7,8){
                full_state_row=global_state==8?1000:4096;     
                 full_state_col=global_state==6?25088:4096;
                 axi_start=1;
                 axi_read(); 
                 while(axi_finish==0);//等待数据初始化完成,初始化完成后跳出 
                 axi_finish=0;
                 axi_start=0; 
                 rectMul();
            }
            if(global_state==9) exit=1; 
        }
        fclose(out);
        
        
        
    }
    
    
    
    
     

    (2)拆状态机,有for的都能拆出来,写上标记

    (3)起名字

    将所有标记改为xxx_finish=0;xxx_start=1;while(xxx_finish==0);

    改写for循环:

    进之前初始化,叶子自加

    如两层ij循环

    #include "stdio.h"
    
    int name_state=0;
    int name_start,name_finish;//控制信号
    int name_i,name_j;//循环变量
    //循环体变量
    int n=5;
    
    int main(){
        for(int i=0;i<n;i++){
            for(int j=0;j<n*n;j++){
                printf("%d %d
    ",i,j);
            }
        }
        //改为 
        name_state=0;
        name_finish=0;
        name_start=1;
        while(name_finish==0){
            switch(name_state){
            case 0:
                if(name_start==1){
                    name_i=0;
                    name_state=1;
                } 
                break;
            case 1:
                if(name_i>=n) {
                    name_finish=1;
                    name_start=0;
                    name_state=0;
                }
                else{
                    name_j=0;
                    name_state=2;
                }
                break;
            case 2:
                if(name_j>=n*n){
                    name_i++;
                    name_state=1;
                }else{
                    printf("%d %d
    ",name_i,name_j);
                    name_j++;
                }
                break;
            }
        }
    }

     (4)用查找替换,把int换成integer,把{换成begin,}换成end,case删除,switch换成case,break删去

    粘到verilog里,再改改endcase,i++展开写就能用了。

  • 相关阅读:
    Create C++ Windows Forms Application in Visual Studio 2017
    VS项目打包发布
    获取光标所在行索引
    拖拽生成控件副本
    MDI中的ToolStrip合并
    使用FFmpeg音视频格式转换
    获取项目中其他文件
    解决Winform大多数DPI问题
    《Pro Git》第3章 分支
    《Pro Git》第2章 Git基础
  • 原文地址:https://www.cnblogs.com/iwanna/p/10259034.html
Copyright © 2011-2022 走看看