| 1 | # ========== Copyright Header Begin ========================================== |
| 2 | # |
| 3 | # OpenSPARC T2 Processor File: DiagList.pm |
| 4 | # Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved |
| 5 | # 4150 Network Circle, Santa Clara, California 95054, U.S.A. |
| 6 | # |
| 7 | # * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 8 | # |
| 9 | # This program is free software; you can redistribute it and/or modify |
| 10 | # it under the terms of the GNU General Public License as published by |
| 11 | # the Free Software Foundation; version 2 of the License. |
| 12 | # |
| 13 | # This program is distributed in the hope that it will be useful, |
| 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | # GNU General Public License for more details. |
| 17 | # |
| 18 | # You should have received a copy of the GNU General Public License |
| 19 | # along with this program; if not, write to the Free Software |
| 20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | # |
| 22 | # For the avoidance of doubt, and except that if any non-GPL license |
| 23 | # choice is available it will apply instead, Sun elects to use only |
| 24 | # the General Public License version 2 (GPLv2) at this time for any |
| 25 | # software where a choice of GPL license versions is made |
| 26 | # available with the language indicating that GPLv2 or any later version |
| 27 | # may be used, or where a choice of which version of the GPL is applied is |
| 28 | # otherwise unspecified. |
| 29 | # |
| 30 | # Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 31 | # CA 95054 USA or visit www.sun.com if you need additional information or |
| 32 | # have any questions. |
| 33 | # |
| 34 | # ========== Copyright Header End ============================================ |
| 35 | package DiagList; |
| 36 | |
| 37 | use 5.008; |
| 38 | use strict; |
| 39 | use warnings; |
| 40 | |
| 41 | use IO::File; |
| 42 | use Tie::IxHash; |
| 43 | use File::Spec; |
| 44 | use Carp; |
| 45 | |
| 46 | require Exporter; |
| 47 | |
| 48 | |
| 49 | use DiagList::Objects; |
| 50 | use DiagList::Output; |
| 51 | use DiagList::Settings; |
| 52 | use DiagList::Script; |
| 53 | |
| 54 | our @ISA = qw(Exporter); |
| 55 | |
| 56 | # Items to export into callers namespace by default. Note: do not export |
| 57 | # names by default without a very good reason. Use EXPORT_OK instead. |
| 58 | # Do not simply export all your public functions/methods/constants. |
| 59 | |
| 60 | # This allows declaration use DiagList ':all'; |
| 61 | # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK |
| 62 | # will save memory. |
| 63 | |
| 64 | our @script = qw(dlist); |
| 65 | our @triage = qw(hookup_triage_interface); |
| 66 | our @functions = qw(dlist construct_dlist get_diag_display build_tags); |
| 67 | |
| 68 | our %EXPORT_TAGS = ( all => [ @script, @triage, @functions ], |
| 69 | func => [ @functions ], |
| 70 | triage => [ @triage ], |
| 71 | script => [ @script ], |
| 72 | ); |
| 73 | |
| 74 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
| 75 | |
| 76 | our @EXPORT = qw( |
| 77 | ); |
| 78 | |
| 79 | our $VERSION = '1.11'; |
| 80 | |
| 81 | ############################################################################## |
| 82 | |
| 83 | sub hookup_triage_interface { |
| 84 | my $code = |
| 85 | q{ |
| 86 | use DiagList::TriageInterface; |
| 87 | }; |
| 88 | |
| 89 | eval $code; |
| 90 | die $@ if $@; |
| 91 | } |
| 92 | |
| 93 | ############################################################################## |
| 94 | ############################################################################## |
| 95 | ############################################################################## |
| 96 | 1; |
| 97 | __END__ |
| 98 | |
| 99 | =head1 NAME |
| 100 | |
| 101 | DiagList - perl module for parsing diag lists |
| 102 | |
| 103 | =head1 SYNOPSIS |
| 104 | |
| 105 | use DiagList; |
| 106 | |
| 107 | my $dlist = DiagList->new('./master_diaglist'); |
| 108 | my $group = $dlist->find_group('cmp_regr'); |
| 109 | |
| 110 | foreach my $buildtag ($group->build_tags) { |
| 111 | |
| 112 | my $buildargs = $dlist->build_args($buildtag); |
| 113 | |
| 114 | foreach my $diagname ($group->list_diags($buildtag)) { |
| 115 | my $diag = $group->find_diag($buildtag, $diagname); |
| 116 | my $runargs = $diag->get_cmdline(); |
| 117 | } |
| 118 | |
| 119 | } |
| 120 | |
| 121 | |
| 122 | =head1 ABSTRACT |
| 123 | |
| 124 | This is a perl module for parsing diag lists. It uses |
| 125 | XML-like syntax to define regression arguments. |
| 126 | |
| 127 | =head1 DESCRIPTION |
| 128 | |
| 129 | This module exists to parse diaglists and return results in a usable |
| 130 | format. The Synopsis section above describes common usage. This is |
| 131 | an object module with no exported functions. The top-level object is |
| 132 | of type DiagList. Sub-objects are returned of type DiagList::Group |
| 133 | and DiagList::Diag. The public interface of each is described below. |
| 134 | |
| 135 | =head2 DiagList Object |
| 136 | |
| 137 | This is the only type of object the user will create explicitly. |
| 138 | |
| 139 | =over 4 |
| 140 | |
| 141 | =item new($file, [$fh]) E<lt>class methodE<gt> |
| 142 | |
| 143 | Parse the given diaglist file and return a new DiagList object. |
| 144 | Throws an exception if it cannot parse the file. If an optional |
| 145 | second argument is provided, it is treated as a file handle to read |
| 146 | from. It can be either an IO::File object or a bare file handle. In |
| 147 | this case the first argument, $file, is used purely for reporting |
| 148 | errors. |
| 149 | |
| 150 | =item build_list() |
| 151 | |
| 152 | Returns a list of the build tags that were seen in the file. |
| 153 | |
| 154 | =item build_args($build_tag) |
| 155 | |
| 156 | Returns the build arguments for the specified build tag. Returns |
| 157 | undef if a build tag called $build_tag was not seen in the file. The |
| 158 | build arguments are the ones specified in the group tag defintion. |
| 159 | The only processing done is that name=E<lt>...E<gt> is stripped out |
| 160 | completely and sys=E<lt>...E<gt> is replaced by -sys=E<lt>...E<gt>. |
| 161 | |
| 162 | =item build_hash() |
| 163 | |
| 164 | Returns a reference to a hash where the keys are build tags and the |
| 165 | values are the build args. Note that this is a reference into the |
| 166 | internal state of the object, so modifying this hash will modify the |
| 167 | DiagList object. |
| 168 | |
| 169 | =item group_list() |
| 170 | |
| 171 | Returns a list of group names that were seen in the file. |
| 172 | |
| 173 | =item find_group($groupname) |
| 174 | |
| 175 | Returns a DiagList::Group object for the specified $groupname. |
| 176 | Returns undef if no such $groupname was seen in the file. |
| 177 | |
| 178 | =item group_hash() |
| 179 | |
| 180 | Returns a reference to a hash where keys are group names and values |
| 181 | are DiagList::Group objects. Note that this is a reference into the |
| 182 | internal state of the object, so modifying the hash will modify the |
| 183 | DiagList object. |
| 184 | |
| 185 | =back |
| 186 | |
| 187 | =head2 DiagList::Group Object |
| 188 | |
| 189 | These objects are created by the DiagList object and can be returned |
| 190 | to the user via the DiagList methods find_group and group_hash (both |
| 191 | described above). The DiagList::Group objects support the following |
| 192 | methods. |
| 193 | |
| 194 | =over 4 |
| 195 | |
| 196 | =item name([$name]) |
| 197 | |
| 198 | Accessor function for the group name. If an argument $name is |
| 199 | provided, the name of the group is set to $name. The name of the |
| 200 | group is returned, whether or not it has changed. Changing the name |
| 201 | with this method is highly discouraged for user code, but it is |
| 202 | perfectly acceptable to call name() with no arugments to get the name. |
| 203 | |
| 204 | =item build_tags() |
| 205 | |
| 206 | Returns a list of build_tags that are applicable to this group. |
| 207 | |
| 208 | =item list_diags($buildtag) |
| 209 | |
| 210 | Returns a list of diag names in this group that correspond to the |
| 211 | given $buildtag. |
| 212 | |
| 213 | =item find_diag($buildtag, $diagname) |
| 214 | |
| 215 | Returns a DiagList::Diag object that corresponds the the given |
| 216 | $diagname and the provided $buildtag. Returns undef if no such |
| 217 | $buildtag or no such $diagname was found. |
| 218 | |
| 219 | =item diag_hash($buildtag) |
| 220 | |
| 221 | Returns a reference to a hash where the keys are diag names and the |
| 222 | values are DiagList::Diag objects. Note tha this is a reference into |
| 223 | the internal state of the object, so modifying the hash will modify |
| 224 | the object. |
| 225 | |
| 226 | =back |
| 227 | |
| 228 | =head2 DiagList::Diag Object |
| 229 | |
| 230 | DiagList::Diag objects represent the state associated with a diag. |
| 231 | They are returned by the DiagList::Group methods find_diag() and |
| 232 | diag_hash(). DiagList::Diag objects support the following methods. |
| 233 | |
| 234 | =over 4 |
| 235 | |
| 236 | =item get_alias() |
| 237 | |
| 238 | Returns the diag alias, as provided in the diaglist file. |
| 239 | |
| 240 | =item get_nametag() |
| 241 | |
| 242 | Returns the diag nametag, as provided in the diaglist file. |
| 243 | |
| 244 | =item get_name() |
| 245 | |
| 246 | Returns the diag name which is the diag alias with :E<lt>nametagE<gt> |
| 247 | appended. |
| 248 | |
| 249 | =item get_full_name() |
| 250 | |
| 251 | Returns the full diag name with alias, nametag, and group, separated |
| 252 | by ':'. |
| 253 | |
| 254 | =item get_file() |
| 255 | |
| 256 | Returns the first file mentioned in the diag line. |
| 257 | |
| 258 | =item get_owner() |
| 259 | |
| 260 | Get debug owner form diag list. |
| 261 | |
| 262 | =item get_cmdline() |
| 263 | |
| 264 | Returns the command-line for the diag. This includes arguments |
| 265 | specified in the DiagList::Group object that contains this object, |
| 266 | followed by arguments specified on the diag command line. If the |
| 267 | containing group happens to be a buildtag (i.e., has a |
| 268 | sys=E<lt>somethingE<gt>), the sys=E<lt>somethingE<gt> is stripped out |
| 269 | of the diag command-line. |
| 270 | |
| 271 | =item get_cmd_argv() |
| 272 | |
| 273 | This is the same as get_cmdline, except that it processes the |
| 274 | command-line with a shell and returns a list that can be treated as an |
| 275 | argv list. Using this instead of get_cmdline allows diaglist entries |
| 276 | to be written the same way they would be on the command-line. |
| 277 | |
| 278 | =back |
| 279 | |
| 280 | =head2 Syntax of the Diaglist file |
| 281 | |
| 282 | The syntax of the Diaglist file is somewhat strange. It makes the |
| 283 | most sense to describe how it evolved than to try to explain the |
| 284 | entire syntax all at once. |
| 285 | |
| 286 | =head3 Diag Lines |
| 287 | |
| 288 | A diag line is a line in the diaglist that specifies a diag. Its syntax is: |
| 289 | |
| 290 | <alias> <args> |
| 291 | |
| 292 | Where E<lt>aliasE<gt> is a name for the diag, and E<lt>argsE<gt> are |
| 293 | arguments to B<sims> used to run the diag. For instance: |
| 294 | |
| 295 | mydiag mydiag.s -max_cycle=300000 |
| 296 | |
| 297 | creates a diag alias "mydiag", which B<sims> will invoke as "mydiag.s |
| 298 | -max_cycle=300000". One argument is special, however. If an argument |
| 299 | is "debugowner=E<lt>usernameE<gt>", that argument is removed from the |
| 300 | command-line before it is passed to B<sims>. The debugowner is |
| 301 | available to clients of the DiagList module via the get_owner() |
| 302 | function, but it is not part of the command line because there is |
| 303 | nothing B<sims> to do with it at runtime. It is useful, however, for |
| 304 | informing the B<diagstatus> database of who owns which diags. |
| 305 | |
| 306 | =head3 Groups |
| 307 | |
| 308 | The main organizational structure in the diaglist is a group. A group |
| 309 | defines a list of diags for a regression and arguments to use for all |
| 310 | diags in that regression. The syntax for a group is an XML-like tag. |
| 311 | The definition can contain arguments. |
| 312 | |
| 313 | For example: |
| 314 | |
| 315 | <foo -foo1 -foo2> |
| 316 | |
| 317 | abc abc.s -abc |
| 318 | def def.s -def |
| 319 | |
| 320 | </foo> |
| 321 | |
| 322 | This defines regression group named "foo". The arguments for the |
| 323 | group are prepended to each diag command line. B<sims> uses |
| 324 | Getopt::Long to parse its arguments, so if conflicting options are |
| 325 | repeated on its command-line, the later option takes precedence. This |
| 326 | means that diag-line options override group options if they are in |
| 327 | conflict. If group foo were run in B<sims>, it would run a diag with |
| 328 | alias "abc" and arguments "-foo1 -foo2 abc.s -abc" and an alias "def" |
| 329 | with arguments "-foo1 -foo2 def.s -def". |
| 330 | |
| 331 | Groups can be opened multiple times, and they may have different |
| 332 | arguments each time. Arguments are only used in the diags contained |
| 333 | in that particular tag. For example: |
| 334 | |
| 335 | <foo -foo1 -foo2> |
| 336 | |
| 337 | abc abc.s -abc |
| 338 | def def.s -def |
| 339 | |
| 340 | </foo> |
| 341 | |
| 342 | <foo -foo3> |
| 343 | |
| 344 | ghi ghi.s -ghi |
| 345 | |
| 346 | </foo> |
| 347 | |
| 348 | This would run "abc" and "def" exactly the same as before. The diag |
| 349 | "ghi" would be run with "-foo3 ghi.s -ghi" and would not include |
| 350 | "-foo1 or -foo2". |
| 351 | |
| 352 | Group definitions may nest, but this does B<not> imply any |
| 353 | relationship between the groups. |
| 354 | |
| 355 | <foo -foo1> |
| 356 | <bar -bar1> |
| 357 | |
| 358 | abc abc.s -abc |
| 359 | |
| 360 | </bar> |
| 361 | </foo> |
| 362 | |
| 363 | This defines two different regressions, "foo" and "bar". In |
| 364 | regression "foo", "abc" will have arguments "-foo1 abc.s -abc". In |
| 365 | regression "bar", it will have arguments "-bar1 abc.s -abc". There is |
| 366 | no notion of group "foo" containing group "bar" or anything like that. |
| 367 | They just happen to have some diag lines in common. |
| 368 | |
| 369 | Note that this means that a diag alias by itself does not define a |
| 370 | unique test (diag plus arguments). The alias/group combination is |
| 371 | necessary, but not sufficient, to make a diag unique. More on that |
| 372 | later. |
| 373 | |
| 374 | |
| 375 | =head3 Nesting tags |
| 376 | |
| 377 | One special tag, E<lt>runargsE<gt> specifies arguments to all enclosed |
| 378 | diags, regardless of their group. |
| 379 | |
| 380 | <runargs -runrun> |
| 381 | <foo -foo1> |
| 382 | <bar -bar1> |
| 383 | |
| 384 | abc abc.s -abc |
| 385 | |
| 386 | </bar> |
| 387 | </foo> |
| 388 | </runargs> |
| 389 | |
| 390 | This means that in group "foo", the diag "abc" will run as "-runrun |
| 391 | -foo1 abc.s -abc" and in group "bar", it will be "-runrun -bar1 abc.s |
| 392 | -abc". |
| 393 | |
| 394 | You can nest E<lt>runargsE<gt> tags. Inner tags will append to the |
| 395 | argument list so inner E<lt>runargsE<gt> will override outer tags if |
| 396 | any arguments are in conflict. Please note that a E<lt>runargsE<gt> |
| 397 | tag does B<not> define a regression, so there is no group called |
| 398 | "runargs". |
| 399 | |
| 400 | Another special tag that applies to all enclosed diags, regardless of |
| 401 | their group, is E<lt>debugownerE<gt>. Just as described for the diag |
| 402 | line, E<lt>debugownerE<gt> does not affect the command line at all, |
| 403 | but it does provide information to the B<diagstatus> database about |
| 404 | who owns which diags. |
| 405 | |
| 406 | <debugowner someuser> |
| 407 | |
| 408 | ... |
| 409 | |
| 410 | </debugowner> |
| 411 | |
| 412 | This is the same as having "debugowner=someuser" on every diag line in |
| 413 | its scope. Note that if a diag line contains a "debugowner=..." and |
| 414 | it is inside a E<lt>debugownerE<gt> tag, the diag line will take |
| 415 | precedence. |
| 416 | |
| 417 | =head3 Special Groups |
| 418 | |
| 419 | There are two types of special groups, buildtags and nametags. They |
| 420 | are syntacticaly just like any other groups, and they define |
| 421 | regressions just like any other groups. They have special meanings |
| 422 | and restrictions, however. |
| 423 | |
| 424 | =head4 Build Tags |
| 425 | |
| 426 | A buildtag is any group that has "sys=E<lt>sysnameE<gt>" in its |
| 427 | argument list. (Note that all B<sims> options begin with '-', so any |
| 428 | argument of the form "E<lt>nameE<gt>=E<lt>valueE<gt>" is an argument |
| 429 | to the diaglist parser). |
| 430 | |
| 431 | A buildtag defines the model that should be built for the regression |
| 432 | and the B<sims> options of how to build the model. |
| 433 | |
| 434 | <build1 sys=cmp -arg1 -arg2> |
| 435 | |
| 436 | ... |
| 437 | |
| 438 | </build1> |
| 439 | |
| 440 | This creates a buildtag called "build1" that specifies that all diags |
| 441 | inside it should be run with the B<sims> "cmp" model, which can be |
| 442 | built with "-arg1 -arg2". |
| 443 | |
| 444 | Unlike other groups, buildtags do B<not> nest. Each diag line must |
| 445 | appear in B<exactly one> build tag. All diaglines in all groups |
| 446 | inside the scope of the buildtag will be run on the specified model. |
| 447 | |
| 448 | <build1 sys=cmp -arg1 -arg2> |
| 449 | <foo -foo1> |
| 450 | <bar -bar1> |
| 451 | mydiag mydiag.s -diag1 |
| 452 | </bar> |
| 453 | </foo> |
| 454 | </build1> |
| 455 | |
| 456 | When you run regression "foo", it will build a cmp model with args |
| 457 | "-arg1 -arg2". It will then run "mydiag" with arguments "-foo1 |
| 458 | mydiag.s -diag1". Similarly, if you ran regression "bar", it would |
| 459 | build the same cmp model and run "mydiag" with "-bar1 mydiag.s |
| 460 | -diag1". Note that "-arg1" and "-arg2" are used at build time for |
| 461 | groups "foo" and "bar", but they do not appear on the diag |
| 462 | command-line during the run. |
| 463 | |
| 464 | A build tag also defines a regression, so you could run a regression |
| 465 | "build1" with the above diaglist. It would build with "-arg1 -arg2" |
| 466 | and would run "mydiag" with "-arg1 -arg2 mydiag.s -diag1". There is |
| 467 | no way for the diaglist parser to tell build-time arguments from |
| 468 | run-time arguments when a buildtag is used as a regression group. |
| 469 | Fortunately, B<sims> will ignore run-time options at build time and |
| 470 | vice-versa, so using buildtags as groups is perfectly legal. |
| 471 | |
| 472 | |
| 473 | =head4 Name Tags |
| 474 | |
| 475 | An ambiguity is possible with multiple groups that contain diags with the same alias. For example: |
| 476 | |
| 477 | <both> |
| 478 | |
| 479 | <foo> |
| 480 | <runargs -foo1> |
| 481 | mydiag mydiag.s |
| 482 | </runargs> |
| 483 | </foo> |
| 484 | |
| 485 | |
| 486 | <bar> |
| 487 | <runargs -bar1> |
| 488 | mydiag mydiag.s |
| 489 | </runargs> |
| 490 | </bar> |
| 491 | |
| 492 | </both> |
| 493 | |
| 494 | Note that we use E<lt>runargsE<gt> tags instead of putting them in the |
| 495 | "foo" and "bar" regressions directly, since we want the "both" group |
| 496 | to run "mydiag" once with "-foo1" and again with "-bar1". The problem |
| 497 | with the above diaglist is that both runs of "mydiag" have the same |
| 498 | alias/group combination when run in group "both". Some other |
| 499 | identifier is needed to give each diag a unique name. |
| 500 | |
| 501 | Nametags are used for this purpose. A nametag is a group that has |
| 502 | "name=E<lt>nameE<gt>" in its argument list. The name is appended to |
| 503 | the alias do define a name that is unique within a group. The |
| 504 | alias/nametag/group combination is enough to make a diag unique |
| 505 | overall. As with buildtags, nametags do not nest, and each diag must |
| 506 | appear in B<exactly one> nametag. We can rewrite the above diaglist |
| 507 | as: |
| 508 | |
| 509 | |
| 510 | <both> |
| 511 | |
| 512 | <foo_group name=foo> |
| 513 | <runargs -foo1> |
| 514 | mydiag mydiag.s |
| 515 | </runargs> |
| 516 | </foo> |
| 517 | |
| 518 | |
| 519 | <bar_group name=bar> |
| 520 | <runargs -bar1> |
| 521 | mydiag mydiag.s |
| 522 | </runargs> |
| 523 | </bar> |
| 524 | |
| 525 | </both> |
| 526 | |
| 527 | Group "foo_group" contains the diag "mydiag:foo" with args "-foo1 |
| 528 | mydiag.s". Group "bar_group" contains the diag "mydiag:bar" with args |
| 529 | "-bar1 mydiag.s". Group "both" contains two diags: "mydiag:foo" with |
| 530 | "-foo1 mydiag.s" and "mydiag:bar" with args "-bar1 mydiag.s". |
| 531 | |
| 532 | When B<sims> creates a directory to run a directory, it uses |
| 533 | E<lt>aliasE<gt>:E<lt>nametagE<gt>:E<lt>groupE<gt> to get a unique |
| 534 | directory name. In contexts where only a single group is relevant, |
| 535 | then E<lt>aliasE<gt>:E<lt>nametagE<gt> is sufficent to name a diag. |
| 536 | |
| 537 | |
| 538 | |
| 539 | |
| 540 | |
| 541 | |
| 542 | =head1 SEE ALSO |
| 543 | |
| 544 | sims(1). |