| #! /usr/bin/env perl | |
| # Copyright (c) 2003-2007 The Regents of The University of Michigan | |
| # All rights reserved. | |
| # | |
| # Redistribution and use in source and binary forms, with or without | |
| # modification, are permitted provided that the following conditions are | |
| # met: redistributions of source code must retain the above copyright | |
| # notice, this list of conditions and the following disclaimer; | |
| # redistributions in binary form must reproduce the above copyright | |
| # notice, this list of conditions and the following disclaimer in the | |
| # documentation and/or other materials provided with the distribution; | |
| # neither the name of the copyright holders nor the names of its | |
| # contributors may be used to endorse or promote products derived from | |
| # this software without specific prior written permission. | |
| # | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| # | |
| # Authors: Steve Reinhardt | |
| # Script to simplify using rundiff on trace outputs from two | |
| # invocations of m5. Takes a common m5 command line with embedded | |
| # alternatives and executes the two alternative commands in separate | |
| # subdirectories with output piped to rundiff. | |
| # | |
| # ******Note that you need to enable some trace flags in the args in order | |
| # to do anything useful!****** | |
| # | |
| # Script arguments are handled uniformly as follows: | |
| # - If the argument does not contain a '|' character, it is appended | |
| # to both command lines. | |
| # - If the argument has a '|' character in it, the text on either side | |
| # of the '|' is appended to the respective command lines. Note that | |
| # you'll have to quote the arg or escape the '|' with a backslash | |
| # so that the shell doesn't think you're doing a pipe. | |
| # - Arguments with '#' characters are split at those characters, | |
| # processed for alternatives ('|'s) as independent terms, then | |
| # pasted back into a single argument (without the '#'s). (Sort of | |
| # inspired by the C preprocessor '##' token pasting operator.) | |
| # | |
| # In other words, the arguments should look like the command line you | |
| # want to run, with "|" used to list the alternatives for the parts | |
| # that you want to differ between the two runs. | |
| # | |
| # For example: | |
| # | |
| # % tracediff m5.opt --opt1 '--opt2|--opt3' --opt4 | |
| # would compare these two runs: | |
| # m5.opt --opt1 --opt2 --opt4 | |
| # m5.opt --opt1 --opt3 --opt4 | |
| # | |
| # % tracediff 'path1|path2#/m5.opt' --opt1 --opt2 | |
| # would compare these two runs: | |
| # path1/m5.opt --opt1 --opt2 | |
| # path2/m5.opt --opt1 --opt2 | |
| # | |
| # If you want to add arguments to one run only, just put a '|' in with | |
| # text only on one side ('--onlyOn1|'). You can do this with multiple | |
| # arguments together too ('|-a -b -c' adds three args to the second | |
| # run only). | |
| # | |
| # The '-n' argument to tracediff allows you to preview the two | |
| # generated command lines without running them. | |
| # | |
| use FindBin; | |
| $dryrun = 0; | |
| if (@ARGV >= 1 && $ARGV[0] eq '-n') { | |
| $dryrun = 1; | |
| shift @ARGV; | |
| } | |
| if (@ARGV < 1) { | |
| die "Usage: tracediff [-n] \"sim1|sim2\" [common-arg \"arg1|arg2\" ...]\n"; | |
| } | |
| foreach $arg (@ARGV) { | |
| $a1 = $a2 = ''; | |
| @subargs = split('#', $arg); | |
| foreach $subarg (@subargs) { | |
| if ($subarg eq '') { | |
| next; | |
| } | |
| @pair = split('\|', $subarg, -1); # -1 enables null trailing fields | |
| if (@pair == 1) { | |
| $a1 .= $subarg; | |
| $a2 .= $subarg; | |
| } elsif (@pair == 2) { | |
| $a1 .= $pair[0]; | |
| $a2 .= $pair[1]; | |
| } else { | |
| print 'Parse error: too many |s in ', $arg, "\n"; | |
| exit(1); | |
| } | |
| } | |
| push @cmd1, $a1; | |
| push @cmd2, $a2; | |
| } | |
| if ($dryrun) { | |
| print "CMD1: ", join(' ', @cmd1), "\n"; | |
| print "CMD2: ", join(' ', @cmd2), "\n"; | |
| exit(0); | |
| } | |
| # First two args are the two simulator binaries to compare | |
| $sim1 = shift @cmd1; | |
| $sim2 = shift @cmd2; | |
| # Everything else is a simulator arg. | |
| $args1 = join(' ', @cmd1); | |
| $args2 = join(' ', @cmd2); | |
| # Common mistake: if you don't set any debugflags this often isn't | |
| # doing what you want. | |
| if ($args1 !~ /--debug-flags/) { | |
| print "****\n"; | |
| print "**** WARNING: no debug flags set... you may not be diffing much!\n"; | |
| print "****\n"; | |
| } | |
| # Run individual invocations in separate dirs so output and intermediate | |
| # files (particularly config.py and config.ini) don't conflict. | |
| $dir1 = "tracediff-$$-1"; | |
| $dir2 = "tracediff-$$-2"; | |
| mkdir($dir1) or die "Can't create dir $dir1\n"; | |
| mkdir($dir2) or die "Can't create dir $dir2\n"; | |
| $cmd1 = "$sim1 -d $dir1 $args1 2>&1 |"; | |
| $cmd2 = "$sim2 -d $dir2 $args2 2>&1 |"; | |
| # Expect that rundiff is in the same dir as the tracediff script. | |
| # FindBin figures that out for us. | |
| $fullcmd = "$FindBin::Bin/rundiff '$cmd1' '$cmd2' 2>&1 > tracediff-$$.out"; | |
| print "Executing $fullcmd\n"; | |
| system($fullcmd); | |