美文网首页
power_check.pl of Low Power RTL设

power_check.pl of Low Power RTL设

作者: airland | 来源:发表于2019-04-15 11:44 被阅读0次
#!/usr/bin/perl -w
######################################################################################
### Copyright 
### This source file may be used and distributed without restriction 
### provided that this copyright statement is not removed from the file 
### and that any derivative work contains the original copyright notice 
### and the associated disclaimer. 
### 
### THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS 
### OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
### WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
######################################################################################
### Created by Arthas Jie Xiao in 2015-09-07 
### contact author: celebraty2008@163.com
### 1. find register assignmetn without condition 
### 2. find 2D array
### 3. find multiplier
### 4. find initial block
######################################################################################

use Env;
use Getopt::Long;
use strict;


my $print_en          = 0;  #to print verbose log
my $folder_name       = "power_check";

my $log_all           = "$folder_name/all_always.v";
my $log_summary       = "$folder_name/summary.v";
my $log_file          = "$folder_name/power_check.v";
my $log_fatal         = "$folder_name/fatal.log";
my $log_all_mul       = "$folder_name/all_mul.log";
my $log_all_2d        = "$folder_name/all_2d.log";
my $log_all_init      = "$folder_name/all_init.log";



my $err_cnt_total     = 0;
my $err_cnt_rdl       = 0;
my $err_cnt_local     = 0;
my $err_cnt_per_file  = 0;
my $log_err           = 0;
my $fatal_exist       = 0;
my $array_2d_total    = 0; 
my $mul_cnt_total     = 0;
my $init_cnt_total    = 0;


my $usage =
qq/
Usage: power_check.pl -[help|h]            ------print help
       power_check.pl -[verbose|v]         ------print verbose log;
       power_check.pl -[file|f] <filelist> ------eg. power_check.pl -f vfiles_rtl
       power_check.pl -[dir|d]  <dir>      ------eg. power_check.pl -d . 
       power_check.pl -[bak|b]             ------eg. power_check.pl -b
       power_check.pl -[filter] <N>        ------eg. power_check.pl -filter [N]
       power_check.pl -[2d_array|2d]       ------eg. power_check.pl -2d
       power_check.pl -[initial|init]      ------eg. power_check.pl -init
       power_check.pl -[multiplier|mul]    ------eg. power_check.pl -mul
       power_check.pl <files>              ------eg. power_check.pl top.v
/;

#initial block is dangerous for Non-reset register, as its intial value is unknown and may synthesis off.
#Abusing 2D array register waste area and power.  
#Abusing multiplier waste area and power.


my $get_help;
my $get_verbose;
my $get_filelist;
my $get_dir;
my $get_filter  = 0;  #default 0
my $get_2d_array=0;
my $get_bak     =0;
my $get_init    =0;
my $get_mul     =0;

GetOptions( 'help'              => \$get_help,          # print help
            'h'                 => \$get_help,          # print help
            'verbose|v'         => \$get_verbose,       # enable full log
            'file|f=s'          => \$get_filelist,      # get filelist
            'dir|d=s'           => \$get_dir,           # get search directory
            'filter=s'          => \$get_filter,        # get filter number
            '2d_array|2d'       => \$get_2d_array,      # get 2d array info
            'bak|b'             => \$get_bak,           # get back up
            'initial|init'      => \$get_init,          # get intial block
            'multiplier|mul'    => \$get_mul,           # get multiplier 
            '<>'                => \&get_parameter      # get parameter
          ) ;




# check cmd-line params
&chkOpts;

#open log  files 
open(LOGFILE, ">$log_file") || die "Cannot open rtl power check file:$log_file\n";

system `rm $log_all -rf`;
open(ALLLOGFILE, ">$log_all") || die "Cannot open rtl power check file:$log_all\n";

system `rm $log_summary -rf`;
open(SUMMARY, ">$log_summary") || die "Cannot open rtl power check file:$log_summary\n";

system `rm $log_fatal -rf`;
open(FATALFILE, ">$log_fatal") || die "Cannot open rtl power check file:$log_fatal\n";

system `rm $log_all_mul -rf`;
if($get_mul) {
    open(ALLMULFILE, ">$log_all_mul") || die "Cannot open rtl power check file:$log_all_mul\n";
}

system `rm $log_all_2d -rf`;
if($get_2d_array) {
    open(ALL2DFILE, ">$log_all_2d") || die "Cannot open rtl power check file:$log_all_2d\n";
}

system `rm $log_all_init -rf`;
if($get_init) {
    open(ALLINITFILE, ">$log_all_init") || die "Cannot open rtl power check file:$log_all_init\n";
}

#read vfiles jxiao
&read_vfiles;

if($get_mul) {
    if($mul_cnt_total != 0 )  {
        print "Low power RTL checker find $mul_cnt_total Multiplier, please review $log_file for more info!\n";
        print SUMMARY "Total multiplier is $mul_cnt_total!\n";
    } else {
        print "Low power RTL checker find No Multiplier!\n";
        print SUMMARY "Total multiplier is $mul_cnt_total!\n";
    }
}

if($get_2d_array) {
    if($array_2d_total != 0 )  {
        print "Low power RTL checker find $array_2d_total 2D_array, please review $log_file for more info!\n";
        print SUMMARY "Total 2D_Array is $array_2d_total!\n";
    } else {
        print "Low power RTL checker find No 2D_Array!\n";
        print SUMMARY "Total 2D_Array is $array_2d_total!\n";
    }
}


if($get_init) {
    if($init_cnt_total != 0 )  {
        print "Low power RTL checker find $init_cnt_total initial block, please review $log_file for more info!\n";
        print SUMMARY "Total initial block is $init_cnt_total!\n";
    } else {
        print "Low power RTL checker find No initial block!\n";
        print SUMMARY "Total initial block is $init_cnt_total!\n";
    }
}

#report log
if($log_err) {
    if($err_cnt_rdl == 0) {
        print "Low power RTL checker find $err_cnt_total issue, please check $log_file for more info!\n";
        print SUMMARY "Total have $err_cnt_total issue!";
    }
    else {
        print "Low power RTL checker find $err_cnt_total issue, including RDL $err_cnt_rdl issue, local $err_cnt_local issue, please check $log_file for more info!\n";
        print SUMMARY "Total have $err_cnt_total issue, RDL $err_cnt_rdl issue, local $err_cnt_local issue!";
    }
} else {
    print "RTL Pass low power RTL check!\n";
    print SUMMARY "Total have 0 issue, RTL pass low power RTL check!";

}


close(LOGFILE);
close(ALLLOGFILE);
close(SUMMARY);
close(FATALFILE);

if($get_mul)      {close(ALLMULFILE);}
if($get_2d_array) {close(ALL2DFILE);}
if($get_init)     {close(ALLINITFILE);}

###################################################################################
#######Function
###################################################################################
#analyze input cmd
sub chkOpts
{
    die $usage if $get_help;
    
    if($get_verbose) { 
        print "[INFO]:Set Verbose Log \n";
        $print_en =1 
    };
    
    if($get_bak) {
        ################################################
        ##For local time bak 
        ###############################################
        my ( $sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
        $year += 1900;
        $mon ++;
        my $data = "$year-$mon-$day $hour:$min";
        
        if(-d $folder_name) {
            #folder exist!;
            print "[INFO]:copy $folder_name to $folder_name$data\n";
            system `cp $folder_name "$folder_name$data" -rf `;
        }
            
    }

    if(-d $folder_name) {
        #if folder exist! 
    }
    else{

        system `mkdir $folder_name`;
    }

    if($get_dir) {
        if(-d $get_dir) {

            system `rm $folder_name/vfiles_power_check -rf`;
            print "[INFO]:Exec cmd \" find $get_dir -name \"\*\.v\" \" !\n";
            system `find $get_dir -name "*.v"  >>$folder_name/vfiles_power_check` ; #not using ">" to cover previous file
        }
        else {
           print "[ERROR]: Input directory $get_dir Does Not Exist ! \n";
           die "$usage";
       }
    
    }

    if($get_filelist) {
        if(-e $get_filelist) {
           if($get_filelist ne "$folder_name/vfiles_power_check"){
               system `rm $folder_name/vfiles_power_check -rf`;
               system `cat $get_filelist  >>$folder_name/vfiles_power_check `; 
           }
        }
        else {
            print "[ERROR]: Input file $get_filelist Does Not Exist ! \n";
            die "$usage";
        }
    }

    if($get_filter) {
        print "[INFO]:Filter Error if Register Bit Num is Not More Than  $get_filter ! \n";
    }

    

}

sub get_parameter
{
    my @parameter = shift(@_);
    my $item;
    foreach $item (@parameter) {
        if( $item !~ m/.*\.v/) {
            print "[ERROR]: Input file $get_dir Does Not .v file ! \n";
            die "$usage"; 
        }
    }

    if(-d $folder_name) {
        #if folder exist! 
    }
    else{
        system `mkdir $folder_name`;
    }

    open(TMP, ">tmp") || die "Cannot open rtl power check file:tmp\n";
    print TMP "@parameter\n";
    close TMP;
    system `cat tmp > $folder_name/vfiles_power_check` ;
    system `rm tmp -rf`;
}


sub read_vfiles 
{

    open (VFILE_LIST, "$folder_name/vfiles_power_check" );
    while(<VFILE_LIST>){
        my $vfile = $_;
        chomp ($vfile);
    
        if ($vfile !~ m/.*\.v/) {
            next;
        } 
        elsif ($vfile =~/\#/){
            # "#" used to comment out lines
            next;
        }
    
        my @dirs = split("\/", $vfile);
        my $file_name = $dirs[$#dirs];
        
        #filter reg.v and files from cad/bfm/fpga
        if($file_name !~ m/.*reg\.v/ && $vfile !~ m/\/cad\// && $vfile !~ m/\/bfm\// 
            && $vfile !~ m/\/fpga\// && $vfile !~ m/\/verification\// && $vfile !~ m/\/testbench\// 
            && $vfile !~ m/\/mini_mi_D/ && $vfile !~ m/\/power_check/){ 

            #remove reg.v and /cad/xxxx file
            print LOGFILE    "Checking $vfile!\n";
            print ALLLOGFILE "Checking $vfile!\n";
            if($get_mul) {
                print ALLMULFILE "Checking $vfile!\n";
            }
            if($get_2d_array) {
                print ALL2DFILE "Checking $vfile!\n";
            }
            if($get_init) {
                print ALLINITFILE "Checking $vfile!\n";
            }


            if($print_en) { print "[INFO]:Checking $vfile!\n"};
            
            #do RTL power check 
            $log_err = &power_check($vfile, $file_name) || $log_err;
    
            print SUMMARY "Checking $vfile have $err_cnt_per_file issue!\n";
        }
        else {
            print LOGFILE    "Not Check $vfile!\n";
            print SUMMARY    "Not Check $vfile!\n";
            print ALLLOGFILE "Not Check $vfile!\n";
            if($get_mul) {
                print ALLMULFILE "Not Check $vfile!\n";
            }
            if($get_2d_array) {
                print ALL2DFILE "Not Check $vfile!\n";
            }
            if($get_init) {
                print ALLINITFILE "Not Check $vfile!\n";
            }
            if($print_en) { print "[INFO]:Not Check $vfile!\n" } ;
        }
    }

    close(VFILE_LIST);
}

#Check RTL code that not easy for ICG insertion
sub power_check {

    my ($vfile, $file_name)   = @_;
    my $line_cnt              = 0; #line counter to trace error
    my $always_blk            = 0; #in always block, set 1, after always block end, set 0 
    my $if_blk                = 0; #0: else ; 1: first if hier
    my $always_begin          = 0; #if always start with "begin", should end with "end; 
    my $if_begin              = 0; #add one in "if begin" or "else if begin" 
    my $error_flag            = 0; #if 1, print always block 
    my $error_line            = 0; #if 1, print error line
    my $error_file            = 0; #if 1, print check log
    my $always_print          = 0; #temp print always block 
    my $initial_blk           = 0; #in initial block, set 1, after end, set 0


    my @hier                  = ([0,0,0,0]);#[if_en, if_or_else, if_begin, if_line];
    my @def_hier              = ([0,0]);    #[if_def_en, if or else]
    my @previous              = ();#previous hier info.

    my $hier_cnt              = 0;#hierarchy counter, counter from 0
    my $hier_add              = 0;#if hier_add set 1, means hier_cnt should add back
    my $comment               = 0;#to remove comments in multiple lines /* ....*/, 1 means comments
    my $line_num              = 0;#use for debug
    my $else_flag             = 0;#to remove comments in multiple lines /* ....*/, 1 means comments
    my $ifdef_cnt             = 0;#to remove comments in multiple lines /* ....*/, 1 means comments
   
    my %reg_hash              = (); 
    my $reg_name              = "";
    my $check_en              = 1 ;
    my $left_num              = 0 ;
    my $right_num             = 0 ;
    
    $fatal_exist              = 0;
    if(-e $vfile) {
        open(MYFILE, "$vfile") || die "can't open $vfile : $!";
    }
    $err_cnt_per_file = 0;
    while(<MYFILE>) {
        my $line = $_;
        chomp($line);
        
        $line_cnt = $line_cnt + 1; 
        $line =~ s/\r//g; #remove ^M, fix display issue
        $line =~ s/\t/    /g; #replase tab to  "    ", do not need to care [\s|\t], all can be " "
        my $line_org = $line; # reserve line original
        
        ##################################
        ####For auto indent
        ##################################
        my $line_len = length($line_org);
        my $space    = "";
        for(my $i = 0 ; $i <= (60 - $line_len); $i = $i+1) {
            $space = " ".$space;
        }

        if($line =~ /^ *reg *\[.*\].*\[.*\] *;/){
            if($get_2d_array) {
                $array_2d_total = $array_2d_total + 1;
                print LOGFILE    "$line_cnt : $line_org$space WARNING: 2D array***************Check if it can be replaced by hardmacro, or PIPE to FIFO!\n";   #print reg [xx:xx] aaaa[xx:xxx];
                print ALL2DFILE  "$line_cnt : $line_org$space WARNING: 2D array***************Check if it can be replaced by hardmacro, or PIPE to FIFO!\n";
            }
        }
        elsif($line =~ /^ *reg *(\[ *([^ ]+) *: *([^ ]+) *\]) *([^ ]+) *;/) {
            #reg [m:n] name;
            $reg_name                   = $4;
            $reg_hash{$reg_name}{left}  = $2;
            $reg_hash{$reg_name}{right} = $3; 
            if($2 =~ /[^\d]/ || $3 =~ /[^\d]/) {
                $reg_hash{$reg_name}{width} = 9999; #if can not detect width
            }
            else {
                $reg_hash{$reg_name}{width} = $2 - $3 + 1; 
            }
            $reg_hash{$reg_name}{check} = 1; #need check
            #print " $line : $reg_hash{$reg_name}{left}  ,  $reg_hash{$reg_name}{right} \n";
        }
        elsif ($line =~ /^ *reg *([^ ]+) *;/) {
            #reg name;
            $reg_name                   = $1;
            $reg_hash{$reg_name}{left}  = 0;
            $reg_hash{$reg_name}{right} = 0; 
            $reg_hash{$reg_name}{width} = 1; 
            $reg_hash{$reg_name}{check} = 1; #need check
        }
            
            
        
        if($line=~m/\/\*.*\*\//) {   #remove /* xxxxx */
            $line =~s/\/\*(.*?)\*\///g;
        }

        if($line =~m/^ *\/\//){  
            #match "//" from begining
            $always_print = "$always_print$line_cnt : $line_org\n";
            $line_num = __LINE__;
            if($always_blk ==1 && $print_en == 1) {
                print "$line_cnt : $line_org$space//--------> \$line_num = $line_num,commented skipping !\n";
            }
            next;
        }
        else {
            #match "//" in line
            $line =~s/\/\/.*//g; 
        }
      
        #for ifdef  
        if($line =~ m/^ *`else/) {
            $else_flag = 1
        }
        elsif($line =~ m/^ *`(ifdef|ifndef)/) {
            $ifdef_cnt = $ifdef_cnt + 1; 
        }
        elsif($line =~ m/^ *`endif/) {
            $ifdef_cnt = $ifdef_cnt -1; 
            if($ifdef_cnt==0){
                $else_flag = 0;
             }
        } 
     
        #print "$line_cnt : $line_org$space//--------> \$ifdef_cnt = $ifdef_cnt, \$else_flag = $else_flag!\n";
        if($else_flag == 1 ) {
            #define block
            $always_print = "$always_print$line_cnt : $line_org\n";
            $line_num = __LINE__;
            if($always_blk ==1 && $print_en == 1) {
                print "$line_cnt : $line_org$space//--------> \$line_num=$line_num,commented skipping !\n";
            }
            next;
        }
        elsif($line=~m/\*\// && $comment) {
            #match "*/" to end "/*" comments
            $always_print = "$always_print$line_cnt : $line_org\n";
            $comment = 0;
            $line_num = __LINE__;
            if($always_blk ==1 && $print_en == 1) {
                print "$line_cnt : $line_org$space//--------> \$line_num=$line_num,commented skipping !\n";
            }
            next;
        }
        elsif($comment) {
            #pass comments
            $always_print = "$always_print$line_cnt : $line_org\n";
            $line_num = __LINE__;
            if($always_blk ==1 && $print_en == 1) {
                print "$line_cnt : $line_org$space//--------> \$line_num=$line_num,commented skipping !\n";
            }
            next;
        }
        elsif($line=~m/\/\*/) {
            #mach "/*"
            $always_print = "$always_print$line_cnt : $line_org\n";
            $comment = 1;
            $line_num = __LINE__;
            if($always_blk ==1 && $print_en == 1) {
                print "$line_cnt : $line_org$space//--------> \$line_num=$line_num,commented skipping !\n";
            }
            next;
        }
        else {
            if($get_mul) {
                #-------------------Mul Check-------------------------
                my $mul_flag =0;
                my $line_mul = $line;
                my $line_mul1; 
                my $line_mul2; 
                if($line_mul !~ /\*/) {         #without "*"

                } else {                        #only check line with "*";
                    while($line_mul =~ s/(.*)\[.*\](.*)/$1$2/g){
                        #remove multiple [x*xx : x*xx] 
                    } ;    

                    if($line_mul =~ m/always *\@ *\( *\* *\)/) { #always @(*)
                        $line_num           = __LINE__;
                    } elsif ($line_mul =~ /-?\d*\'(h|d|o|b)[\dabcdef]+\s*\*|\* *-?\d*\'(h|d|o|b)[\dabcdef]+/i )  { # 2'h3 * () or () * 2'h3
                        $line_num           = __LINE__;
                    } elsif ($line_mul =~ /(\w+) *\* *(\w+)/) { 
                        $line_mul1 = $1;
                        $line_mul2 = $2;
                        if($line_mul1 !~/\D/ | $line_mul2 !~ /\D/) {   #2 * () or () * 2;
                            $line_num           = __LINE__;
                        } else {                                       #add_1 * () 
                            $line_num           = __LINE__;
                            $mul_flag = 1;
                        }
                    } elsif ($line_mul =~ /\*/)  {
                        $line_num           = __LINE__;
                        $mul_flag = 1;
                    }
                    if($print_en) {
                        print "$line_cnt : $line_org$space//-------> \$line_num=$line_num, \$line_mul=$line_mul, \$mul_flag=$mul_flag\n";
                    }

                    if($mul_flag) {
                        $mul_cnt_total = $mul_cnt_total  + 1;
                        print LOGFILE    "$line_cnt : $line_org$space WARNING: Multiplier***************Check if needed or can be shared!\n";   
                        print ALLMULFILE "$line_cnt : $line_org$space WARNING: Multiplier***************Check if needed or can be shared!\n";
                    } else {
                        print ALLMULFILE "$line_cnt : $line_org\n";
                    }
                }
                #-------------------Mul Check-------------------------
            }

            if($line =~m/^ *(endmodule|endtask|endfunction)/){           
                #endmodule or endtask or endfunction
                $line_num = __LINE__;
                if($always_blk == 1) { #has always 
                    if($print_en == 1) {
                         print "$line_cnt : $line_org$space//-------> \$line_num=$line_num,print previous always block!\n";
                    }
                    print ALLLOGFILE "$always_print";
                    $always_print =""; #clear $always_print
                }
                #clear 
                $always_blk = 0;
                $always_begin =0;
                $error_flag   =0;
                $error_line   =0;
                $hier_cnt     =0;
                $if_begin     =0;
                next;
            }
            elsif($line =~m/^ *always *\@ *\( *(posedge|negedge).*\)/) {
                #alwasy @ ( posedge clk or negedge reset_n) //match always block 
                $line_num = __LINE__;
                if($always_blk == 1) { #has always 
                    #if($print_en == 1) {
                    #     print "$line_cnt : $line_org$space//-------> \$line_num=$line_num,print previous always block!\n";
                    #}
                    print ALLLOGFILE "$always_print";
                    $always_print =""; #clear $always_print
                }
                $always_blk   =1;
                $always_begin =0;
                $error_flag   =0;
                $error_line   =0;
                $hier_cnt     =0;
                $if_begin     =0;
                @hier         = ([0,0,0,0]);
                @previous     = (0,0,0,0,0);
                if($line =~m/^ *always *\@ *\( *[posedge|negedge].*\) *begin/) {
                    #alway block with begin
                    $always_begin =1;
                }

                if($print_en) { print "$line_cnt : $line_org$space//-------> \$line_num=$line_num, \$always_blk = $always_blk, \$always_begin = $always_begin \n" } ;
                $always_print = "$line_cnt : $line_org\n"; #initial always block print
                next;
            }
            elsif($line =~ m/^ *(initial|wire[ []|assign |reg[ []|always *\@ *\(|\..*\()/){
                #initial / wire / assign
                #always (*
                #.xxx ( xxxx),
                $line_num = __LINE__;
                if($always_blk == 1) { #has always 
                    if($print_en == 1) {
                         print "$line_cnt : $line_org$space//-------> \$line_num=$line_num,print previous always block!\n";
                    }
                    print ALLLOGFILE "$always_print";
                    $always_print =""; #clear $always_print
                }
                #clear 
                $always_blk   =0;
                $always_begin =0;
                $error_flag   =0;
                $error_line   =0;
                $hier_cnt     =0;
                $if_begin     =0;
                
                #handle intial block print
                if($get_init & $line =~ /^ *initial |^ *initial$/ ) {
                    $line_num = __LINE__;
                    $initial_blk =1; 
                    $init_cnt_total = $init_cnt_total + 1;
                    print LOGFILE     "$line_cnt : $line_org$space ERROR: Initial***************Make sure no register initialization!\n";   #print initial
                    print ALLINITFILE "$line_cnt : $line_org$space ERROR: Initial***************Make sure no register initialization!\n";
                    if($print_en == 1) {
                         print "$line_cnt : $line_org$space//-------> \$line_num=$line_num, print initial block start!\n";
                    }
                } 
                next
            }
            elsif($initial_blk==1){
                print LOGFILE "$line_cnt : $line_org\n";   #print initial
                print ALLLOGFILE "$line_cnt : $line_org\n";
                if($line =~/^ *end *$/) {
                    $initial_blk = 0;
                    $line_num = __LINE__;
                    if($print_en == 1) {
                         print "$line_cnt : $line_org$space//-------> \$line_num=$line_num, print initial block end!\n";
                    }
                } else {
                    $line_num = __LINE__;
                    if($print_en == 1) {
                         print "$line_cnt : $line_org$space//-------> \$line_num=$line_num, print initial block body!\n";
                    }
                }
            }
            elsif($always_blk==1 && $always_begin== 0 && $hier_cnt==0  && $line =~ m/^ *begin/){
                #always@(posedge clk)
                #    begin     //match this "begin"
                $line_num     = __LINE__;
                $always_begin = 1;
                $always_print = "$always_print$line_cnt : $line_org\n";
                if($print_en) { print "$line_cnt : $line_org$space//-------> \$line_num=$line_num, \$always_blk = $always_blk, \$always_begin = $always_begin \n" } ;
                next;
            }
            elsif($always_blk == 1 ) { 
                #in always block
                if($print_en) { print "$line_cnt : $line_org" } ;

                $always_print = "$always_print$line_cnt : $line_org";
                $hier_add     =0;  #has only valid for one line

                if($line =~ m/^ *begin *if.*\) *begin/) {                       # begin if () begin
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 2;
                    $hier[$hier_cnt][2] = 1;       #add begin for previous hier  
                    $hier_cnt        = $hier_cnt + 1;
                    $hier[$hier_cnt] = [(1,1,1,0)];#if_en=1, if_else=1, if_begin=1, if_line=0; if_line used when if_begin==0
                    @previous        =  (1,1,1,0,$hier_cnt); 
                }
                elsif($line =~ m/^ *begin *if.*\)/) {                       # begin if () 
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 1;
                    $hier[$hier_cnt][2] = 1;       #add begin for previous hier  
                    $hier_cnt        = $hier_cnt + 1;
                    $hier[$hier_cnt] = [(1,1,0,0)];#if_en=1, if_else=1, if_begin=1, if_line=0; if_line used when if_begin==0
                    @previous        =  (1,1,0,0,$hier_cnt); 
                }
                elsif($line =~ m/^ *if.*\) *begin/) {                         # if () begin
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 1;
                    $hier_cnt        = $hier_cnt + 1;
                    $hier[$hier_cnt] = [(1,1,1,0)]; #if_en=1, if_else=1, if_begin=1, if_line=0; if_line used when if_begin==0
                    @previous        =  (1,1,1,0,$hier_cnt); 
                }
                elsif ($line =~ m/^ *else *if.*\) *begin/){                   # else if () begin, no end
                    $line_num        = __LINE__;
                    $if_begin = $if_begin + 1; #no end, so begin add 1;
                    if($previous[2] == 1 || $previous[3] == 1 ) {                   # if-else with begin, or has one line 
                        #if (xxx)                       #if(xxx)
                        #   q<= d;                      #
                        #else if(xxx) //hier_cnt++      #else if(xxx)   //hier_cnt do not need ++
                        $hier_cnt = $hier_cnt +1 ;                                  
                    }
                    $hier[$hier_cnt] = [(1,1,1,0)];
                    @previous        =  (1,1,1,0,$hier_cnt);
                }
                elsif($line =~ m/^ *(else)* *if *\(.*\).*<=.*;/){             # if () , no begin, but with Q<=d assignment
                    # if(xxx) Q<= D;
                    $line_num          = __LINE__;
                    $hier[$hier_cnt+1] = [(1,1,0,1)];
                    @previous          =  (0,0,0,1,$hier_cnt); 
                    $previous[0]       = 0; #out of if block
                    $previous[3]       = 1; #with one line in if_no_begin block 
                    $hier_add          = 1; #add back
                }
                elsif($line =~ m/^ *else *if *\(/){                          # else if () , no begin, no end
                    $line_num          = __LINE__;
                    if($previous[2] == 1 || $previous[3] == 1 ) {                  # if-else with begin, or has one line  
                        $hier_cnt = $hier_cnt +1 ;
                    }
                    $hier[$hier_cnt] = [(1,1,0,0)]; #no begin
                    @previous        =  (1,1,0,0,$hier_cnt); 
                }
                elsif($line =~ m/^ *if *\(/){                                # if () , no begin
                    $line_num        = __LINE__;
                    $hier_cnt        = $hier_cnt + 1;
                    $hier[$hier_cnt] = [(1,1,0,0)];
                    @previous        =  (1,1,0,0,$hier_cnt); 
                }
                elsif($line =~ m/^ *end *else *if.*\) *begin/){             # end else if () begin
                    $line_num        = __LINE__;
                    #previou is also [1,1,1,0, $hier_cnt], so keep
                }
                elsif($line =~ m/^ *end *else *if.*\)/){                    # end else if (), no begin 
                    $line_num        = __LINE__;
                    #previou is also [1,1,1,0, $hier_cnt], so keep
                    $if_begin        = $if_begin - 1;
                    $hier[$hier_cnt][2] = 0; #no begin
                    $previous[2] =0;  
                }
                elsif($line =~ m/^ *end *else *begin/){                     # end else begin
                    #change if-else = 0 for else
                    $line_num        = __LINE__;
                    $hier[$hier_cnt] = [(1,0,1,0)]; 
                    @previous        =  (1,0,1,0,$hier_cnt);          
                }
                elsif ($line =~ m/^ *else.*begin/){                         # else begin, no end
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 1;
                    if($previous[2] == 1 || $previous[3] == 1 ) {
                        $hier_cnt = $hier_cnt +1 ;
                    }
                    $hier[$hier_cnt] = [(1,0,1,0)];
                    @previous        =  (1,0,1,0,$hier_cnt);
                }
                elsif ($line =~ m/^ *begin/){                               # only begin
                    $line_num           = __LINE__;
                    $if_begin           = $if_begin + 1;
                    $hier[$hier_cnt][2] = $hier[$hier_cnt][2]+1 ;          #add begin
                    $previous[2]        = 1 ;
                }
                elsif ($line =~ m/^ *else/){                                # else, no begin, no end
                    $line_num           = __LINE__;
                    if($previous[2] == 1 || $previous[3] == 1 ) {
                        $hier_cnt = $hier_cnt +1 ;
                    }
                    $hier[$hier_cnt] = [(1,0,0,0)];
                    @previous        =  (1,0,0,0,$hier_cnt);
                    if ( $line =~ /^ *else *case[xz]? *\(/){
                        $line_num           = __LINE__;
                        $hier_cnt = $hier_cnt +1 ;
                        $hier[$hier_cnt] = [(1,0,1,0)];
                        @previous        =  (1,0,1,0,$hier_cnt);
                    }
                    
                }
                elsif($line =~ m/^ *for *\(.*\) *begin/ ){                  # "for" begin  
                    $line_num           = __LINE__;
                    $hier_cnt           = $hier_cnt + 1;
                    $if_begin           = $if_begin + 1;                   #add begin
                    $hier[$hier_cnt][0] = $hier[$hier_cnt-1][0]; #keep if_en
                    $hier[$hier_cnt][1] = $hier[$hier_cnt-1][1]; #keep if_else
                    $hier[$hier_cnt][2] = 1; #add begin
                    $hier[$hier_cnt][3] = 0;
                    $previous[0]        = $hier[$hier_cnt][0];
                    $previous[1]        = $hier[$hier_cnt][1];
                    $previous[2]        = 1 ;
                    $previous[3]        = 0 ;
                    $previous[4]        = $line_cnt ;
                }
                elsif($line =~ m/^ *for *\(.*\)/ ){                         # for, no begin
                    $line_num           = __LINE__;
                    $hier_cnt = $hier_cnt + 1;
                    $hier[$hier_cnt][0] = $hier[$hier_cnt-1][0]; #keep if_en
                    $hier[$hier_cnt][1] = $hier[$hier_cnt-1][1]; #keep if_else
                    $hier[$hier_cnt][2] = 0; #don't add begin
                    $hier[$hier_cnt][3] = 0;
                    $previous[0]        = $hier[$hier_cnt][0];
                    $previous[1]        = $hier[$hier_cnt][1];
                    $previous[2]        = 0 ;
                    $previous[3]        = 0 ;
                    $previous[4]        = $line_cnt ;
                }
                elsif($line =~ m/^ *case[xz]? *\(.*\)/ ){                   #for case, casex, casez
                    $line_num           = __LINE__;
                    $hier_cnt = $hier_cnt + 1;
                    $hier[$hier_cnt][0] = 1; #same as if_en
                    $hier[$hier_cnt][1] = 0; #regard it as "else"
                    $hier[$hier_cnt][2] = 1; #regard it has "begin"
                    $hier[$hier_cnt][3] = 0;
                    $previous[0]        = 1;
                    $previous[1]        = 0;
                    $previous[2]        = 1 ;
                    $previous[3]        = 0 ;
                    $previous[4]        = $line_cnt ;
                }
                elsif($line =~m/^ *default *: *begin/){                      #case  default branch with begin
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 1;
                    if($previous[2] == 1 || $previous[3] == 1 ) {            # if-else with begin, or has one line 
                        $hier_cnt = $hier_cnt + 1;
                    }
                    $hier[$hier_cnt] = [(1,0,1,0)];
                    @previous        =  (1,0,1,0,$hier_cnt);
                }
                elsif($line =~m/^ *default *:/){                            #case  default branch without begin
                    $line_num           = __LINE__;
                    if($previous[2] == 1 || $previous[3] == 1 ) {           # if-else with begin, or has one line 
                        $hier_cnt = $hier_cnt + 1;
                    }
                    $hier[$hier_cnt] = [(1,0,0,0)];
                    @previous        =  (1,0,0,0,$hier_cnt);
                    if($line =~ /.*: *if *\(.*\) *begin/) {                    #with begin
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,1,0)];                     
                        @previous        =  (1,1,1,0,$hier_cnt);
                    } 
                    elsif($line =~ /.*: *if *\(/){                             #without begin
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,0,0)];                    
                        @previous        =  (1,1,0,0,$hier_cnt);
                    }
                }
                elsif($line =~m/^ *(([\w']+)|(\w+(\[\w+\])?)|(`\w+)) *: *begin/){      #case other branch with begin as AAAA,2'b00,3'd7,4'hf, `DEF
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 1;
                    if($previous[2] == 1 || $previous[3] == 1 ) {           # if-else with begin, or has one line 
                        $hier_cnt = $hier_cnt + 1;
                    }
                    $hier[$hier_cnt] = [(1,1,1,0)];
                    @previous        =  (1,1,1,0,$hier_cnt);
                }
                elsif($line =~m/^.*, *(([\w']+)|(\w+(\[\w+\])?)|(`\w+)) *: *begin/){      #case other branch with begin as "," AAAA,2'b00,3'd7,4'hf, `DEF
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 1;
                    if($previous[2] == 1 || $previous[3] == 1 ) {           # if-else with begin, or has one line 
                        $hier_cnt = $hier_cnt + 1;
                    }
                    $hier[$hier_cnt] = [(1,1,1,0)];
                    @previous        =  (1,1,1,0,$hier_cnt);
                }
                elsif($line =~m/^ *(([\w']+)|(\w+(\[\w+\])?)|(`\w+)) *:/){          #case other branch without begin  2'b00
                    $line_num        = __LINE__;
                    if($previous[2] == 1 || $previous[3] == 1 ) {           # if-else with begin, or has one line 
                        $hier_cnt = $hier_cnt + 1;
                    }
                    $hier[$hier_cnt] = [(1,1,0,0)];
                    @previous        =  (1,1,0,0,$hier_cnt);
                    if($line =~ /.*: *if *\(.*\) *begin/) {                    #with begin
                        $line_num        = __LINE__;
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,1,0)];                      
                        @previous        =  (1,1,1,0,$hier_cnt);
                    } 
                    elsif($line =~ /.*: *if *\(/){                             #without begin
                        $line_num        = __LINE__;
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,0,0)];                      
                        @previous        =  (1,1,0,0,$hier_cnt);
                    }
                    elsif($line =~/.*: *case[xz]? *\(/){                        #xxxx : case
                        $line_num        = __LINE__;
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,1,0)];                      
                        @previous        =  (1,1,1,0,$hier_cnt);
                    }
                }
                elsif($line =~m/^.*, *(([\w']+)|(\w+(\[\w+\])?)|(`\w+)) *:/){          #case other branch without begin  2'b00
                    $line_num        = __LINE__;
                    if($previous[2] == 1 || $previous[3] == 1 ) {           # if-else with begin, or has one line 
                        $hier_cnt = $hier_cnt + 1;
                    }
                    $hier[$hier_cnt] = [(1,1,0,0)];
                    @previous        =  (1,1,0,0,$hier_cnt);
                    if($line =~ /.*: *if *\(.*\) *begin/) {                    #with begin
                        $line_num        = __LINE__;
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,1,0)];                      
                        @previous        =  (1,1,1,0,$hier_cnt);
                    } 
                    elsif($line =~ /.*: *if *\(/){                             #without begin
                        $line_num        = __LINE__;
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,0,0)];                      
                        @previous        =  (1,1,0,0,$hier_cnt);
                    }
                    elsif($line =~/.*: *case[xz]? *\(/){                        # xxxx: case 
                        $line_num        = __LINE__;
                        $hier_cnt = $hier_cnt + 1;
                        $hier[$hier_cnt] = [(1,1,1,0)];                      
                        @previous        =  (1,1,1,0,$hier_cnt);
                    }
                }
                elsif($always_begin == 1 && $if_begin == 0  && $line =~ m/^ *end/ && $line !~m/^ *end.*<=/) {        #always begin end, if_begin cnt inside =0;
                    $line_num           = __LINE__;
                    $always_begin       = 0;
                    $always_blk         = 0;
                    if($error_flag == 1) {  #check error flag
                        print LOGFILE "$always_print\n";
                    }
                    print ALLLOGFILE "$always_print\n";
                    $always_print =""; #clear $always_print
                }
                elsif($line =~ m/^ *endcase/) {                                    #end in word as end_xxx
                    if($previous[2]==1 || $previous[3]==1) {                       # xxx:begin 
                        $line_num           = __LINE__;
                        $hier_cnt = $hier_cnt -1 ;                                 #    A <= B;
                    }                                                              #end  //this end has minus one
                    else {
                        $line_num           = __LINE__;
                        $hier_cnt = $hier_cnt -2 ;                                 # to fix hier_cnt error if as XXX: A<=B;
                    } 
                    $previous[0] = $hier[$hier_cnt][0];                              #roll back previous
                    $previous[1] = $hier[$hier_cnt][1];                              #roll back previous
                    $previous[2] = $hier[$hier_cnt][2];                              #roll back previous
                    $previous[3] = $hier[$hier_cnt][3];                              #roll back previous
                    
                }
                elsif($line =~ m/^ *end\w+/) {                                    #end in word as end_xxx
                    $line_num           = __LINE__;
                }
                elsif($always_begin == 0 && ($if_begin == 0 || ($if_begin==1 && $line =~ m/^ *end/)) && $error_flag == 1 ){
                    #always block end
                    $always_blk         = 0;
                    if($if_begin == 0) {
                        $line_num           = __LINE__;
                        #DO not minus $hier_cnt
                    } 
                    else {
                        $line_num           = __LINE__;
                        $hier_cnt           = $hier_cnt -1 ;
                    }
                    print LOGFILE    "$always_print\n";
                    print ALLLOGFILE "$always_print\n";
                    $always_print =""; #clear $always_print
                    
                }
                elsif($line =~ m/^ *end/) {                                    #end, only end in one line
                    
                    if($hier_cnt == 0 && $hier[$hier_cnt][2]>=1 || $hier[$hier_cnt][2] >=2) {       #for "begin end without if/else
                        $line_num           = __LINE__;
                        $hier[$hier_cnt][2] = $hier[$hier_cnt][2] -1;
                    } 
                    else {  
                        $line_num           = __LINE__;
                        $hier_cnt           = $hier_cnt -1 ; 
                        if($hier[$hier_cnt][2]==0 && $hier_cnt!=0) {                               #-end high 1 hier without begin-end, hier back one more
                            $hier_cnt           = $hier_cnt -1 ; 
                        }
                    }
                    $if_begin           = $if_begin - 1;
                }
                elsif($line =~ m/[()&>!|~*%=]+.*<= / && $previous[0]==1 && $previous[2]==0 ) { 
                    #for complicated condition in "if/else if"
                    $line_num           = __LINE__;
                }
                elsif($line =~ m/(\w)+ *<= / && $previous[0]==1 && $previous[2]==0 ) {
                    #if (xxx) 
                    #    q<= d;  //hier_cnt--; but when check if need to print, hier_cnt should add back
                    $line_num           = __LINE__;
                    $hier_cnt           = $hier_cnt -1 ;
                    $previous[0]        = 0; #out of if block
                    $previous[3]        = 1; #with one line in if_no_begin block 
                    $hier_add           = 1; #add back
                        
                }
                elsif($line =~ m/.*\) *begin/) {     #for if (xxxxxxxxxx
                                                    #        xxxxxx) begin
                    $line_num        = __LINE__;
                    $if_begin        = $if_begin + 1;
                    $hier[$hier_cnt] = [(1,1,1,0)];                      
                    @previous        =  (1,1,1,0,$hier_cnt);
                }
                else{
                    $line_num           = __LINE__;
                }

                if($print_en) {
                    print "$space//-------> \$line_num=$line_num, \$hier_cnt=$hier_cnt ,\$always_blk = $always_blk, \$always_begin = $always_begin,\$hier\[\$hier_cnt\] = $hier[$hier_cnt][2] ";
                    if($hier_cnt < 0){
                        
                        print "[FATAL]: $vfile,force \$hier_cnt 0 ";
                        $hier_cnt = 0;
                        $fatal_exist= 1;
                    }
                } 

                $if_blk = 0;
                for( my $i =1; $i <= ($hier_cnt+$hier_add) ; $i=$i+1) {
                    if($hier[$i][1] == 1 ) {
                        $if_blk = 1;
                    }
                }    



                #Check regisger assignment
                #if($if_blk== 0){
                    if( $line =~ m/ *(if|for|case|casex|casez) *\(.*<=.*\)/){
                        #condition as if(a<=b)
                    }
                    elsif( $line=~ m/([^ ]+) *<= *(#[^ ])? *([^ ;]*) */){
                        if($print_en) {print ",\$left=$1,\$right=$3, "} ;
                            $check_en = 1;

                        if( exists($reg_hash{$1}{width}))  {
                            if($reg_hash{$1}{width} <= $get_filter) {
                                #if width <= N or if there is "Q<= Q" above
                                $check_en  = 0;
                            }
                            $left_num  = $reg_hash{$1}{left};
                            $right_num = $reg_hash{$1}{right};
                        }


                        if( $1 ne $3 && $check_en) {
                        }
                        elsif( $line=~ m/([^ ]+) *<= *(#[^ ])? *([^ ;]*) *([^ ;]*)/ && $check_en ){  #for A<= #1 A + 1;
                            if($4 ne "") {
                                if($print_en) {print "\$4=$4,"};
                            } else {
                                $reg_hash{$1}{check} = 0;  #remove check
                            }
                        }

                        if($if_blk == 0) { 
                            $error_line = 1;
                            if(exists($reg_hash{$1}{check})) {
                                if($reg_hash{$1}{check} == 0) { 
                                    $error_line = 0;
                                    if($print_en) {print "modify error_flag, "};

                                }
                            } 

                            if($error_line == 1) {
                                $error_flag = 1;
                                $error_file = 1; 
                                $err_cnt_total  = $err_cnt_total + 1;
                                $err_cnt_per_file = $err_cnt_per_file + 1;
                                if (exists($reg_hash{$1}{width})) {
                                    $always_print = "$always_print$space ERROR: $1\[$left_num:$right_num\]***************should add assignment condition for power saving!"
                                }
                                else {
                                    $always_print = "$always_print$space ERROR: $1***************should add assignment condition for power saving!"
                                }
                            }
                        }

                    }
                    #else {
                    #    if($print_en) { print "Script can not handle!" };
                    #}
                #}
                if($print_en) {print "\$if_blk = $if_blk, \$if_begin = $if_begin, \$error_flag=$error_flag\n" } ;
               
                $always_print = "$always_print \n";
                

            }
        }
            
    }     
    if($fatal_exist) {
        print FATALFILE "$vfile\n"
    }
    
    if ($vfile =~ m/\/rdl\//){
        $err_cnt_rdl = $err_cnt_rdl + $err_cnt_per_file;
    }
    else {
        $err_cnt_local = $err_cnt_local + $err_cnt_per_file;
    }
    return $error_file;
}

相关文章

网友评论

      本文标题:power_check.pl of Low Power RTL设

      本文链接:https://www.haomeiwen.com/subject/nsfuwqtx.html