#!/usr/bin/perl
#!/usr/bin/perl
#############################################################################
# Time-stamp: <Wed Nov 22 2000 02:58:05 Stardate: [-30]5765.61 hwloidl>
#
# Usage: grs2gr [options] <gr-file1> <gr-file2> ...
#
# Convert several .gr files (from the same GUM run) into a single
# .gr file with all times adjusted relative to the earliest start
# time. A typical use of this script after running a prg foo_mp is
#   grs2gr =*foo*.gr > foo_mp.gr
# Note that GUM generates 1 .gr file for every PE with the name 
#   =absolute=path=name=foo_mp.<pe>.gr
# 
# The current version of GUM (up to 2.10) sometimes add spurious events
# with an attached thread id of ffffffff. These are automatically filtered
# out and a warning about the number of ignored events is printed.
# We really should track down the source of these events at some point!
#
# Just figured out the reason for the FETCH ffffffff events: if a fetch
# message is forwarded to another PE (upon finding a BLOCKED_FETCH in a 
# BQ of an RBH closure) a FETCH event is printed although the forwarding
# should be transparent in the .gr file (we do not record arrival of FETCHes,
# but only sending of FETCHes). Fixed in the new RTS.
#
# Options:
#
#############################################################################

$ff = 0;
$count = 1;
$| = 1;

foreach $i (@ARGV) {
    open(GR, $i) || die "Can't read $i\n";
    $cmd = <GR>;
    $dateline = <GR>;
    $start = <GR>;
    ($pe, $timestamp) = ($start =~ /PE\s+(\d+) \[(\d+)\]/);
    die "PE $pe too high\n" if $pe > $#ARGV+1;
    $proc[$count++] = $pe;
    $prog[$pe] = $cmd;
    $time[$pe] = $timestamp;
    close(GR);
}

$basetime = 0;

# GUM 4.xx: Now counting from 1
for($i = 1; $i < $count; $i++) {
    $pe = $proc[$i];
    die "PE $pe missing? ($i,$proc[$i])\n" if !defined($time[$pe]);
    die "Mismatched .gr files ($pe,$prog[$pe])\n" if $pe > 1 && $prog[$pe] ne $prog[$pe - 1];
    $basetime = $time[$pe] if $basetime == 0 || $basetime > $time[$pe];
}

print $cmd;
print $dateline;

for($i = 1; $i < $count; $i++) {
    $pe = $proc[$i];
    $delta = $time[$pe] - $basetime;
    open(GR, $ARGV[$i-1]) || die "Can't read $i-1 |$ARGV[i-1]|\n";
    $cmd = <GR>;
    $dateline = <GR>;
    $start = <GR>;
    while(<GR>) {
        # in the new RTS this shouldn't be necessary any more
        #$ff++, next if /ffffffff/; # BUG: GUM produces spurious REPLY  ffffffff's
        /PE\s+(\d+) \[(\d+)\]/;
	printf "PE %2u [%lu]%s", $1, $2 + $delta, $';
    }
    close(GR);
}

print STDERR "Warning: $ff events with a thread id ffffffff ignored\n" if $ff>0;
