1" Vim indent file 2" Language: SystemVerilog 3" Maintainer: kocha <[email protected]> 4" Last Change: 05-Feb-2017 by Bilal Wasim 5 6" Only load this indent file when no other was loaded. 7if exists("b:did_indent") 8 finish 9endif 10let b:did_indent = 1 11 12setlocal indentexpr=SystemVerilogIndent() 13setlocal indentkeys=!^F,o,O,0),0},=begin,=end,=join,=endcase,=join_any,=join_none 14setlocal indentkeys+==endmodule,=endfunction,=endtask,=endspecify 15setlocal indentkeys+==endclass,=endpackage,=endsequence,=endclocking 16setlocal indentkeys+==endinterface,=endgroup,=endprogram,=endproperty,=endchecker 17setlocal indentkeys+==`else,=`endif 18 19" Only define the function once. 20if exists("*SystemVerilogIndent") 21 finish 22endif 23 24let s:cpo_save = &cpo 25set cpo&vim 26 27function SystemVerilogIndent() 28 29 if exists('b:systemverilog_indent_width') 30 let offset = b:systemverilog_indent_width 31 else 32 let offset = shiftwidth() 33 endif 34 if exists('b:systemverilog_indent_modules') 35 let indent_modules = offset 36 else 37 let indent_modules = 0 38 endif 39 40 " Find a non-blank line above the current line. 41 let lnum = prevnonblank(v:lnum - 1) 42 43 " At the start of the file use zero indent. 44 if lnum == 0 45 return 0 46 endif 47 48 let lnum2 = prevnonblank(lnum - 1) 49 let curr_line = getline(v:lnum) 50 let last_line = getline(lnum) 51 let last_line2 = getline(lnum2) 52 let ind = indent(lnum) 53 let ind2 = indent(lnum - 1) 54 let offset_comment1 = 1 55 " Define the condition of an open statement 56 " Exclude the match of //, /* or */ 57 let sv_openstat = '\(\<or\>\|\([*/]\)\@<![*(,{><+-/%^&|!=?:]\([*/]\)\@!\)' 58 " Define the condition when the statement ends with a one-line comment 59 let sv_comment = '\(//.*\|/\*.*\*/\s*\)' 60 if exists('b:verilog_indent_verbose') 61 let vverb_str = 'INDENT VERBOSE:' 62 let vverb = 1 63 else 64 let vverb = 0 65 endif 66 67 " Indent according to last line 68 " End of multiple-line comment 69 if last_line =~ '\*/\s*$' && last_line !~ '/\*.\{-}\*/' 70 let ind = ind - offset_comment1 71 if vverb 72 echo vverb_str "De-indent after a multiple-line comment." 73 endif 74 75 " Indent after if/else/for/case/always/initial/specify/fork blocks 76 elseif last_line =~ '`\@<!\<\(if\|else\)\>' || 77 \ last_line =~ '^\s*\<\(for\|case\%[[zx]]\|do\|foreach\|forever\|randcase\)\>' || 78 \ last_line =~ '^\s*\<\(always\|always_comb\|always_ff\|always_latch\)\>' || 79 \ last_line =~ '^\s*\<\(initial\|specify\|fork\|final\)\>' 80 if last_line !~ '\(;\|\<end\>\)\s*' . sv_comment . '*$' || 81 \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . sv_comment . '*$' 82 let ind = ind + offset 83 if vverb | echo vverb_str "Indent after a block statement." | endif 84 endif 85 " Indent after function/task/class/package/sequence/clocking/ 86 " interface/covergroup/property/checkerprogram blocks 87 elseif last_line =~ '^\s*\<\(function\|task\|class\|package\)\>' || 88 \ last_line =~ '^\s*\<\(sequence\|clocking\|interface\)\>' || 89 \ last_line =~ '^\s*\(\w\+\s*:\)\=\s*\<covergroup\>' || 90 \ last_line =~ '^\s*\<\(property\|checker\|program\)\>' 91 if last_line !~ '\<end\>\s*' . sv_comment . '*$' || 92 \ last_line =~ '\(//\|/\*\).*\(;\|\<end\>\)\s*' . sv_comment . '*$' 93 let ind = ind + offset 94 if vverb 95 echo vverb_str "Indent after function/task/class block statement." 96 endif 97 endif 98 99 " Indent after module/function/task/specify/fork blocks 100 elseif last_line =~ '^\s*\(\<extern\>\s*\)\=\<module\>' 101 let ind = ind + indent_modules 102 if vverb && indent_modules 103 echo vverb_str "Indent after module statement." 104 endif 105 if last_line =~ '[(,]\s*' . sv_comment . '*$' && 106 \ last_line !~ '\(//\|/\*\).*[(,]\s*' . sv_comment . '*$' 107 let ind = ind + offset 108 if vverb 109 echo vverb_str "Indent after a multiple-line module statement." 110 endif 111 endif 112 113 " Indent after a 'begin' statement 114 elseif last_line =~ '\(\<begin\>\)\(\s*:\s*\w\+\)*' . sv_comment . '*$' && 115 \ last_line !~ '\(//\|/\*\).*\(\<begin\>\)' && 116 \ ( last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' || 117 \ last_line2 =~ '^\s*[^=!]\+\s*:\s*' . sv_comment . '*$' ) 118 let ind = ind + offset 119 if vverb | echo vverb_str "Indent after begin statement." | endif 120 121 " Indent after a '{' or a '(' 122 elseif last_line =~ '[{(]' . sv_comment . '*$' && 123 \ last_line !~ '\(//\|/\*\).*[{(]' && 124 \ ( last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' || 125 \ last_line2 =~ '^\s*[^=!]\+\s*:\s*' . sv_comment . '*$' ) 126 let ind = ind + offset 127 if vverb | echo vverb_str "Indent after begin statement." | endif 128 129 " De-indent for the end of one-line block 130 elseif ( last_line !~ '\<begin\>' || 131 \ last_line =~ '\(//\|/\*\).*\<begin\>' ) && 132 \ last_line2 =~ '\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|forever\|final\)\>.*' . 133 \ sv_comment . '*$' && 134 \ last_line2 !~ '\(//\|/\*\).*\<\(`\@<!if\|`\@<!else\|for\|always\|initial\|do\|foreach\|forever\|final\)\>' && 135 \ last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' && 136 \ ( last_line2 !~ '\<begin\>' || 137 \ last_line2 =~ '\(//\|/\*\).*\<begin\>' ) 138 let ind = ind - offset 139 if vverb 140 echo vverb_str "De-indent after the end of one-line statement." 141 endif 142 143 " Multiple-line statement (including case statement) 144 " Open statement 145 " Ident the first open line 146 elseif last_line =~ sv_openstat . '\s*' . sv_comment . '*$' && 147 \ last_line !~ '\(//\|/\*\).*' . sv_openstat . '\s*$' && 148 \ last_line2 !~ sv_openstat . '\s*' . sv_comment . '*$' 149 let ind = ind + offset 150 if vverb | echo vverb_str "Indent after an open statement." | endif 151 152 " Close statement 153 " De-indent for an optional close parenthesis and a semicolon, and only 154 " if there exists precedent non-whitespace char 155 elseif last_line =~ ')*\s*;\s*' . sv_comment . '*$' && 156 \ last_line !~ '^\s*)*\s*;\s*' . sv_comment . '*$' && 157 \ last_line !~ '\(//\|/\*\).*\S)*\s*;\s*' . sv_comment . '*$' && 158 \ ( last_line2 =~ sv_openstat . '\s*' . sv_comment . '*$' && 159 \ last_line2 !~ ';\s*//.*$') && 160 \ last_line2 !~ '^\s*' . sv_comment . '$' 161 let ind = ind - offset 162 if vverb | echo vverb_str "De-indent after a close statement." | endif 163 164 " `ifdef and `else 165 elseif last_line =~ '^\s*`\<\(ifdef\|else\)\>' 166 let ind = ind + offset 167 if vverb 168 echo vverb_str "Indent after a `ifdef or `else statement." 169 endif 170 171 endif 172 173 " Re-indent current line 174 175 " De-indent on the end of the block 176 " join/end/endcase/endfunction/endtask/endspecify 177 if curr_line =~ '^\s*\<\(join\|join_any\|join_none\|\|end\|endcase\|while\)\>' || 178 \ curr_line =~ '^\s*\<\(endfunction\|endtask\|endspecify\|endclass\)\>' || 179 \ curr_line =~ '^\s*\<\(endpackage\|endsequence\|endclocking\|endinterface\)\>' || 180 \ curr_line =~ '^\s*\<\(endgroup\|endproperty\|endchecker\|endprogram\)\>' || 181 \ curr_line =~ '^\s*}' 182 let ind = ind - offset 183 if vverb | echo vverb_str "De-indent the end of a block." | endif 184 elseif curr_line =~ '^\s*\<endmodule\>' 185 let ind = ind - indent_modules 186 if vverb && indent_modules 187 echo vverb_str "De-indent the end of a module." 188 endif 189 190 " De-indent on a stand-alone 'begin' 191 elseif curr_line =~ '^\s*\<begin\>' 192 if last_line !~ '^\s*\<\(function\|task\|specify\|module\|class\|package\)\>' || 193 \ last_line !~ '^\s*\<\(sequence\|clocking\|interface\|covergroup\)\>' || 194 \ last_line !~ '^\s*\<\(property\|checker\|program\)\>' && 195 \ last_line !~ '^\s*\()*\s*;\|)\+\)\s*' . sv_comment . '*$' && 196 \ ( last_line =~ 197 \ '\<\(`\@<!if\|`\@<!else\|for\|case\%[[zx]]\|always\|initial\|do\|foreach\|forever\|randcase\|final\)\>' || 198 \ last_line =~ ')\s*' . sv_comment . '*$' || 199 \ last_line =~ sv_openstat . '\s*' . sv_comment . '*$' ) 200 let ind = ind - offset 201 if vverb 202 echo vverb_str "De-indent a stand alone begin statement." 203 endif 204 endif 205 206 " De-indent after the end of multiple-line statement 207 elseif curr_line =~ '^\s*)' && 208 \ ( last_line =~ sv_openstat . '\s*' . sv_comment . '*$' || 209 \ last_line !~ sv_openstat . '\s*' . sv_comment . '*$' && 210 \ last_line2 =~ sv_openstat . '\s*' . sv_comment . '*$' ) 211 let ind = ind - offset 212 if vverb 213 echo vverb_str "De-indent the end of a multiple statement." 214 endif 215 216 " De-indent `else and `endif 217 elseif curr_line =~ '^\s*`\<\(else\|endif\)\>' 218 let ind = ind - offset 219 if vverb | echo vverb_str "De-indent `else and `endif statement." | endif 220 221 endif 222 223 " Return the indentation 224 return ind 225endfunction 226 227let &cpo = s:cpo_save 228unlet s:cpo_save 229 230" vim:sw=2 231