使用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
#################################################
形而上者谓之道 形而下者谓之器。