├── doxyfile ├── Doxyfile.template ├── idv_doxyfile_sv.delta └── idv_doxylayout.xml ├── filter └── idv_doxyfilter_sv.pl ├── html └── idv_dox_footer.html ├── scripts ├── idv_doxyfile_tmplconv.pl └── makealldocs.sh └── test ├── Doxyfile.delta ├── Makefile ├── dofilter.sh ├── dotest.pl ├── test.cpp.golden ├── test.sv ├── test_incl.sv └── test_namespace.cpp.golden /doxyfile/idv_doxyfile_sv.delta: -------------------------------------------------------------------------------- 1 | # $Id$ 2 | #----------------------------------------------------------------------------- 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | # 16 | #----------------------------------------------------------------------------- 17 | # Title: Doxygen Doxyfile Delta File for SystemVerilog 18 | # Description: This doxyfile delta defines the delta's from the base template 19 | # to use doxygen with the IDV SystemVerilog filter. 20 | # Use with the idv_doxyfile_tmplconv.pl script. 21 | # 22 | # Original Author: Sean O'Boyle 23 | # Contact: seanoboyle@intelligentdv.com) 24 | # Company: Intelligent Design Verification 25 | # Company URL: http://intelligentdv.com 26 | # 27 | # Download the most recent version here: 28 | # http://intelligentdv.com/downloads 29 | # 30 | # File Bugs Here: http://bugs.intelligentdv.com 31 | # Project: DoxygenFilterSV 32 | # 33 | # File: idv_doxyfile_sv.delta 34 | # $LastChangedBy$ 35 | # $LastChangedDate$ 36 | # $LastChangedRevision$ 37 | # 38 | #----------------------------------------------------------------------------- 39 | FILE_PATTERNS = *.svh *.sv *.cpp *.c *.h 40 | EXAMPLE_PATTERNS = *.sv, *.svh 41 | EXTENSION_MAPPING = sv=C++ svh=C++ 42 | FILTER_PATTERNS = *.sv=/filter/idv_doxyfilter_sv.pl *.svh=/filter/idv_doxyfilter_sv.pl 43 | LAYOUT_FILE = /doxyfile/idv_doxylayout.xml 44 | CASE_SENSE_NAMES = YES 45 | JAVADOC_AUTOBRIEF = YES 46 | TAB_SIZE = 3 47 | EXTRACT_ALL = YES 48 | EXTRACT_PRIVATE = YES 49 | EXTRACT_STATIC = YES 50 | FULL_PATH_NAMES = NO 51 | STRIP_FROM_PATH = /idv/subversion 52 | STRIP_CODE_COMMENTS = NO 53 | INLINE_INFO = NO 54 | SHOW_DIRECTORIES = YES 55 | WARN_NO_PARAMDOC = YES 56 | WARN_FORMAT = "$file:$line: $text " 57 | RECURSIVE = YES 58 | EXCLUDE_SYMLINKS = YES 59 | SOURCE_BROWSER = YES 60 | REFERENCED_BY_RELATION = YES 61 | REFERENCES_RELATION = YES 62 | ALPHABETICAL_INDEX = YES 63 | HTML_DYNAMIC_SECTIONS = YES 64 | HTML_TIMESTAMP = YES 65 | GENERATE_LATEX = NO 66 | PDF_HYPERLINKS = NO 67 | USE_PDFLATEX = NO 68 | MACRO_EXPANSION = YES 69 | HAVE_DOT = YES 70 | TEMPLATE_RELATIONS = YES 71 | DOT_GRAPH_MAX_NODES = 1024 72 | DOT_TRANSPARENT = NO 73 | DOT_MULTI_TARGETS = YES 74 | SEARCHENGINE = YES 75 | SERVER_BASED_SEARCH = YES 76 | 77 | -------------------------------------------------------------------------------- /doxyfile/idv_doxylayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /filter/idv_doxyfilter_sv.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # $Id$ 3 | #----------------------------------------------------------------------------- 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | # 17 | #----------------------------------------------------------------------------- 18 | # Title: Doxygen Filter for the SystemVerilog Language 19 | # Description: This script converts SystemVerilog code to C++ "like" code 20 | # for the purpose of documenting in Doxygen. (This script 21 | # is not a language transalation script.) 22 | # The script traverses the input SV file line-by-line and outputs 23 | # a C++ like file. Specifics are noted in-line. 24 | # This script was generated heuristically - so there will likely 25 | # be new issues discovered. 26 | # 27 | # Usage: Doxygen: In your doxyfile define the FILTER_PATTERN as: 28 | # *.sv=/path/to/filter/idv_doxyfilter_sv.pl *.svh= myfile.cpp 31 | # The myfile.cpp will be generated from the myfile.sv. 32 | # Options: At this point there is only one option: 33 | # --package_mode - enables SV Package to CPP namespace conversion 34 | # NOTE: this feature is not yet fully functional - the 35 | # generated cpp is correct; but doxygen is confused 36 | # by our typical: 37 | # package foo; 38 | # `include file.sv 39 | # endpackage: foo 40 | # NOTE: options in doxyfile FILTER_PATTERN are not allowed -- so if you'd like 41 | # to use an option create a wrapper script and call the wrapper from 42 | # the doxyfile. An example shell script is found in the test/dofilter.sh path. 43 | # 44 | # 45 | # 46 | # NOTE: Search for TODO and HACK notations in-line 47 | # NOTE: HACK items are typically due to either: 48 | # 1) preprocessor macro used to define an SV keyword 49 | # (keywords need to be present in order for the filter to work) 50 | # 2) strange (and arguably illegal) SV coding 51 | # NOTE: Preprocessor Macros are a PITA! Doxygen does the replace for me - 52 | # and there are a number of instances where an SV pattern to CPP pattern 53 | # would work fine IF the preprocessor ran *before* the filter. Sooo... 54 | # TODO: integrate SV preprocessor that does the `DEFINE replaces in 55 | # this filter. 56 | # 57 | # Original Author: Sean O'Boyle 58 | # Contact: seanoboyle@intelligentdv.com) 59 | # Company: Intelligent Design Verification 60 | # Company URL: http://intelligentdv.com 61 | # 62 | # Download the most recent version here: 63 | # http://intelligentdv.com/downloads 64 | # 65 | # File Bugs Here: http://bugs.intelligentdv.com 66 | # Project: DoxygenFilterSV 67 | # 68 | # File: idv_doxyfilter_sv.pl 69 | # $LastChangedBy$ 70 | # $LastChangedDate$ 71 | # $LastChangedRevision$ 72 | # 73 | #----------------------------------------------------------------------------- 74 | 75 | use strict; 76 | use Getopt::Long; 77 | 78 | my $blockcomment = 0; 79 | my $doxyblockcomment = 0; 80 | my $str_back = ""; 81 | my $str_line_continue = 0; 82 | my $str_back_lc_start = ""; 83 | my $str_back_lc_mid = ""; 84 | my $str_back_lc_end = ""; 85 | my $macro_start = 0; 86 | my @macroargs; 87 | my $multiline_macro = 0; 88 | my $ifdef_start = 0; 89 | my $inline_comment = ""; 90 | my $inline_block_comment = ""; 91 | my $isdpi = 0; 92 | my $enum_start = 0; 93 | my $enum = 0; 94 | my $ml_assign_start = 0; 95 | my $ml_assign = 0; 96 | my $covergroup = 0; 97 | my $covergroup_name = ""; 98 | my $constraint = 0; 99 | my $program_start = 0; 100 | my $module_start = 0; 101 | my $interface_start = 0; 102 | my $interface_name = ""; 103 | my $interface_template_start = 0; 104 | my $stringconcat = 0; 105 | my $onelinestringconcat = ""; 106 | my $class = 0; 107 | my $classname = ""; 108 | my $class_start = 0; 109 | my $derived_class = 0; 110 | my $template_class = 0; 111 | my $template_class_drop = 0; 112 | my $template_brackets = 0; 113 | my $template_inline_assign = ""; 114 | my $access_specifier = ""; 115 | my $function = 0; 116 | my $function_start = 0; 117 | my $ispure = 0; 118 | my $isextern = 0; 119 | 120 | my $moduleinterface = 0; 121 | my $moduleprogram = 0; 122 | my $modulemodule = 0; 123 | 124 | # Get command line options 125 | my $package_mode = ''; 126 | GetOptions ('package_mode' => \$package_mode # experimental feature - add support for SV packages -- make look like C++ namespace 127 | ); 128 | 129 | my @infile = <>; # slurp from STDIN 130 | 131 | my $angle_bracket_count = 0; 132 | my $paren_count = 0; 133 | 134 | my $infile_line = 0; 135 | # Process the SV File Line-by-Line 136 | # First Pass - Convert #() to <> 137 | foreach (@infile) { 138 | $inline_comment = ""; 139 | $infile_line++; 140 | 141 | # Skip Comments 142 | # TODO - this is the same comment routine as in the main section - make in to subroutine 143 | if (!$blockcomment) { 144 | if (s/\/\*(.*)\*\//\/\*\*\//) { # strip comment off of the line; leave the marker 145 | $inline_block_comment = $1; 146 | #print(STDERR $infile_line.": inline block comment \"".$inline_block_comment."\"\n"); 147 | } 148 | if (s/\/\/(.*)\\/\/\/\\/) { # Comment in a macro - leave the line escape 149 | $inline_comment = $1; 150 | #print(STDERR $infile_line.": inline macro comment \"".$inline_comment."\"\n"); 151 | } 152 | elsif (s/\/\/(.*)/\/\//) { # strip comment; leave the marker 153 | $inline_comment = $1; 154 | #print(STDERR $infile_line.": inline comment \"".$inline_comment."\"\n"); 155 | } 156 | } 157 | 158 | if ((!$inline_block_comment)&&(/\/\*/)) { 159 | $blockcomment = 1; 160 | } 161 | 162 | if ($blockcomment) { 163 | if (/\*\//) { # found the end of a block comment 164 | $blockcomment = 0; 165 | } 166 | next; # skip to next line of file 167 | } 168 | 169 | # Fixup any '# (' business; or '# (' etc etc 170 | s/\#\s+\(/\#\(/; 171 | 172 | # Find the #( 173 | # if the line has a start the iterate the line 174 | # if we are in an angle bracket then iterate the line 175 | if ((/\#\(/) || ($angle_bracket_count > 0)) { 176 | my $line = ""; 177 | my @chars = split(''); 178 | my $char_num = 0; 179 | foreach (@chars) { 180 | #print(STDERR "Char: ".$chars[$char_num]."\n"); 181 | if (($chars[$char_num] eq "#") && ($chars[$char_num+1] eq "(")) { 182 | $chars[$char_num] = "<"; 183 | $chars[$char_num+1] = ""; 184 | $angle_bracket_count++; 185 | } 186 | elsif (($angle_bracket_count > 0) && ($chars[$char_num] eq "(")) { 187 | $paren_count++; 188 | } 189 | elsif (($angle_bracket_count > 0) && ($paren_count <= 0) && ($chars[$char_num] eq ")")) { 190 | $chars[$char_num] = "> "; 191 | $angle_bracket_count--; 192 | } 193 | elsif (($angle_bracket_count > 0) && ($chars[$char_num] eq ")")) { 194 | $paren_count--; 195 | } 196 | 197 | # reassemble the line 198 | $line = $line.$chars[$char_num]; 199 | $char_num++; 200 | } 201 | # Put the back 202 | $_ = $line; 203 | } 204 | 205 | # Return the Inline Comment to the End of the Line 206 | # NOTE: doxygen cannot handle an inline comment in a macro -- SV specifies that those comments should be ignored 207 | if ($inline_comment ne "") { 208 | s/\/\//\/\/$inline_comment/; 209 | } 210 | $inline_comment = ""; 211 | if ($inline_block_comment ne "") { 212 | s/\/\*\*\//\/\*$inline_block_comment\*\//; 213 | $inline_block_comment = ""; 214 | } 215 | 216 | } 217 | 218 | 219 | $infile_line = 0; 220 | # Process the SV File Line-by-Line 221 | foreach (@infile) { 222 | $inline_comment = ""; 223 | $infile_line++; 224 | 225 | # Fix DOS Files 226 | s/\r//g; 227 | 228 | #----------------------------------------------------------------------------- 229 | # 230 | # Deal with Comments 231 | # 232 | #----------------------------------------------------------------------------- 233 | # Detect Single Line Comments 234 | # Looking for: 235 | # ... // comment 236 | # or 237 | # ... /// doxygen comment 238 | # or 239 | # ... /* comment */ 240 | # Current Strategy: 241 | # - skip all commented lines 242 | # - Don't want to filter the comment so we remove the comment 243 | # - BUT - we want to save the comment if it was an inline or doxygen comment 244 | # so we'll put back the comment at the end 245 | # - And - comments in macro - leave the line escape 246 | if (!$blockcomment) { 247 | if (s/\/\*(.*)\*\//\/\*\*\//) { # strip comment off of the line; leave the marker 248 | $inline_block_comment = $1; 249 | #print(STDERR $infile_line.": inline block comment \"".$inline_block_comment."\"\n"); 250 | } 251 | if (s/\/\/(.*)\\/\/\/\\/) { # Comment in a macro - leave the line escape 252 | $inline_comment = $1; 253 | #print(STDERR $infile_line.": inline macro comment \"".$inline_comment."\"\n"); 254 | } 255 | elsif (s/\/\/(.*)/\/\//) { # strip comment; leave the marker 256 | $inline_comment = $1; 257 | #print(STDERR $infile_line.": inline comment \"".$inline_comment."\"\n"); 258 | } 259 | 260 | } 261 | 262 | # Block Comment Start 263 | # Looking for: 264 | # /* 265 | # Current Strategy: 266 | # - skip all commented lines 267 | if ((!$inline_block_comment)&&(/\/\*/)) { 268 | $blockcomment = 1; 269 | } 270 | 271 | # Detect Doxygen Block Comment 272 | # Looking for: 273 | # /** 274 | # Current Strategy: 275 | # - skip all commented lines 276 | if (/\/\*\*/) { 277 | $doxyblockcomment = 1; 278 | } 279 | 280 | # Detect Doxygen Block Comment 281 | # Looking for: 282 | # /*! 283 | # Current Strategy: 284 | # - skip all commented lines 285 | if (/\/\*\!/) { 286 | $doxyblockcomment = 1; 287 | } 288 | 289 | # Skip Block Commented Code 290 | # We don't try to filter SV code that is commented 291 | # Current Strategy: 292 | # - skip all commented lines 293 | if ($blockcomment) { 294 | if ($doxyblockcomment) { 295 | # Inside a doxygen block commente 296 | # we can look for @ or \ markup in here 297 | # if we want to do something special 298 | } 299 | if (/\*\//) { # found the end of a block comment 300 | $blockcomment = 0; 301 | $doxyblockcomment = 0; 302 | } 303 | print; 304 | next; # skip to next line of file 305 | } 306 | 307 | # Detect and Skip Full Anything in a String 308 | # Don't want to convert keywords that are in the body of a string 309 | # Looking for: 310 | # " ... " 311 | # Current Strategy: 312 | # - delete anything inside of double quotes 313 | # - get rid of the entire line 314 | # - exception - DPI import / export 315 | # - exception - string passed into a macro 316 | if (/\bexport\s+"DPI/) {} 317 | elsif (/\bimport\s+"DPI/) {} 318 | elsif (/^\s*`/){} 319 | elsif (/`"(\w+)`"/) {} 320 | elsif (s/"(.*)"/""/g) { 321 | $str_back = $1; 322 | } 323 | # String with a line continuation in the middle 324 | elsif ($str_line_continue) { # middle of string 325 | #print STDERR "in string\n"; 326 | if (s/(.*)"/lcend"/) { # end of string 327 | $str_back_lc_end = $1; 328 | #print STDERR "end of string ".$str_back_lc_end." \n"; 329 | #print STDERR $_."\n"; 330 | } 331 | elsif (s/(.*)\\/lcmiddle\\/) { # middle of string 332 | $str_back_lc_mid = $1; 333 | } 334 | else { 335 | die "FATAL: bad string line continuation at file line ".$infile_line; 336 | } 337 | 338 | } 339 | elsif (s/"(.*)\\$/"lcstart\\/) { # start of string 340 | $str_back_lc_start = $1; 341 | $str_line_continue = 1; 342 | } 343 | else { 344 | $str_back = ""; 345 | } 346 | 347 | # Keep Track of Where we are in Angle Brackets 348 | if (//) { 349 | my @chars = split(''); 350 | foreach (@chars) { 351 | if ($_ eq "<") { 352 | $template_brackets++; 353 | } 354 | elsif ($_ eq ">") { 355 | $template_brackets--; 356 | } 357 | } 358 | } 359 | 360 | #----------------------------------------------------------------------------- 361 | # 362 | # Deal with Symbols that Break Doxygen Parsing 363 | # -- tickmarks need to be closed in doxygen - so get rid of all SV unclosed tickmarks 364 | # 365 | #----------------------------------------------------------------------------- 366 | # Literals with X or Z 367 | # Looking for: 368 | # ... 5'h.X.. 369 | # ... 5'b.Z.. 370 | # ... 5'd.z.. 371 | # Current Strategy: 372 | # - no strategy 373 | # - TODO: if we encounter an issue - put the fix here 374 | 375 | # Sized Literals 376 | # Looking for: 377 | # ... 5'h... 378 | # ... 5'b... 379 | # ... 5'd... 380 | # Current Strategy: 381 | # - change to 0x, 0b, 0d 382 | s/\d+\s*'[h|H]/0x/; 383 | s/\d+\s*'[d|D]/0d/; 384 | s/\d+\s*'[b|B]/0b/; 385 | s/\d+\s*'[o|O]/0o/; 386 | 387 | # UnSized Literals 388 | # Looking for: 389 | # ... 'h... 390 | # ... 'b... 391 | # ... 'd... 392 | # Current Strategy: 393 | # - change to 0x, 0b, 0d 394 | s/'[h|H]/0x/; 395 | s/'[d|D]/0d/; 396 | s/'[b|B]/0b/; 397 | s/'[o|O]/0o/; 398 | 399 | # Static Casting 400 | # SV static cast uses a tick (') where C++ foregoes the tick 401 | # Looking for: 402 | # ... typename'(value or equation) ... 403 | # Current Strategy: 404 | # - make it look like a C++ static cast: typename(value or equation) by removing the tick 405 | s/(.+)\s*'\s*\((.+)\)/$1($2)/; 406 | s/(.+)\s*'\s*\{(.+)\}/$1($2)/; 407 | 408 | # Remaining Tickmarks 409 | # Looking for: 410 | # ...'... 411 | # Current Strategy: 412 | # - get rid of any tickmarks that remain (after the above more accurate conversions) 413 | s/'//g; 414 | 415 | #----------------------------------------------------------------------------- 416 | # 417 | # Deal with Macros 418 | # 419 | #----------------------------------------------------------------------------- 420 | # Preprocessor Macros 421 | # Looking for: 422 | # Anything that starts with a backtick (`) 423 | # Current Strategy: 424 | # - HACK: hand replace any defines that are used to define SV keywords 425 | # especially those that this filter needs to see to generate correct documentation 426 | # - replace the backtick with a pound sign (#) for defined C++ macros 427 | # - double tick (``) concatenation is replaced with ## concatination 428 | # - escaped quotes (`") around an argument (single word) are replaced with stringizer (#) 429 | # - anything else that starts with a tick (`) is assume to be a #define - so the tick is removed 430 | # - continue filtering the line 431 | # - skip over strings - including strings that continue over multiple lines 432 | # TODO: improve algorithm for stringizer replacement -- should only use stringizer on macro arguments 433 | 434 | # HACK - in OVM `define for _protected is protected 435 | s/`_protected/protected/; 436 | # HACK: teal/truss preprocessor macro: `PURE pure 437 | s/`PURE/pure/; 438 | # HACK: vmm preprocessor macro: VMM_HW_RTL_COMPONENT_START interface 439 | s/`VMM_HW_RTL_COMPONENT_START\b/interface/; 440 | # HACK: vmm preprocessor macro: VMM_HW_RTL_COMPONENT_END endinterface 441 | s/`VMM_HW_RTL_COMPONENT_END\b/endinterface/; 442 | 443 | $macro_start = 0; 444 | if (/^\s*`/) { 445 | $macro_start = 1; 446 | s/`(define|error|import|undef|elif|if|include|using|else|ifdef|line|endif|ifndef|pragma)/#$1/; 447 | s/``/##/g; # concatenate 448 | s/`"(\w+)`"/#$1/; # stringize - assuming that any single word between escaped quotes should be stringized 449 | s/`"/"/g; # escaped quotes that aren't stringized inputs -> convert to quotes 450 | s/`\\/\\/g; 451 | s/`(\w)/$1/g; 452 | if (s/"(.*)"/""/g) { 453 | $str_back = $1; 454 | } 455 | elsif (s/"(.*)\\$/"lcstart\\/) { # start of string 456 | $str_back_lc_start = $1; 457 | $str_line_continue = 1; 458 | } 459 | if (/\\\s*$/) { 460 | $multiline_macro = 1; 461 | } 462 | } 463 | 464 | # Multiline Preprocessor Macros 465 | # Assuming that the only use of line continuation marker is for multiline preprocessor macros 466 | # Looking for: 467 | # Line Continuation (\) LF 468 | # Current Strategy: 469 | # - continue filtering the line 470 | # - the last line of the macro doesn't have an escape - so we keep track of this 471 | if ($multiline_macro) { 472 | s/``/##/g; # concatenate 473 | s/`"(\w+)`"/#$1/; # stringize - assuming that any single word between escaped quotes should be stringized 474 | s/`"/"/g; # escaped quotes that aren't stringized inputs -> convert to quotes 475 | s/`\\/\\/g; 476 | s/`(\w)/$1/g; 477 | if (/\\\s*$/) { 478 | $multiline_macro = 1; 479 | } 480 | else { 481 | $multiline_macro = 0; 482 | } 483 | } 484 | 485 | # Remaining BackTickmarks 486 | # Looking for: 487 | # ...`... 488 | # Current Strategy: 489 | # - get rid of any backtickmarks that remain (after the above more accurate conversions) 490 | s/`//g; 491 | 492 | #----------------------------------------------------------------------------- 493 | # 494 | # Deal with Stuff that C++ Doesn't Have 495 | # 496 | #----------------------------------------------------------------------------- 497 | # Coverage Groups 498 | # Looking for: 499 | # covergroup covergroup_name; 500 | # ... 501 | # endgroup 502 | # Current Strategy: 503 | # - Make look like C function that returns type covergroup 504 | # NOTE:Dealing with the contents of a covergroup is tough b/c of all of the curly braces 505 | if (s/\bcovergroup\b/function covergroup/) { # make look like function for function processing (below) 506 | $covergroup = 1; 507 | } 508 | if ($covergroup) { 509 | s/\@(.*?);/;/; #remove sampling 510 | } 511 | if (s/\bendgroup\b/endfunction/) { # make look like function for function processing (below) 512 | $covergroup = 0; 513 | } 514 | 515 | # Constraints 516 | # Looking for: 517 | # constraint constraint_name { 518 | # ... 519 | # } 520 | # Current Strategy: 521 | # - change to make it look like a method that returns type constraint 522 | # 523 | s/\bconstraint(\s+)(\S+);/constraint $2();/; 524 | s/\bconstraint(\s+)(\S+)(\s*)\{/constraint $2() { /; 525 | 526 | # Program Block 527 | # SV Program Block 528 | # Looking for: 529 | # ... program foo; 530 | # ... program foo(...); 531 | # ... program foo(... 532 | # Current Strategy: 533 | # - make look like C++ function that returns type program 534 | if (/\bprogram\s+(\w)\s*/) { 535 | $program_start = 1; 536 | $moduleprogram = 1; 537 | if (s/\bprogram\s+(\w+)\s*\((.*?)\)/\/** \@ingroup SVprogram *\/program $1($2)/) {} 538 | elsif (s/\bprogram\s+(\w+)\s*\((.*?)/\/** \@ingroup SVprogram *\/program $1($2/) {} 539 | else {s/\bprogram\s+(\w+)/\/** \@ingroup SVprogram *\/program $1(/;} 540 | } 541 | if ($program_start) { 542 | if (s/\)\s*;/) {/) { 543 | $program_start = 0; 544 | } 545 | elsif (s/;/) {/) { 546 | $program_start = 0; 547 | } 548 | } 549 | 550 | # Initial Block, Final Block 551 | # Looking for: 552 | # ... initial ... 553 | # ... final ... 554 | # Current Strategy: 555 | # - remove keyword (initial is always followed by begin - begin is transformed to '{' so contents of initial block just look like new scope 556 | s/\binitial\b//; 557 | s/\bfinal\b//; 558 | 559 | # Virtual Interface Declaration 560 | # Looking for: 561 | # ... virtual interface foo ... 562 | # Current Strategy: 563 | # - make look like C++ variable of type foo (remove string 'virtual interface' 564 | s/\bvirtual\s+?interface//; 565 | 566 | # Interface (and Module) Block 567 | # SV Interface Block 568 | # Looking for: 569 | # ... interface foo; 570 | # ... interface foo(...); 571 | # ... interface foo(... 572 | # ... interface foo #(...) (...); 573 | # ... interface foo #(...); 574 | # ... interface foo #(... 575 | # ...) (...); 576 | # ... interface foo #(... 577 | # ...); 578 | # Current Strategy: 579 | # - make look like C++ function that returns type interface 580 | if (s/\b(interface|module)(\s+)/\/** \@ingroup SV$1 *\/$1$2/) { 581 | 582 | if ($1 eq "interface") { 583 | $moduleinterface = 1; 584 | } 585 | if ($1 eq "module") { 586 | $modulemodule = 1; 587 | } 588 | 589 | $interface_start = 1; 590 | if (s/\b(interface|module)\s+(\w+)\s*?\((.*?)\)/$1 $2($3)/) {} 591 | elsif (s/\b(interface|module)\s+(\w+)\s*\((.*?)/$1 $2($3/) {} 592 | elsif (/\b(interface|module)\s+(\w+)\s*\(/) { 593 | $interface_start = 1; 594 | $interface_name = $1; 595 | } 596 | else {s/\b(interface|module)\s+(\w+);/$1 $2();/;} 597 | 598 | if (s/\b(interface|module)\s+(\w+)\s*/> $interface_name/) { 615 | $interface_template_start = 0; 616 | } 617 | } 618 | 619 | if ($interface_start) { 620 | if (s/\)\s*;/) {/) { 621 | $interface_start = 0; 622 | $template_brackets = 0; 623 | $interface_template_start = 0; 624 | } 625 | elsif (s/;/() {/) { 626 | $interface_start = 0; 627 | $template_brackets = 0; 628 | $interface_template_start = 0; 629 | } 630 | } 631 | 632 | # Logic Types with defined widths 633 | # Looking for: 634 | # logic [10:4] foo ... 635 | # bit[1:0] wee ... 636 | # 637 | # Current Strategy: 638 | # - Convert to a C++ template class instance 639 | s/\b(logic|bit|wire|reg)\s*?\[(.+?):(.+?)\]\s*?/$1 <$2:$3> /g; 640 | 641 | # Static Sized Arrays defined with ranges 642 | # Looking for: 643 | # ... foo [1:54]... 644 | # ... goo [54:1]... 645 | # 646 | # Current Strategy: 647 | # - Convert to a C++ style array (do the math) 648 | if (/\[(\d):(\d)\]/) { 649 | my $num1 = $1; 650 | my $num2 = $2; 651 | my $size = 0; 652 | if ($num1 < $num2) { 653 | $size = $num2 - $num1 + 1; 654 | } 655 | else { 656 | $size = $num1 - $num2 + 1; 657 | } 658 | s/\[(\d):(\d)\]/[$size]/; 659 | } 660 | 661 | # Timescale / Timeunit / TimePrecision: 662 | # Have no meaning to C++ and are typically on their own line in SV 663 | # Current Strategy: 664 | # - get rid of the entire line 665 | # 666 | if (/\btimescale\b/) { 667 | print "\n"; 668 | next; # skip to next line of file 669 | } 670 | if (/\btimeunit\b/) { 671 | print "\n"; 672 | next; # skip to next line of file 673 | } 674 | if (/\btimeprecision\b/) { 675 | print "\n"; 676 | next; # skip to next line of file 677 | } 678 | 679 | # DPI Exports 680 | # A DPI Export makes a method in this scope available to an external codebase 681 | # TODO: take care of multiline dpi export 682 | # Looking for: 683 | # - export \s+"DPI... 684 | # Current Strategy: 685 | # - get rid of the entire line 686 | if (/\bexport\s+"DPI/) { 687 | print "\n"; 688 | next; # skip to next line of file 689 | } 690 | 691 | #----------------------------------------------------------------------------- 692 | # 693 | # Deal with Stuff that C++ Does Have -- convert the syntax from SV to C++ 694 | # 695 | #----------------------------------------------------------------------------- 696 | 697 | # DPI Imports 698 | # A DPI Import is just another method available at the scope where the import occured 699 | # Looking for: 700 | # - import "DPI.." function 701 | # Current Strategy: 702 | # - make it look like a C++ function; remove the import "DPI.." 703 | if (/\bimport\s+"DPI/) { 704 | $isdpi = 1; 705 | $function_start = 1; 706 | s/import\s+"DPI.*".*function/function/; 707 | s/import\s+"DPI.*".*task/task/; 708 | } 709 | 710 | # Pass by Reference 711 | # 712 | # Looking for: ... ref foo ... 713 | # Current Strategy: 714 | # - make it look like a C++ reference 715 | # NOTE: this isn't really required -- doxygen can still parse with 'ref' 716 | #s/\bref\s+(\w+)/$1&/; 717 | 718 | # Packages 719 | # An SV package is very similar to a C++ namespace; 720 | # Looking for: 721 | # - package mypackage; 722 | # - import mypackage; 723 | # - import mypackage::*; 724 | # - import mypackage::foo; 725 | # Current Strategy: 726 | # - make it look like a C++ namespace 727 | if ($package_mode) { # Optional because doxygen doesn't like how we typically do packages in SV (with `include) 728 | s/\bpackage\b(.*?);/namespace $1 {/; 729 | s/\bendpackage\s*:\s*\S+/}/; 730 | s/\bendpackage\b/}/; 731 | s/\bimport\s+(\w+)::\*\s*;/using namespace $1;/; 732 | s/\bimport\s+(\w+)::(.*)\s*;/using $1::$2;/; 733 | s/\bimport\s+(\w+)\s*;/using namespace $1;/; 734 | } 735 | else { 736 | s/\bpackage\b(.*?);//; 737 | s/\bendpackage\s*:\s*\S+//; 738 | s/\bendpackage\b//; 739 | s/\bimport\s+(\w+)::\*\s*;//; 740 | s/\bimport\s+(\w+)::(.*)\s*;//; 741 | s/\bimport\s+(\w+)\s*;//; 742 | s/extends\s+(\w+)::(\w+)/extends $2/; 743 | } 744 | 745 | 746 | # Case Statement 747 | # SV case looks exactly like C++ case except that C++ case opens with { 748 | # SV also has special types of case not in C++ (casez, casex) 749 | # Current Strategy: 750 | # - change casex and casez to case 751 | # - open case like C++ 752 | s/\bcasez\b/case/; 753 | s/\bcasex\b/case/; 754 | if (/\bcase\b/) { 755 | s/case(.*)\)/case $1) { /; 756 | } 757 | 758 | # Class 759 | # A C++ class looks exactly like an SV class with these exceptions: 760 | # - derived class different keyword (taken care of above) 761 | # - C++ class opens with { while SV class opens with ; 762 | # SV: class myderivedclass extends mybaseclass; ... 763 | # C++: class myderivedclass : public mybaseclass { ... 764 | # - A forward declared class in SV is the SAME as one in C++ 765 | # - SV parameterized class looks different from a C++ template: 766 | # o class C #(int size = 1); ... // base class 767 | # o class C #(type T = bit); ... // base class 768 | # o class D1 #(type P = real) extends C; // T is bit (the default) 769 | # o class D2 #(type P = real) extends C #(integer); // T is integer 770 | # o class D3 #(type P = real) extends C #(P); // T is P 771 | # becomes: 772 | # o template class C { ... // base class 773 | # o template class C { ... } // base class 774 | # o template class D1 : public C { // T is bit (the default) 775 | # o template class D2 : public C { // T is integer 776 | # o template class D3 : public C

// T is P 777 | # Current Strategy: 778 | # - convert SV class to C++ Class 779 | # - convert SV Parameterized class to C++ template class 780 | # 781 | s/\btype REQ=int,RSP=int/typename REQ=int, typename RSP=int/; # HACK: support for OVM weirdness 782 | 783 | # Apparently a space between the class name and the parameterized list is not required - so let's add one - since that's what the rest of this filter expects 784 | s/(\w)(<)/$1 $2/; 785 | 786 | if (/\bclass(\s+)(\S+)/) { # was /class(\s+)(\w+)/ -- but need to support class definition in macros 787 | $class_start = 1; 788 | $classname = $2; 789 | # C++ does not declare abstract classes (C++ abstract class just has pure methods declared) 790 | if (/\bvirtual\b/) { 791 | s/virtual\s+class/class/; 792 | } 793 | # forward reference 794 | # in SV a forward reference looks like: typedef class myclass; 795 | # in C++ it looks like: class myclass; 796 | if (/typedef/) { 797 | s/typedef\s+class(.*;)/class $1/; 798 | $class_start = 0; 799 | } 800 | } 801 | if ($class_start) { 802 | s/\btype /typename /g; # 'typename' and 'class' are equivalent 803 | if (s/;/ { public: /) { # SV defaults to public; C++ defaults to private 804 | $class = 1; # we're in a class body 805 | $class_start = 0; 806 | $access_specifier = "public"; 807 | } 808 | if (/class(\s+)(\S+)(\s*)\s+extends\s+(.*)$/$1> class $classname extends $2/) { 820 | $template_class_drop = 1; # dropped class name 821 | } 822 | elsif (s/(.*)>(.*)$/$1> class $classname $2/) { 823 | #print STDERR "Current Line: >".$_."\n"; 824 | $template_class_drop = 1; #dropped class name 825 | #print (STDERR "Dropped\n"); 826 | } 827 | elsif ($infile[$infile_line] =~ /^(\s*?) 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 | 43 | 51 | 62 | 69 | 70 |
44 |
45 | 46 | Intelligent Design Verification
47 | Intelligent Design Verification
48 | Project: $projectname, Revision: $projectnumber
49 |
50 |
52 |
53 | Copyright (c) 2008-2010 Intelligent Design Verification.
54 | Permission is granted to copy, distribute and/or modify this document 55 | under the terms of the GNU Free Documentation License, Version 1.2 56 | or any later version published by the Free Software Foundation; 57 | with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
58 | A copy of the license is included here:
59 | http://www.intelligentdv.com/licenses/fdl.txt
60 |
61 |
63 |
64 | doxygen
65 | Doxygen Version: $doxygenversion
66 | IDV SV Filter Version: 2.6.3
67 | $datetime
68 |
71 |

72 | Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV 73 |
74 | 75 | 76 | -------------------------------------------------------------------------------- /scripts/idv_doxyfile_tmplconv.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # $Id$ 3 | #----------------------------------------------------------------------------- 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | # 17 | #----------------------------------------------------------------------------- 18 | # Title: Doxygen Doxyfile Configuration file Template / Delta to Output 19 | # Description: This script converts an input Doxyfile template file and a 20 | # delta file and outputs a Doxyfile. The template Doxyfile is 21 | # a complete Doxyfile - usually generated from doxygen with a 22 | # 'doxygen -g' command. The delta Doxyfile is a set of changes 23 | # from the template doxyfile in a key = value format. Keys are 24 | # the keywords defined in the template Doxyfile. The script 25 | # grabs the key/value combinations from the delta file, searches 26 | # the template file for matching keys and replaces the values with 27 | # a new value from the delta file. 28 | # This script allows the generation of a single reference Doxyfile 29 | # (template) than can be altered slightly with project (delta). 30 | # 31 | # Usage: 32 | # idv_doxyfile_tmplconv.pl --path_doxyscr "../../../Doxygen" \ 33 | # --path_prj "../../../project" \ 34 | # --template Doxyfile.template \ 35 | # --delta Doxyfile.delta \ 36 | # --output Doxyfile.output 37 | # 38 | # NOTE: Search for TODO and HACK notations in-line 39 | # NOTE: Script does not support multiline value definitions in either the 40 | # template or delta file. (multiline == line with escaped \linefeed) 41 | # NOTE: No error / warning is generated when a match is not found 42 | # TODO: Add support for skipping commented (#) lines 43 | # 44 | # Original Author: Sean O'Boyle 45 | # Contact: seanoboyle@intelligentdv.com) 46 | # Company: Intelligent Design Verification 47 | # Company URL: http://intelligentdv.com 48 | # 49 | # Download the most recent version here: 50 | # http://intelligentdv.com/downloads 51 | # 52 | # File Bugs Here: http://bugs.intelligentdv.com 53 | # Project: DoxygenFilterSV 54 | # 55 | # File: idv_doxyfile_tmplconv.pl 56 | # $LastChangedBy$ 57 | # $LastChangedDate$ 58 | # $LastChangedRevision$ 59 | # 60 | #----------------------------------------------------------------------------- 61 | use strict; 62 | use Getopt::Long; 63 | 64 | # Get command line options 65 | my $path_home = ''; 66 | my $proj_name = ''; 67 | my $proj_num = ''; 68 | my $out_dir = ''; 69 | my $path_doxyscr = ''; 70 | my $path_prj = ''; 71 | my $template_file = ''; 72 | my $delta_file = ''; 73 | my $output_file = ''; 74 | GetOptions ('path_home=s' => \$path_home, 75 | 'proj_name=s' => \$proj_name, 76 | 'proj_num=s' => \$proj_num, 77 | 'out_dir=s' => \$out_dir, 78 | 'path_doxyscr=s' => \$path_doxyscr, 79 | 'path_prj=s' => \$path_prj, 80 | 'template=s' => \$template_file, 81 | 'delta=s' => \$delta_file, 82 | 'output=s' => \$output_file); 83 | 84 | open(TEMPLATE, '<', $template_file) or die "Can't open template file $!"; 85 | my @output_file_arr =