使用Perl处理Excel之DMA映射
功能
通道处理,将各个通道的外设映射到通道上
外设ack信号处理
脚本执行情况
顶层Perl脚本(dma_parse.pl)
将上述两个功能脚本整合,便于调用
#!/usr/bin/perl -wuse 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\\\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#################################################