Merge with head.
[gem5.git] / util / rundiff
index 4aed9200ee3e3a253f5f06d6fe4ab25be1a9d6b2..c34bb53a3fc1e9171b16bfae5630ff5549c321d4 100755 (executable)
@@ -25,6 +25,9 @@
 # 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: Nathan Binkert
+#          Steve Reinhardt
 
 # Diff two streams.
 #
 # "filename" is a pipe (|).  Thus to compare the instruction traces
 # from two versions of m5 (m5a and m5b), you can do this:
 #
-# rundiff 'm5a --trace:flags=InstExec |' 'm5b --trace:flags=InstExec |'
+# rundiff 'm5a --traceflags=InstExec |' 'm5b --traceflags=InstExec |'
 #
 
 use strict;
 
+use Getopt::Std;
+
+#
+# Options:
+#  -c <n> : print n lines of context before & after changes
+#  -l <n> : use n lines of lookahead
+#  -x     : use "complex" diff from Algorithm::Diff (see below)
+#
+our ($opt_c, $opt_l, $opt_x);
+getopts('c:l:x');
+
 #
 # For the highest-quality (minimal) diffs, we can use the
-# Algorithm::Diff package.  If you don't have this installed, or want
-# the script to run faster (like 3-4x faster, based on informal
-# observation), set $use_complexdiff to 0; then a built-in, simple,
-# and generally quite adequate algorithm will be used instead.
-my $use_complexdiff = 0;
+# Algorithm::Diff package.  By default, a built-in, simple, and
+# generally quite adequate algorithm will be used.  If you have
+# Algorithm::Diff installed on your system, and don't mind having the
+# script go slower (like 3-4x slower, based on informal observation),
+# then specify '-x' on the command line to use it.
+my $use_complexdiff = defined($opt_x);
 
 if ($use_complexdiff) {
-    use Algorithm::Diff qw(traverse_sequences);
+    # Don't use 'use', as that's a compile-time option and will fail
+    # on systems that don't have Algorithm::Diff installed even if
+    # $use_complexdiff is false.  'require' is evaluated at runtime,
+    # so it's OK.
+    require Algorithm::Diff;
+    import Algorithm::Diff qw(traverse_sequences);
 };
 
-my $lookahead_lines = 200;
-my $precontext_lines = 3;
-my $postcontext_lines = 3;
+my $lookahead_lines = $opt_l || 200;
+
+# in theory you could have different amounts of context before and
+# after a diff, but until someone needs that there's only one arg to
+# set both.
+my $precontext_lines = $opt_c || 3;
+my $postcontext_lines = $precontext_lines;
 
 my $file1 = $ARGV[0];
 my $file2 = $ARGV[1];
@@ -66,6 +90,10 @@ my ($fh1, $fh2);
 open($fh1, $file1) or die "Can't open $file1";
 open($fh2, $file2) or die "Can't open $file2";
 
+# print files to output so we know which is which
+print "-$file1\n";
+print "+$file2\n";
+
 # buffer of matching lines for pre-diff context
 my @precontext = ();
 # number of post-diff matching lines remaining to print
@@ -170,7 +198,10 @@ sub printdiff
                              DISCARD_A => \&discard1,
                              DISCARD_B => \&discard2 });
 
-       die "Lost sync!" if (!$match_found);
+       if (!$match_found) {
+           printdiff(scalar(@lines1), scalar(@lines2));
+           die "Lost sync!";
+       }
 
        # Since we shouldn't get here unless the first lines of the
        # buffers are different, then we must discard some lines off
@@ -199,7 +230,10 @@ sub checkmatch
     # treated as common; if that bugs you, use Algorithm::Diff.
     if ($lines1[$n1] eq $lines2[$n2] && $lines1[$n1+1] eq $lines2[$n2+1]) {
        printdiff($n1, $n2);
+       return 1;
     }
+
+    return 0;
 }
 
 sub simple_diff
@@ -219,6 +253,8 @@ sub simple_diff
            return if checkmatch($cnt, $n);
        }
     }
+
+    printdiff(scalar(@lines1), scalar(@lines2));
     die "Lost sync!";
 }