Perl脚本处理寄存器信息表
在编写Perl脚本处理寄存器信息表时,对计算各寄存器初始值这一步的思路进行记录。
寄存器信息表表头信息如下:
default值格式如下,不同寄存器以空行区分:
针对模块各寄存器中不同bit位字段的default值进制表达不统一,笔者的思路是将对每个字段首先将不同进制统一转化为二进制形式,再拼接各自的比特位lsb数个0,后累加得到最高32位长度的二进制数字,最后转化为16进制形式得到寄存器初始值。
for my $i (0..@reg_name-1){
if($reg_bit[$i] =~ /(\s*)+(\d+)+(\:)+(\d+)+(\s*)/) {$lsb = $4;}
elsif($reg_bit[$i] =~ /(\[)+(\d+)+(\])/){$lsb = $2;}
else {$lsb = $reg_bit[$i];}
# 先对每个字段的default值处理:首先将不同进制统一转化为二进制形式,再拼接各自的比特位lsb数个0
if($reg_def[$i] =~ /'h/){ @default_s = split(/'h/,$reg_def[$i]);
my $sig_b_def0 = sprintf "%b",hex($default_s[1]);
$sig_b_def = $sig_b_def0.(0 x $lsb);
$sig_def[$i] = $sig_b_def;
# print "$reg_addr{$reg_name[$i]}:$sig_def[$i]"."\n";
@default_s = ();
}
elsif($reg_def[$i] =~ /'b/){@default_s = split(/'b/,$reg_def[$i]);
$sig_b_def = $default_s[1].(0 x $lsb);
$sig_def[$i] = $sig_b_def;
# print "$reg_addr{$reg_name[$i]}:$sig_def[$i]"."\n";
@default_s =();
}
elsif($reg_def[$i] =~ /0x/){
@default_s = split(/x/,$reg_def[$i]);
my $sig_b_def0 = sprintf "%b",hex($default_s[1]);
$sig_b_def = $sig_b_def0.(0 x $lsb);
$sig_def[$i] = $sig_b_def;
print "$reg_addr{$reg_name[$i]}:$sig_def[$i]"."\n";
@default_s = ();
}
elsif($reg_def[$i] =~ /'d/){
@default_s = split(/'d/,$reg_def[$i]);
my $sig_b_def0 = sprintf "%b",$default_s[1];
$sig_b_def = $sig_b_def0.(0 x $lsb);
$sig_def[$i] = $sig_b_def;
# print "$reg_addr{$reg_name[$i]}:$sig_def[$i]"."\n";
@default_s = ();
}
else {$sig_def[$i] = 0;}
}
经过累加计算后得到的最高32位长度的二进制数字:
# 在累加计算中采用“|”运算代替“+”,并两次reverse:
$single_reg_def = reverse(reverse($single_reg_def) | reverse($sig_def[$i]));
在最后一次累加完成后,将得到的最高32位长度的二进制数字先转化为十进制,再转化为16进制,得到最终的寄存器初始值
my $int_single_reg_def = unpack("N",pack("B32",substr("0" x 32 . "$single_reg_def", -32)));
my $dec_single_reg_def = sprintf("%d",$int_single_reg_def);
push @reg_default,"0x".(sprintf("%x",$dec_single_reg_def));