#!/usr/bin/perl -w
%mirrored = ();
$ln = 0;
$kern = "";
while(<>){
	$str = $_;
	$ln++;

	if($str =~ /pgi_uacc_mirror_alloc\(size=.*,elemsize=.*,hosthandle=(.*),lineno=.*,name=(.*)\)/){
		print "[$ln] Found $2 (host_addr = $1)\n";
		($d, $n, $h) = (0, $2, $1);
		@arr = ($n, $d);
		push(@{$mirrored{$h}}, [@arr]);
		next;
	}
	if($str =~ /map    dev:(.*) host:(.*) size:.* offset:.*  data\[.*\] \(line:.* name:(.*)\)/) {
		($d, $h, $n) = ($1, $2, $3);
		foreach $haddr (keys %mirrored){
			if($haddr =~ /^$h$/) {
		 		print "[$ln] > $n: map host_addr $h to dev_addr $d\n"; 
				print "[$ln] > new name: $n. Origin: $mirrored{$h}[0][0] \n" if($mirrored{$h}[0][0] !~ /^$n$/);
				$mirrored{$h}[1] = $d;
			}
		}
		next;

	}
	if($str =~ /pgi_uacc_cuda_dataup1\(devdst=(.*),hostsrc=(.*),offset=.*,stride=.*,size=.*,eltsize=.*,lineno=(.*),name=(.*),thread=.*\)/){
		($d, $h, $l, $n) = ($1, $2, $3, $4);
		foreach $haddr (keys %mirrored){
			if($haddr =~ /^$h$/){
				print "[$ln] >> upload $n to device ($h -> $d).";
				print "Origin name: $mirrored{$h}[0][0]" if($mirrored{$h}[0][0] !~ /^$n$/);
				print "\n";
				last;
			}
		}
		next;
	}
	if($str =~ /pgi_uacc_cuda_datadown1\(devdst=(.*),hostsrc=(.*),offset=.*,stride=.*,size=.*,eltsize=.*,lineno=(.*),name=(.*),async=.*/ ||
	   $str =~ /pgi_uacc_datadown\(devptr=(.*),hostptr=(.*),poffset=.*,offset=.*,stride=.*,size=.*,extent=.*,eltsize=.*,lineno=(.*),name=(.*),flags=(.*),threadid=.*\)/){
		($d, $h, $l, $n) = ($1, $2, $3, $4);
		$ch = "";
		$ch = " Checking for" if($d =~ /^0x0$/ || $l < 0);
		foreach $haddr (keys %mirrored){
			if($haddr =~ /^$h$/){
				print "[$ln] >>$ch download '$n' to host ($d -> $h). ";
				print "Origin name: $mirrored{$h}[0][0]" if($mirrored{$h}[0][0] !~ /^$n$/);
				print "\n";
				last;
			}
		}
		next;
	}
	if($str =~ /pgi_uacc_begin\( file=(.*), function=(.*), lines=.*, startline=(.*), endline=(.*), devid=.*, threadid=.* \)/) {
		print "[$ln] === $1 == $2 ($3:$4)\n";
	}
	if($str =~ /pgi_uacc_begin\( data region, file=(.*), function=(.*), lines=.*, startline=(.*), endline=(.*), devid=.*, threadid=.* \)/) {
		print "[$ln] === data_reg:  $1 == $2 ($3:$4)\n";
	}
	if($str =~ /pgi_uacc_cuda_wait done/){
#		print "[$ln] ===========================\n";
	}
	if($str =~ /pgi_uacc_dataon\(devptr=(.*),hostptr=(.*),poffset=.*,offset=.*,stride=.*,size=.*,extent=.*,eltsize=.*,lineno=(.*),name=(.*),flags=(.*)/){
		($d, $h, $l, $n, $f) = ($1, $2, $3, $4, $5);
		 $f =~ s/,.*//;
		 foreach $haddr (keys %mirrored){
		 	if($haddr =~ /^$h$/){
				print "[$ln] >> Check for '$n' to device ($h -> $d). ";
				print "Origin name: $mirrored{$h}[0][0]" if($mirrored{$h}[0][0] !~ /^$n$/);
				print "\n";
				if($f =~ /copyout/) {print "!! WARNING: copyout for mirror variable. lineno=$l\n";}
				if($f =~ /copyin/) {print "!! WARNING: copyin for mirror variable. lineno=$l\n";}
				if($f =~ /create/) {print "!! WARNING: create for mirror variable. lineno=$l\n";}
				last;
		 	}
		 }
		 next;
	}
	if($str =~ /pgi_uacc_dataup\(devptr=(.*),hostptr=(.*),poffset=.*,offset=.*,stride=.*,size=.*,extent=.*,eltsize=.*,lineno=(.*),name=(.*),flags=(.*),threadid=.*\)/){
		($d, $h, $l, $n, $f) = ($1, $2, $3, $4, $5);
		 foreach $haddr (keys %mirrored){
		 	if($haddr =~ /^$h$/){
				print "[$ln] >> Check for '$n' to device ($h -> $d). ";
				print "Origin name: $mirrored{$h}[0][0]" if($mirrored{$h}[0][0] !~ /^$n$/);
				print "\n";
				if($l>0 && $f =~ /copyout/) {print "!! WARNING: copyout for mirror variable. lineno=$l\n";}
				if($l>0 && $f =~ /copyin/) {print "!! WARNING: copyin for mirror variable. lineno=$l\n";}
				if($l>0 && $f =~ /create/) {print "!! WARNING: create for mirror variable. lineno=$l\n";}
				last;
		 	}
		 }
		 next;
	}
	if($str =~ /pgi_uacc_dataoff\(devptr=(.*),hostptr=(.*),poffset=.*,offset=.*,stride=.*,size=.*,extent=.*,eltsize=.*,lineno=(.*),name=(.*),flags=(.*)/){
		($d, $h, $l, $n, $f) = ($1, $2, $3, $4, $5);
		 $f =~ s/,.*//;
		 foreach $haddr (keys %mirrored){
		 	if($haddr =~ /^$h$/){
				print "[$ln] >> Check for '$n' to host ($h -> $d). ";
				print "Origin name: $mirrored{$h}[0][0]" if($mirrored{$h}[0][0] !~ /^$n$/);
				print "\n";
				if($f =~ /copyout/) {print "!! WARNING: copyout for mirror variable. lineno=$l\n";}
				if($f =~ /copyin/) {print "!! WARNING: copyin for mirror variable. lineno=$l\n";}
				if($f =~ /create/) {print "!! WARNING: create for mirror variable. lineno=$l\n";}
				last;
		 	}
		 }
		 next;
	}
	if($str =~ /mapped host:.* dev:.* offset:.* \(host:(.*) dev:(.*) size:.* offset:.* data\[.*\] line:.* name:(.*)\)/) {
		($h, $d, $n) = ($1, $2, $3);
		foreach $haddr (keys %mirrored){
			if($haddr =~ /^$h$/){
				print "[$ln] >> mapping found:  $h -> $d for $n";
				print "!!!!  $mirrored{$h}[0][0] $mirrored{$h}[0][1]" if($mirrored{$h}[0][0] !~ /^$n$/);
				print "\n";
				last;
			}
		}
		next;
	}
	if($str =~ /Arguments to function [0-9]+ ([^ ]+)/){
		print "[$ln] >>>>>>> Kernel $1\n";
	}
	if($str =~ /host:(0x[0-9a-f]\+)/ || $str =~ /hostptr=(0x[0-9a-f]\+)/) {
		$h = $1;
		foreach $haddr (keys %mirrored){
			if($haddr =~ /^$h$/){
				 print "[$ln] !! mapping found:  $h for $n";
				 print "      >> $str";
				 last;
			}
		}
		next;
	}
	if($str =~ /Function .* = .* = (.*)/){ $kern = $1; next;}
	if($str =~ / 1x1x1 = block size/){
		print "!!! WARNING: kernel $kern launched with thread block 1x1x1\n"

	}
}

