util: Add a README file for the m5 utility.
[gem5.git] / util / rundiff
index 732b84d210ef837a66311e0908fe2059ec481730..b988d5db2b95fdac494634ef432e5b3464877f10 100755 (executable)
 # "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 FileHandle;
+use Getopt::Std;
 
 #
-# 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;
-
-#if ($use_complexdiff) {
-#    use Algorithm::Diff qw(traverse_sequences);
-#};
+# 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');
 
-my $lookahead_lines = 200;
-my $precontext_lines = 3;
-my $postcontext_lines = 3;
+#
+# For the highest-quality (minimal) diffs, we can use the
+# 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) {
+    # 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 = $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 +87,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
@@ -137,6 +162,12 @@ sub printdiff
 
     # Set $postcontext to print the next $postcontext_lines matching lines.
     $postcontext = $postcontext_lines;
+
+    # Normally we flush after the postcontext lines are printed, but if
+    # the user has decreed that there aren't any we need to flush now
+    if ($postcontext == 0) {
+        STDOUT->flush();
+    }
 }
 
 
@@ -170,7 +201,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 +233,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 +256,8 @@ sub simple_diff
            return if checkmatch($cnt, $n);
        }
     }
+
+    printdiff(scalar(@lines1), scalar(@lines2));
     die "Lost sync!";
 }
 
@@ -253,10 +292,12 @@ while (1) {
        # figure out what to do with this line
        if ($postcontext > 0) {
            # we're in the post-context of a diff: print it
-           $postcontext--;
            print ' ', $l1;
            $lineno1++;
            $lineno2++;
+            if (--$postcontext == 0) {
+                STDOUT->flush();
+            }
        }
        else {
            # we're in the middle of a matching region... save this