#!/usr/local/bin/perl
#######################################################################
# File Name    : synbatch
# Date Created : 6/16/00
# Author       : Doug Hergatt, Gregg D. Lahti & Tim L. Wilson
# Project      : 
#######################################################################
# $Id: synbatch,v 1.5 2000/08/12 09:15:56 glahti Exp $
#######################################################################
# Description:
# This script is used to drive the synthesis compilation of a target. 
# The G_DESIGN_FILE_NAME, G_SUBFUBS, & G_LIBRARY_NAME are passed in
# from gmake (or syn_make.rules).
#######################################################################

# Check for project specific environment variables
die "Environment variable PROJ_NAME is not defined!\n" if (!defined($ENV{PROJ_NAME}));
die "Environment variable PROJ_SYN is not defined!\n" if (!defined($ENV{PROJ_SYN}));

$proj_name = $ENV{PROJ_NAME};
$proj_syn = $ENV{PROJ_SYN};

# This is the project setup script
$proj_script = $ENV{PROJ_SYN} . "/" . "tops_setup";

# Setup interrupt handler to die on SIGINT (ctrl-c)
$SIG{INT} = 'die_on_error';

# Set the hostname
$machine = `hostname`;

# Get design name from make (stripped of path & suffix from gmake)
$design_file_name = $ARGV[0];

# Strip off path & extension
$design = $design_file_name;
$design =~ s/(\S+)\..*/$1/;
$design =~ s%.*?([^/]+)$%$1%;

# Create log file
$logfile = "log/${design}.log";
# Retain last copy of log file
if (-e $logfile) {
  system("mv $logfile $logfile.1");
}

# Parse the command line for arguments
shift @ARGV;
while (@ARGV) {
  if ($ARGV[0] =~ /LIB=(.*)/) {
    $lib = $1;
  } elsif ($ARGV[0] =~ /SUBFUB=(.*)/) {
    $subfub_list = $1;
  } elsif ($ARGV[0] =~ /HOST=(.*)/) {
    $rsh_host = $1;
  }
  shift @ARGV;
}

# Print info on current compilation process
print "\nExecuting with arguments:\n";
print "G_LIBRARY_FILE: $lib\n";
print "G_DESIGN_FILE_NAME: $design_file_name\n";
print "G_SUBFUBS: $subfub_list\n";
print "REMOTE_HOST: $rsh_host\n\n";

# Set default, TOPS will assign actual default lib
if ($lib eq "") {
  $lib = "DEFAULT";
}

# This builds the command line that will be executed below
$line = "dc_shell-t -x \"set G_DESIGN_FILE_NAME $design_file_name; set G_SUBFUBS \[list $subfub_list\]; set G_LIBRARY_NAME $lib; source ${proj_syn}/proj_main.tcl\" ";

# if running on remote machine, add rsh, and extra commands to front of line to execute

$CMD_FILE = $rsh_host . ".csh";
open (CMD_FILE_HANDLE,">$CMD_FILE") || die "Error: can't open $CMD_FILE file";

if ($rsh_host ne "") {
  print CMD_FILE_HANDLE "#!/bin/tcsh\n";
  print CMD_FILE_HANDLE "# auto generated command file for running TOPS remotely\n\n";

  $pwd = `pwd`;
  chomp($pwd);
  print CMD_FILE_HANDLE "cd $pwd;\n";

  print CMD_FILE_HANDLE "source $proj_script;\n\n";
  print CMD_FILE_HANDLE "echo \"Starting dc_shell session\"\n";

  print CMD_FILE_HANDLE "dc_shell-t -x \"set G_DESIGN_FILE_NAME $design_file_name; set G_SUBFUBS [list $subfub_list]; set G_LIBRARY_NAME $lib; source ${proj_syn}/proj_main.tcl\";\n\n";
  print CMD_FILE_HANDLE "echo \"Finished remote shell script\"\n";
  close (CMD_FILE_HANDLE);
  system("chmod +x $CMD_FILE");
  $line = "rsh $rsh_host \'$pwd/$CMD_FILE\'";
  $machine = $rsh_host;
}

# Fork our process into parent/child processes
FORKU: {
  if ($pid = fork) {
    # print "\nparent pid is $$\n";
    # this is the parent process
    #waitpid $pid,0;
    wait;
  } elsif (defined $pid) {
    # this is the child process
    # execute actual command, pipe off verbage crap from rsh to bit-bucket
    print "Compiling $design on $machine\n";
    # Execute the command file (remote) or line generated above
    exec("$line 2>&1 > $logfile");
    $childstatus = $?;
    # print "\nchild exited with: $childstatus, $childstatus2\n";
		
    # check for resultant db, if it isn't die with a fail exit status
    if (-e "$pwd/dbs/$design.db") { 
      $errorstatus = 1;
    }
  } elsif ($! =~ /No more process/) {
    # Barf!  A supposedly recoverable fork process
    sleep 5;
    redo FORKU;
  } else {
    # weird fork error
    die "Can't fork: $!\n";
  }
}

# Generate the Log Summary File
generate_log_summary();

# We're done, cleanup and exit nicely
if ($childstatus != 0 or $errorstatus != 0) {
  exit(1);
} else {
  system("rm $CMD_FILE");
  exit(0);
}

# trap & cleanup subroutines
sub die_on_error { 
  local ($sig) = @_;
  # print STDOUT "trapping signal $sig!\n";
  kill 9, $pid++;
  kill 9, $pid++;
  kill 9, $pid++;
  kill 9, $pid;
  exit(1);
}

# Subroutine to generate the log summary file
sub generate_log_summary { 
  print "Generating Log Summary File\n";

  $log_file = "log/${design}.log";
  $log_file_summary = "log/${design}.log.summary";

  # Retain last copy of log summary file
  if (-e $log_file_summary) {
    system("mv $log_file_summary $log_file_summary.1");
  }

  open (LOG_FILE,"$log_file") || die "Error: can't open $log_file";
  open (LOG_FILE_SUMMARY,">$log_file_summary") || die "Error: can't open $log_file_summary";

  # Start a header in the log summary file
  print LOG_FILE_SUMMARY "##########################################################\n";
  print LOG_FILE_SUMMARY "#    ${design} Log File Summary                           \n";
  print LOG_FILE_SUMMARY "##########################################################\n";
  print LOG_FILE_SUMMARY "\n";

  # Prep arrays with header information
  push (@errors, "# Error description:\n");
  push (@warnings, "# Warning description:\n");
  push (@elapsed_time, "# Elapsed Time for synthesis:\n");

  # Start line counter
  $line_cnt = 0;  
  $error_cnt = 0;  
  $warning_cnt = 0;  
  # Search for lines with errors and warnings
  while (<LOG_FILE>) {
    $line_cnt++;
    if (/^.*Error/) {
      s/Error//;
      push (@errors, "line no $line_cnt: $_");
      $error_cnt++;
    } elsif (/^Warning/) {
      s/Warning//;
      push (@warnings, "line no $line_cnt: $_");
      $warning_cnt++;
    } elsif (/Elapsed time/) {
      push (@elapsed_time, $_);
    }
  }

  # Format summary log output
  print LOG_FILE_SUMMARY "There are $error_cnt errors, $warning_cnt warnings\n\n";
  print LOG_FILE_SUMMARY "@elapsed_time\n";

  if ($error_cnt > 0) {
    print LOG_FILE_SUMMARY "@errors\n";
  }

  if ($warning_cnt > 0) {
    print LOG_FILE_SUMMARY "@warnings\n";
  }

  close LOG_FILE;
  close LOG_FILE_SUMMARY;
}

###############################################################################
# $Log: synbatch,v $
# Revision 1.5  # 2000/08/12 09:15:56 glahti 
###############################################################################



