Monday, May 17, 2010

verilog/sv indent


  1 #!/usr/bin/perl

  2 # Author; Lifeng Chen, Magnum Semiconductor

  3 # Purpose: Indent verilog/systemverilog file

  4

  5 use Term::ANSIColor;

  6

  7 # Flow Control

  8 my $debug_me = 1;

  9

 10 ##TODO

 11 # 1. better indent for block-comment

 12

 13 # Space for each indent

 14 my $Space = "  ";

 15

 16 # comment definition.

 17 my $sl_delm = qw(// );

 18 my %block_delm = (

 19   '{' => '}',

 20   '(' => ')'

 21 );

 22

 23 # Note: Each Open keyword must have corresponding close keyword

 24 my @OpenSingle = qw{repeat for while if else};

 25 my @CloseSingle = qw{; };

 26

 27 my @OpenKeywords = qw{ begin module program package class task function fork case casex casez};  #interface

 28 my @CloseKeywords = qw{ end endmodule endprogram endpackage endclass endtask endfunction join join_none join_any endcase};  #endinterface

 29 my @IgnoreKeywords = qw{ extern typedef disable};

 30

 31 my @OpenSpecial = qw{ovm_field_utils_begin ovm_object_utils_begin ovm_object_param_utils_begin ovm_component_utils_begin};

 32 my @CloseSpecial = qw{ovm_field_utils_end ovm_object_utils_end ovm_object_param_utils_end ovm_component_utils_end};

 33

 34 @OpenKeywords = (@OpenKeywords, @OpenSpecial);

 35 @CloseKeywords = (@CloseKeywords, @CloseSpecial);

 36

 37 sub indent {

 38     my $open_block_comment=0, $close_block_comment=0, $in_block_comment=0;

 39     my $total_indent = 0, $block_indent = 0, $single_indent = 0, $last_indent=0;

 40     my($infile) = @_;

 41     my $tmpfile= "$infile.tmp";

 42     my $open_num=0, $close_num=0, $bracket_delta=0;

 43     my $cleaned_line;

 44

 45     print colored ['green'],"$infile\n";

 46     system("cp $infile $tmpfile");

 47

 48     open(TFILE, ">$tmpfile");

 49     open(FILE, "<$infile");

 50

 51     LINE_LOOP: while(my $line = <FILE>) {

 52         chomp $line;

 53         if ($open_block_comment==1 and $close_block_comment==0) {$in_block_comment = 1;}

 54         else {$in_block_comment = 0;}

 55         $line =~ s{$sl_delm(\w|\*)}{$sl_delm $1};  #remove false block-comment; append space after single-line comment symbol immediately followed by letters etc

 56         $cleaned_line=$line;

 57

 58         if ($cleaned_line =~ m{/\*}) {

 59             $open_block_comment=1;  #start a block comment

 60         }

 61         if ($cleaned_line =~ m{\*/}) {

 62             $close_block_comment=1; #end a block comment

 63         }

 64         if ($close_block_comment == 1) {  #clear block comment flag

 65             $open_block_comment=0;

 66             $close_block_comment=0;

 67         }

 68         #if ($in_block_comment) {$cleaned_line =~ s{^.*\*/}{*/};}  #remove anything in block comment, till end-block symbol is detected

 69         $cleaned_line=~s{"[^"]*"}{}g;  #remove keyword in string

 70         $cleaned_line =~ s{/\*.*\*/}{}g;  #remove keyword in a single-line block comment

 71         $cleaned_line =~ s{^.*\*/}{};  #remove keyword in block comment

 72         $cleaned_line =~ s{/\*.*$}{};  #remove keyword in block comment

 73         $cleaned_line=~ s{$sl_delm.*$}{};  #remove keyword in line comment

 74         $cleaned_line =~ s{\s+$}{};  #remove tailing blanks

 75         #if ($debug_me == 1 and $. >= 577 and $. <= 585) {

 76         #print "debug_me: $., blk_ind: $block_indent, sgl_ind: $single_indent, comment=$in_block_comment: '$cleaned_line'\n";

 77         #}

 78         if ($in_block_comment==1) {

 79             print TFILE "$line\n";  #keep things as they were in a block comment

 80             next LINE_LOOP;

 81         }

 82         $line =~ s/^\s+//;  #remove leading space to prepare for indent

 83         $line =~ s/\s+$//;  #remove any tailing space

 84

 85         #output the active line

 86         if ($line =~ m{^$sl_delm}) {  #indent single-line comment

 87             for($i=0;$i<$block_indent+$single_indent;$i++) { print TFILE $Space; }

 88             print TFILE "$line\n";

 89             next LINE_LOOP;

 90         }

 91

 92         foreach $CloseKey (@CloseKeywords) {

 93             if($cleaned_line =~ /\b$CloseKey\b/) { $block_indent--; $single_indent=0;}

 94         }

 95         $bracket_delta=0;

 96         foreach $open (keys %block_delm) { #indent brackets

 97           $close=$block_delm{"$open"};

 98           $open_num = ($cleaned_line =~ s/\Q$open\E/$open/isg);

 99           $close_num = ($cleaned_line =~ s/\Q$close\E/$close/isg);

100           $bracket_delta+=$open_num-$close_num;

101         }

102         if ($cleaned_line =~ /\S/) {for($i=0;$i<$block_indent+$single_indent;$i++) { print TFILE $Space; }}  #don't indent empty line

103         print TFILE "$line\n";

104         $start_block_line=0;

105         OPEN_BLOCK: foreach $OpenKey (@OpenKeywords) {

106             foreach $IgnoreKey (@IgnoreKeywords) {

107               if($cleaned_line =~ /\b$IgnoreKey\b/) { last OPEN_BLOCK;}

108             }

109             if($cleaned_line =~ /\b$OpenKey\b/) { $block_indent++; $start_block_line=1; }

110         }

111         if ($start_block_line == 0) {

112             OPEN_SINGLE: foreach $OpenKey (@OpenSingle) {

113                 if($cleaned_line =~ /\b$OpenKey\b/ and $cleaned_line !~ /`$OpenKey\b/ ) {

114                     $single_indent++;

115                 }

116             }

117             if ($single_indent > 0) {

118                 CLOSE_SINGLE: foreach $CloseKey (@CloseSingle) {

119                     if($cleaned_line =~ /$CloseKey$/) {

120                         $single_indent=0;

121                     }

122                 }

123             }

124         }

125         $block_indent+=$bracket_delta;

126         #if ($bracket_delta<0) {$block_indent+=$bracket_delta; }

127         #if ($bracket_delta>0) {$block_indent+=$bracket_delta; }

128         if ($block_indent < 0) {print colored ['yellow'],"\tindent_num = $block_indent @ cleaned_line $.. will be reset.\n"; $block_indent=0;}

129         $last_indent=$block_indent;

130     }

131     $total_indent=$block_indent + $single_indent;

132     if ($total_indent != 0) {print colored ['yellow'],"\tThe indentation of final line is not cleared to zero: $block_indent + $single_indent\n";}

133     close FILE; close TFILE;

134     system("mv -f $tmpfile $infile");

135 }

136

137 my $argnum;

138 if($ARGV[0] eq "" or $ARGV[0] =~ /-h/) {

139     print "Usage : $0 verilogfile.v\n";

140     print "        $0 *.sv\n";

141     print "        $0 *.*v*\n";

142     print "Help  :\n";

143     print "        $0\n";

144     exit(0);

145 }

146 print "Indenting...\n";

147 foreach $argnum (0 .. $#ARGV) {

148     my $ifile = $ARGV[$argnum];

149     &indent($ifile);

150 }

>

No comments: