#!/usr/imports/bin/perl

# File    : xcc.test.pl
# Author  : Dorit Naishlos 
# Desc    : Compile XMT-C source code

if(scalar(@ARGV) < 1  or scalar(@ARGV) > 4){
  die "\nUsage: xcc <fileprefix> [-cluster <clustering-factor>]\n\n";
}

$DEFAULT_CLUSTER_SIZE = 32;


$clustering_factor = 0;

if(scalar(@ARGV) > 1){
  $cluster_flag = $ARGV[1];
  if($cluster_flag == "-cluster")
    {
      if(scalar(@ARGV) > 2){
	$clustering_factor = $ARGV[2];
	if($clustering_factor <= 0){
	  die "\nUsage: xcc.test.pl <fileprefix> [-cluster <clustering-factor: positive integer>]\n\n";
	}
      }
      else{
	$clustering_factor = $DEFAULT_CLUSTER_SIZE;
      }
    }
  else {
    die "\nUsage: xcc.test.pl <fileprefix> [-cluster <clustering-factor>]\n\n";
  }
}
  
$keep = 0;
$filePrefix = $ARGV[0];

$xmtDir = $ENV{"XMTDIR"};
$SUIF_DIR  = "$xmtDir/suif/";
$XCC_DIR = "$xmtDir/xcc";

print "\n\n --> pscc -I$XCC_DIR/include -parallel -v -.snt $filePrefix.c\n";
system ("$SUIF_DIR/bin/pscc -I$XCC_DIR/include -parallel -v -.snt $filePrefix.c");
#system ("pscc -I$XCC_DIR/include -parallel -v -.snt $filePrefix.c");
#system ("pscc -I$XCC_DIR/include -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/ssbig-na-sstrix/include -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/glibc-1.09 -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/glibc-1.09/sysdeps/generic -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/glibc-1.09/string -parallel -v -.snt $filePrefix.c");

print "\n\n --> porky -unused-syms -unused-types $filePrefix.snt $filePrefix.fp1";
system ("$SUIF_DIR/bin/porky -unused-syms -unused-types $filePrefix.snt $filePrefix.fp1");
#system ("porky -unused-syms -unused-types $filePrefix.snt $filePrefix.fp1");

print "\n\n --> xpass $filePrefix.fp1 $filePrefix.xpass\n";
if($clustering_factor == 0){
  system ("$XCC_DIR/bin/xpass.test $filePrefix.fp1 $filePrefix.xpass\n");
  #system ("xpass.test $filePrefix.fp1 $filePrefix.xpass \n");
  print "\n\n --> s2c $filePrefix.xpass $filePrefix.xpass.c";
}
else{
  system ("$XCC_DIR/bin/xpass.test $filePrefix.fp1 $filePrefix.xpass -cluster $clustering_factor\n");
  #system ("xpass.test $filePrefix.fp1 $filePrefix.xpass -cluster $clustering_factor\n");
  print "\n\n --> s2c $filePrefix.xpass $filePrefix.xpass.c -cluster $clustering_factor";
}


system ("$SUIF_DIR/bin/s2c $filePrefix.xpass $filePrefix.xpass.c"); 
#system ("s2c $filePrefix.xpass $filePrefix.xpass.c");

open(IN, $filePrefix . '.xpass.c' ) or
  die "\nCannot open input file $ARGV[0].xpass.c\n\n";
open(OUT, '>' . $filePrefix . '.gcc_in.c') or
    die "\nCannot open output file $ARGV[0].gcc_in.c\n\n";

print OUT "#include \"xmt_templates\.h\"\n";
print OUT "register int TCUID asm (\"\$16\");\nregister int TCUS asm (\"\$17\");\n";

$ignore = 0;

# do some some cleanups
while(<IN>){
  if( /\bextern void spawn\(/ or
      /\bextern void fspawn\(/ or
#      /\bextern void join\(/ or
      /\bextern int ps\(/ or
      /\bextern void spawn_setup\(/ or
      /\bextern void spawn_light_setup\(/ or
      /\bextern void fspawn_setup\(/ or
      /\bextern void fspawn_light_setup\(/ or
      /\bextern int spawn_init\(/ or
      /\bextern int spawn_light_init\(/ or
      /\bextern int fspawn_init\(/ or
      /\bextern int fspawn_light_init\(/ or
      /\bextern int spawn_cluster_init\(/ or
      /\bextern int spawn_light_cluster_init\(/ or
      /\bextern int get_num_threads\(/ or
      /\bextern char \*get_exposed_vars_struct_address\(/ or
      /\bextern void set_stack_pointer\(/ or
      /\bextern int get_new_TID\(/ or
      /\bextern void spin_TCU\(/ or
      /\bextern void fspin_TCU\(/ or
      /\bextern void halt_TCU\(/ or
      /\bextern int get_TCUID\(/ or
      /\bextern int get_num_completed\(/ or
      /\bextern int get_max_tid\(/ or
      /\bextern int get_max_tid_spawned\(/ or
      /\bextern void thread_start_label\(/ or
      /\bextern void print_thread_start\(/ or
      /\bextern void print_fork_spin_start\(/ or
      /\bextern void print_fork_spin_end\(/ or
      /\bextern void print_init_end\(/ or
      /\bextern void \print\(/ or
      /\bextern void wait_for_value\(/ or
      /\bextern void wait_for_address\(/ or
      /\bextern void begin\(/ or
      /\bextern void stop\(/ or
      /\bextern void refresh\(/ or
      /\bextern void stop_tcus_execution\(/ or
      /\bextern void suspend_till_valid_tid\(/ or
      /\bextern int last_tid\(/ or
      /\bextern int get_number_of_tcus\(/ or
      /\bextern int xfork\(/ or
      /\bextern int xfork_and_init\(/ or
      /\bextern void xexit\(/ or
      /\bextern void xbarrier_init\(/ or
      /\bextern void xbarrier\(/ or
      /\bextern void xlock_init\(/ or
      /\bextern void xlock\(/ or
      /\bextern void xunlock\(/ or
      /\bextern void _xmt_lock_init\(/ or
      /\bextern void _xmt_lock\(/ or
      /\bextern void _xmt_unlock\(/ or
      /\bextern void init_threads_data\(/ or
      /\bextern void dummy\(\);/)
    {
      next;
    }
  elsif(/\bextern void join\(/)
    {
#      $_ = "register int TCUID asm (\"\$16\");\nregister int TCUS asm (\"\$17\");\n";
      next;
    }
  elsif(/\bextern void dummy()/)
    {
      $ignore = 38;
      next;
    }
  elsif( $ignore  > 0)
    {
      $ignore = $ignore - 1;
      next;
    }
  elsif(/int TCUID;/ or
	 /int TCUS;/)
    {
      next;
    }
# else
#    {
#      s/int TCUID;/register int TCUID asm ("\$16");/;
#      s/int TCUS;/register int TCUS asm ("\$17");/;
#    }

  print OUT $_;
}
close (IN);
close (OUT);


print "\n compile (.s) --> gcc -S -O2 -I$XCC_DIR/include $filePrefix.gcc_in.c\n";
system ("$XCC_DIR/bin/gcc -S -O2 -I$XCC_DIR/include $filePrefix.gcc_in.c");
# GOOD system ("$GCC_DIR/bin/gcc -S -O2  -I$XCC_DIR/include $filePrefix.gcc_in.c");
# REGULAR GCC system ("gcc -S -O2 -I$XCC_DIR/include $filePrefix.gcc_in.c");
#system ("$GCC_DIR/bin/gcc -S -O2  -I$XCC_DIR/include -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/ssbig-na-sstrix/include -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/glibc-1.09 -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/glibc-1.09/sysdeps/generic -I/a/amber/amber1/amber1-local/dorit/SimpleScalar/glibc-1.09/string $filePrefix.gcc_in.c");

# 6) determine what the allocation size would be:
#
# file.gcc_in.s --> (5) --> file.s

print "\n --> lastPhase.pl $filePrefix.gcc_in.s\n";
system("lastPhase.pl $filePrefix");

#system("clean.pl $filePrefix.s");


# Remove Intermidiate files
#

if($keep == 0)
  {
    system("rm $filePrefix.snt");
    system("rm $filePrefix.fp1");
    system("rm $filePrefix.xpass");
    system("rm $filePrefix.xpass.c");
    #system("rm $filePrefix.gcc_in.c"); 
    system("rm $filePrefix.gcc_in.s");
  }



