使用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 "\nUsage: perl dma_parse.pl -f <excel_file> \\\n";  
  print "                        [-h] \n\n";
  print "For example:\n";
  print "    perl dma_parse.pl -f dma_map.xls\n"; 
  print "    perl dma_parse.pl -h \n"; 
  print "\n";
}

#################################################
# 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(), ".\n";
}

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(/DMA\d/){
		#print "Row, Col    = ($row, $col)\n\n";
		my $rowtmpfmt=(sprintf "%03d", $row);
		my $coltmpfmt=(sprintf "%03d", $col);
		$dma{$cell->value()} = $rowtmpfmt.$coltmpfmt;
		#print "$_\n\n";
	    }
        }
    }
    #显示DMA坐标
    #foreach my $position (sort keys %dma) {
    #  print "$position = $dma{$position}\n";
    #}
    print "\n\n";    
#################################################
# 分别处理DMA1/DMA2(遍历)各个通道
#################################################    
    foreach my $dma_name (sort keys %dma){
	#print "$dma_name\n\n";
        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)\n";
	
        #################################################
        # 取得各个通道映射信息
        #################################################   
	my $channel_num = 0; 
        for my $col ( $loop_col .. $loop_col+7 ) {
	    my @channel;
	    #print "channel_num = $channel_num\n";  #通道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 "$_\n";
		push(@channel,$cell->value());    #得到通道中的外设,存入数组
            }

            #################################################
            # 格式化处理通道数组元素
            #################################################   
	    my @fmtouts;
	    foreach my $peripheral (@channel){    #格式化出通道数组
	        my @channel_tmp = split(/\s+/,$peripheral);
		#print "channel_tmp = @channel_tmp\n";
		push @fmtouts,@channel_tmp; 
	    }
	    #print "\n\nchannel = @channel\n\n";
	    #print "fmtouts = @fmtouts\n\n\n";

            #################################################
            # 输出通道内的映射信息
            #################################################   
	    my $periphs_num = @fmtouts;
	    #print "periphs_num = $periphs_num\n";
	    my $perph_tmpnum = 0;
	    my $remap = 0;
	    my $perph_remap;
	    foreach my $peripherals (@fmtouts){
	        $_ = $peripherals;
		#print "$_\n";

		$remap = 0;                    #清除重映射标记

		if(/\(1\)/){                #判断是否有重映射  
		    #print "$` \t $& \t $' \n";
		    $peripherals = $`;
		    $remap = 1;
		    $perph_remap = $peripherals."_dma_remap"; 
		}

		if(/\(2\)/){                #判断是否有重映射  
		    #print "$` \t $& \t $' \n";
		    $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\);\n";
		    }
		    elsif($remap == 1){
	                print "assign \L$eq_left = \(\L$perph_remap \? 0 : \L$eq_right\);\n";
		    }
		    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\) ||\n";
		    }
		    elsif($remap == 1){
	                print "assign \L$eq_left = \(\L$perph_remap \? 0 : \L$eq_right\) ||\n";
		    }
		    else{
	                print "assign \L$eq_left = \L$eq_right ||\n";
		    }
	        }
	        elsif($perph_tmpnum < $periphs_num-1){
		    if($remap == 2){
	                print "                        \(\L$perph_remap \? \L$eq_right : 0\) ||\n";
		    }
		    elsif($remap == 1){
	                print "                        \(\L$perph_remap \? 0 : \L$eq_right\) ||\n";
		    }
		    else{
	                print "                        \L$eq_right ||\n";
		    }
	        }
	        else{
		    if($remap == 2){
	                print "                        \(\L$perph_remap \? \L$eq_right : 0\);\n";
		    }
		    elsif($remap = 1){
	                print "                        \(\L$perph_remap \? 0 : \L$eq_right\);\n";
		    }
		    else{
	                print "                        \L$eq_right;\n";
		    }
	        }
		
		#print"remp = $remap\n";
	        $perph_tmpnum++;               #通道中外设映射个数
	    }
	    $channel_num = $channel_num + 1;   #表示通道号channel1/channel2/...
	    print"\n";
        }
    }
}

外设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(), ".\n";
}

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(/DMA\d/){
		#print "Row, Col    = ($row, $col)\n\n";
		my $rowtmpfmt=(sprintf "%03d", $row);
		my $coltmpfmt=(sprintf "%03d", $col);
		$dma{$cell->value()} = $rowtmpfmt.$coltmpfmt;
		#print "$_\n\n";
	    }
        }
    }
    #显示DMA坐标
    #foreach my $position (sort keys %dma) {
    #  print "$position = $dma{$position}\n";
    #}
    print "\n\n";    
#################################################
# 分别处理DMA1/DMA2(遍历)各个外设
#################################################    
    foreach my $dma_name (sort keys %dma){
	#print "$dma_name\n\n";
        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)\n";
	
        #################################################
        # 取得各个外设映射信息
        #################################################   
        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\n";              #外设名字 
 
            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\n";
		   my $channel_num = $col - $dma_col - 1;          #计算通道信息
	           my $coltmpfmt=(sprintf "%03d", $channel_num);   #通道信息
		   #print "coltmpfmt = $coltmpfmt\n";
		   my $peripherals_tmp = $coltmpfmt.$cell->value();
		   push(@peripherals,$peripherals_tmp);            #得到外设映射的信息,存入数组,同时将通道信息也存入其中
		   #print "$_\n";
       	        }
            }

	    my $peripherals_num = @peripherals;          #确定映射信息是否为空(==0)
	    if($peripherals_num == 0){
       	        next;                                    #如果为空将不在进行数据分析,进行下一次循环
	    }

	    #print "peripherals = @peripherals\n";

            #################################################
            # 格式化处理外设映射数组元素
            #################################################   
	    my @fmtouts;
	    foreach my $peripheral (@peripherals){             #格式化出通道数组
		my $channel_num = substr($peripheral,0,3);     #分离通道信息
		#print "channel_num = $channel_num\n";
		substr($peripheral,0,3) = ""; 
	        my @peripherals_tmp = split(/\s+/,$peripheral);
		#print "peripherals_tmp = @peripherals_tmp\n";

		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]\n"; 
		   $count++;
		}
		push @fmtouts,@peripherals_tmp; 
	    }
	    #print "\n\nfmtouts = @fmtouts\n";	    

            #################################################
            # 正则处理:格式化输出    
	    # 分析数据:数组1用于查找含(1),数组2用于查找含(2)的外设映射通道信息
            #################################################   
	    my $remap_num = @fmtouts;

	    #print "remap_num = $remap_num\n";
            #################################################
            # 处理无映射情况   
            #################################################   
	    foreach my $fmtout (@fmtouts){
		$_ = $fmtout;
		#print "$_\n";
		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;\n";
	    }
            #################################################
            # 处理存在映射的情况   
            #################################################   
	    my @fmtouts_tmp = @fmtouts;
	    foreach my $fmtout (@fmtouts){
		$_ = $fmtout;
		#print "$_\n";
		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;\n";
		       }
	           }
		}
	    }
	    
	    print "\n";
        }
    }
}

使用方法


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
################################################# 

posted @ 2017-05-29 16:42  乔_木  阅读(610)  评论(0编辑  收藏  举报