• 使用Perl处理Excel之DMA映射


    使用Perl处理Excel之DMA映射

    功能


    通道处理,将各个通道的外设映射到通道上
    外设ack信号处理

    脚本执行情况



    顶层Perl脚本(dma_parse.pl)


    将上述两个功能脚本整合,便于调用

    #!/usr/bin/perl -w
    use strict;
    
    my $Has_Help = ""; 
    my $workfile = ""; 
    my $worklist = ""; 
    my $excelfile;
    my $ipnamelist;
    
    if( $#ARGV < 0 ) {
      &print_usage;
      exit;
    }
    my $filename ="";
    &parse_argv;
    
    if( $Has_Help =~ /TRUE/ )  #显示帮助说明
        {
          &print_usage;
          exit;
        }
    if($workfile =~ /TRUE/)
    {
       chomp($excelfile);
       
       #格式化输出通道输出部分
       system"perl dmaremap_parse.pl   $excelfile";
       system"perl dmaack_parse.pl   $excelfile";
    }
    else
        {
          &print_usage;
          exit;
        }
    
    #################################################
    # Sub-routine: print_usage()   帮助说明
    #################################################
    sub print_usage {
      print "
    Usage: perl dma_parse.pl -f <excel_file> \
    ";  
      print "                        [-h] 
    
    ";
      print "For example:
    ";
      print "    perl dma_parse.pl -f dma_map.xls
    "; 
      print "    perl dma_parse.pl -h 
    "; 
      print "
    ";
    }
    
    #################################################
    # Sub-routine : parse_argv()   参数读入
    #################################################
    sub parse_argv {
      my $all_arg = "-h|-f";
    
      for(my $i=0; $i<=$#ARGV; $i++) {
        if( $ARGV[$i] =~ /-f/ ) {
          $i++;
          if(!defined $ARGV[$i])
          {
             $Has_Help = "TRUE";
          }
          $workfile = "TRUE";
          $excelfile = $ARGV[$i];
        }
        elsif( $ARGV[$i] =~ /-h/ ) {
          $Has_Help = "TRUE";
        }
        else { ### other options
          $Has_Help = "TRUE";
        }
      }
    }
    
    

    通道映射脚本(dmaremap_parse.pl)


    #!/usr/bin/perl -w
    
    #################################################
    # 使用方法
    # perl dma_parse.pl dma_map.xls
    #################################################    
    
    use strict;
    use Spreadsheet::ParseExcel;
    use Spreadsheet::ParseExcel::FmtUnicode;
    
    my $parser   = Spreadsheet::ParseExcel->new();
    my $formatter = Spreadsheet::ParseExcel::FmtUnicode->new(Unicode_Map=>"CP936");
    my $workbook = $parser->parse($ARGV[0], $formatter);    
    #my $workbook = $parser->parse($ARGV[0]);
     
    if ( !defined $workbook ) {
        die $parser->error(), ".
    ";
    }
    
    for my $worksheet ( $workbook->worksheets() ) {
     
        my ( $row_min, $row_max ) = $worksheet->row_range();
        my ( $col_min, $col_max ) = $worksheet->col_range();
     
    #################################################
    # get DMA1/2坐标
    #################################################    
        my %dma;
        for my $row ( $row_min .. $row_max ) {
            for my $col ( $col_min .. $col_max ) {
     
                my $cell = $worksheet->get_cell( $row, $col );
                next unless $cell;
    	    $_ = $cell->value();
    	    if(/DMAd/){
    		#print "Row, Col    = ($row, $col)
    
    ";
    		my $rowtmpfmt=(sprintf "%03d", $row);
    		my $coltmpfmt=(sprintf "%03d", $col);
    		$dma{$cell->value()} = $rowtmpfmt.$coltmpfmt;
    		#print "$_
    
    ";
    	    }
            }
        }
        #显示DMA坐标
        #foreach my $position (sort keys %dma) {
        #  print "$position = $dma{$position}
    ";
        #}
        print "
    
    ";    
    #################################################
    # 分别处理DMA1/DMA2(遍历)各个通道
    #################################################    
        foreach my $dma_name (sort keys %dma){
    	#print "$dma_name
    
    ";
            my $row = substr($dma{$dma_name},0,3); 	#使用substr得到前三位字符串
            my $col = substr($dma{$dma_name},3,3); 	#使用substr得到后三位字符串
    
            my $loop_row = $row + 2;
            my $loop_col = $col + 1;
    	#print "Row, Col    = ($loop_row, $loop_col)
    ";
    	
            #################################################
            # 取得各个通道映射信息
            #################################################   
    	my $channel_num = 0; 
            for my $col ( $loop_col .. $loop_col+7 ) {
    	    my @channel;
    	    #print "channel_num = $channel_num
    ";  #通道channel1/2/3
                for my $row ( $loop_row .. $loop_row+31 ) {
     
                    my $cell = $worksheet->get_cell( $row, $col );
                    next unless $cell;
    		if(($cell->value() eq ""))
           	        {
           	           next;
           	        }
                    $_ = $cell->value();
    		#print "$_
    ";
    		push(@channel,$cell->value());    #得到通道中的外设,存入数组
                }
    
                #################################################
                # 格式化处理通道数组元素
                #################################################   
    	    my @fmtouts;
    	    foreach my $peripheral (@channel){    #格式化出通道数组
    	        my @channel_tmp = split(/s+/,$peripheral);
    		#print "channel_tmp = @channel_tmp
    ";
    		push @fmtouts,@channel_tmp; 
    	    }
    	    #print "
    
    channel = @channel
    
    ";
    	    #print "fmtouts = @fmtouts
    
    
    ";
    
                #################################################
                # 输出通道内的映射信息
                #################################################   
    	    my $periphs_num = @fmtouts;
    	    #print "periphs_num = $periphs_num
    ";
    	    my $perph_tmpnum = 0;
    	    my $remap = 0;
    	    my $perph_remap;
    	    foreach my $peripherals (@fmtouts){
    	        $_ = $peripherals;
    		#print "$_
    ";
    
    		$remap = 0;                    #清除重映射标记
    
    		if(/(1)/){                #判断是否有重映射  
    		    #print "$` 	 $& 	 $' 
    ";
    		    $peripherals = $`;
    		    $remap = 1;
    		    $perph_remap = $peripherals."_dma_remap"; 
    		}
    
    		if(/(2)/){                #判断是否有重映射  
    		    #print "$` 	 $& 	 $' 
    ";
    		    $peripherals = $`;
    		    $remap = 2;
    		    $perph_remap = $peripherals."_dma_remap"; 
    		}
    		
                    #my $output = $peripherals;
    		#$output =~ /(d)/; 
    		
    		my $eq_left  = $dma_name."_single"."[$channel_num]";
    		my $eq_right = $peripherals."_dma_req";
    
    		if($periphs_num == 1){
    		    if($remap == 2){
    	                print "assign L$eq_left = (L$perph_remap ? L$eq_right : 0);
    ";
    		    }
    		    elsif($remap == 1){
    	                print "assign L$eq_left = (L$perph_remap ? 0 : L$eq_right);
    ";
    		    }
    		    else{
    	                print "assign L$eq_left = L$eq_right;";
    		    }
    	        }
    	        if($perph_tmpnum == 0){
    		    if($remap == 2){
    	                print "assign L$eq_left = (L$perph_remap ? L$eq_right : 0) ||
    ";
    		    }
    		    elsif($remap == 1){
    	                print "assign L$eq_left = (L$perph_remap ? 0 : L$eq_right) ||
    ";
    		    }
    		    else{
    	                print "assign L$eq_left = L$eq_right ||
    ";
    		    }
    	        }
    	        elsif($perph_tmpnum < $periphs_num-1){
    		    if($remap == 2){
    	                print "                        (L$perph_remap ? L$eq_right : 0) ||
    ";
    		    }
    		    elsif($remap == 1){
    	                print "                        (L$perph_remap ? 0 : L$eq_right) ||
    ";
    		    }
    		    else{
    	                print "                        L$eq_right ||
    ";
    		    }
    	        }
    	        else{
    		    if($remap == 2){
    	                print "                        (L$perph_remap ? L$eq_right : 0);
    ";
    		    }
    		    elsif($remap = 1){
    	                print "                        (L$perph_remap ? 0 : L$eq_right);
    ";
    		    }
    		    else{
    	                print "                        L$eq_right;
    ";
    		    }
    	        }
    		
    		#print"remp = $remap
    ";
    	        $perph_tmpnum++;               #通道中外设映射个数
    	    }
    	    $channel_num = $channel_num + 1;   #表示通道号channel1/channel2/...
    	    print"
    ";
            }
        }
    }
    

    外设ack信号处理脚本(dmaack_parse.pl)


    #!/usr/bin/perl -w
    
    #################################################
    # 使用方法
    # perl dma_parse.pl dma_map.xls
    #################################################    
    
    use strict;
    use Spreadsheet::ParseExcel;
    use Spreadsheet::ParseExcel::FmtUnicode;
    
    my $parser   = Spreadsheet::ParseExcel->new();
    my $formatter = Spreadsheet::ParseExcel::FmtUnicode->new(Unicode_Map=>"CP936");
    my $workbook = $parser->parse($ARGV[0], $formatter);    
    #my $workbook = $parser->parse($ARGV[0]);
     
    if ( !defined $workbook ) {
        die $parser->error(), ".
    ";
    }
    
    for my $worksheet ( $workbook->worksheets() ) {
     
        my ( $row_min, $row_max ) = $worksheet->row_range();
        my ( $col_min, $col_max ) = $worksheet->col_range();
     
    #################################################
    # get DMA1/2坐标
    #################################################    
        my %dma;
        for my $row ( $row_min .. $row_max ) {
            for my $col ( $col_min .. $col_max ) {
     
                my $cell = $worksheet->get_cell( $row, $col );
                next unless $cell;
    	    $_ = $cell->value();
    	    if(/DMAd/){
    		#print "Row, Col    = ($row, $col)
    
    ";
    		my $rowtmpfmt=(sprintf "%03d", $row);
    		my $coltmpfmt=(sprintf "%03d", $col);
    		$dma{$cell->value()} = $rowtmpfmt.$coltmpfmt;
    		#print "$_
    
    ";
    	    }
            }
        }
        #显示DMA坐标
        #foreach my $position (sort keys %dma) {
        #  print "$position = $dma{$position}
    ";
        #}
        print "
    
    ";    
    #################################################
    # 分别处理DMA1/DMA2(遍历)各个外设
    #################################################    
        foreach my $dma_name (sort keys %dma){
    	#print "$dma_name
    
    ";
            my $dma_row = substr($dma{$dma_name},0,3); 	#使用substr得到前三位字符串
            my $dma_col = substr($dma{$dma_name},3,3); 	#使用substr得到后三位字符串
    
            my $loop_row = $dma_row + 2;
            my $loop_col = $dma_col + 1;
    	#print "Row, Col    = ($loop_row, $loop_col)
    ";
    	
            #################################################
            # 取得各个外设映射信息
            #################################################   
            for my $row ( $loop_row .. $loop_row+31 ) {
    	    my @peripherals;
    	    my $periph_cell = $worksheet->get_cell( $row, $loop_col-1);  #外设行列确定
    	    my $peripherals_name = $periph_cell->value; 
    	    #print "peripherals_name = $peripherals_name
    ";              #外设名字 
     
                for my $col ( $loop_col .. $loop_col+7 ) {
                    my $cell = $worksheet->get_cell( $row, $col );
                    next unless $cell;
    		if(($cell->value() eq ""))
           	        {
           	           next;
           	        }
                    $_ = $cell->value();
    		if(/w+/)
           	        {
    		   #print "dma_col = $dma_col
    ";
    		   my $channel_num = $col - $dma_col - 1;          #计算通道信息
    	           my $coltmpfmt=(sprintf "%03d", $channel_num);   #通道信息
    		   #print "coltmpfmt = $coltmpfmt
    ";
    		   my $peripherals_tmp = $coltmpfmt.$cell->value();
    		   push(@peripherals,$peripherals_tmp);            #得到外设映射的信息,存入数组,同时将通道信息也存入其中
    		   #print "$_
    ";
           	        }
                }
    
    	    my $peripherals_num = @peripherals;          #确定映射信息是否为空(==0)
    	    if($peripherals_num == 0){
           	        next;                                    #如果为空将不在进行数据分析,进行下一次循环
    	    }
    
    	    #print "peripherals = @peripherals
    ";
    
                #################################################
                # 格式化处理外设映射数组元素
                #################################################   
    	    my @fmtouts;
    	    foreach my $peripheral (@peripherals){             #格式化出通道数组
    		my $channel_num = substr($peripheral,0,3);     #分离通道信息
    		#print "channel_num = $channel_num
    ";
    		substr($peripheral,0,3) = ""; 
    	        my @peripherals_tmp = split(/s+/,$peripheral);
    		#print "peripherals_tmp = @peripherals_tmp
    ";
    
    		my $element_num = @peripherals_tmp;
    		my $count = 0;
    		while($count < $element_num){                  #附加通道信息
    	           $peripherals_tmp[$count] = $channel_num.$peripherals_tmp[$count];
    
    		   #print "peripherals_tmp[$count] = $peripherals_tmp[$count]
    "; 
    		   $count++;
    		}
    		push @fmtouts,@peripherals_tmp; 
    	    }
    	    #print "
    
    fmtouts = @fmtouts
    ";	    
    
                #################################################
                # 正则处理:格式化输出    
    	    # 分析数据:数组1用于查找含(1),数组2用于查找含(2)的外设映射通道信息
                #################################################   
    	    my $remap_num = @fmtouts;
    
    	    #print "remap_num = $remap_num
    ";
                #################################################
                # 处理无映射情况   
                #################################################   
    	    foreach my $fmtout (@fmtouts){
    		$_ = $fmtout;
    		#print "$_
    ";
    		if(/(d)/){
    		   next;              #去除包含重映射的外设
    		}
    
    	 	my $channel_num = substr($fmtout,2,1);     #分离通道信息
    		substr($fmtout,0,3) = ""; 
    		my $dma_ack = $dma_name."_ack"."[".$channel_num."]";
    		my $peripherals_ack = $fmtout."_dma_ack";
    		print "assign L$peripherals_ack = L$dma_ack;
    ";
    	    }
                #################################################
                # 处理存在映射的情况   
                #################################################   
    	    my @fmtouts_tmp = @fmtouts;
    	    foreach my $fmtout (@fmtouts){
    		$_ = $fmtout;
    		#print "$_
    ";
    		if(/(2)/){
    		   my $channel_2 = substr($fmtout,2,1);        #映射通道2信息
    		   my $fmtout = $`;                            #自动,捕获之前的信息
    		   substr($fmtout,0,3) = "";                   #去除通道信息,重新赋值 
    		   my $dma_ack2 = $dma_name."_ack"."[".$channel_2."]";
    	           foreach my $fmtout_tmp (@fmtouts_tmp){
    		       $_ = $fmtout_tmp;
    		       if(/$fmtout/){
    			  $_ = $fmtout_tmp;
    			  if(/(2)/){
                                 next;
    			  }
    	 	          my $channel_1 = substr($fmtout_tmp,2,1);     #映射通道2信息
    		          substr($fmtout_tmp,0,3) = ""; 
    		          my $dma_ack1 = $dma_name."_ack"."[".$channel_1."]";
    		          my $peripherals_ack = $fmtout."_dma_ack";
    			  my $peripherals_remap = $fmtout."_dma_remap";
    		          print "assign L$peripherals_ack = L$peripherals_remap ? L$dma_ack2 : L$dma_ack1;
    ";
    		       }
    	           }
    		}
    	    }
    	    
    	    print "
    ";
            }
        }
    }
    

    使用方法


    dma_parse.pl 顶层文件
    |
    |--dmaremap_parse.pl
    |
    |--dmaack_parse.pl
    
    #################################################
    # 使用方法
    # perl dma_parse.pl dma_map.xls
    #################################################
    
    #################################################
    # 子文件使用方法
    # perl dmaremap_parse.pl dma_map.xls
    # perl dmaack_parse.pl dma_map.xls
    ################################################# 
    
    
  • 相关阅读:
    PHP 单例 工厂模式 类的重载 抽象 接口
    上传文件
    ThinkPHP3.2中if标签
    JS闭包特性 运算符 DOM操作
    循环数组 连接数据库 AJAX
    ThinkPHP
    TP框架
    MVC框架
    类的自动加载,静态属性静态方法
    魔术方法__get()和set函数
  • 原文地址:https://www.cnblogs.com/OneFri/p/6918333.html
Copyright © 2020-2023  润新知