#! /usr/bin/perl

# This script supports the following options:
# -rl <rtl test list file> : this is mandatory if rtl is to be run
# -gl <gate test list file> : this is mandatory if either best or worst is to be run
# -bl <best case test list file> : this is mandatory if -best is used and -gl is not specified
#     if both -bl and -gl are specified, then -bl takes precidence
# -wl <worst case test list file> : this is mandatory if -worst is used and -gl is not specified
#     if both -wl and -gl are specified, then -bl takes precidence
# -s <bsub submit script file> : this is mandatory
# -rtl: run rtl simulations
# -best: run best case simulations
# -worst: run worst case simulations
# -gates: run both best and worts case simulations
# !! if none of the previous 5 options are used all four modes will be used.
# -counter: start value for the job id counter, usefull to redefine from default 1000, if want to
# -block <block_name>: specify the block name for generating the directory for log files.
# -top <dut1,dut2>: specify the list of dut for coverage. Default = $block.

# import the users environment variables for their home dir and for the name of the workarea
# so that we can make sure that there is a unique directory generated to store the log files.
use Env qw(DDK);

# define default values for certain variables that can be (re)defined on the command line.
$test_file = "not_defined";
$regress_file = "not_defined";
$run_rtl = 0;
$run_best = 0;
$run_worst = 0;
$block = "dig_owi";
$top = $block;

# we use a counter to keep track of the job number.  This is for two purposes:
# 1) each simulation needs its own library so that it does not corrupt other concurrent simulations
#    We give each library a unique name using this counter (by using the +nclibdirname+ verilog option)
# 2) we use the counter to give each simulation a unique, but easy to determine job name, so that we
#    can create lsf job dependancies (reason for this explained later)
$counter = 1;

# use perl library command to extract the command line options.
use Getopt::Long;
&GetOptions("tl=s" => \$test_file, "s=s" => \$regress_file, "rtl"=>\$run_rtl, "best" => \$run_best, "worst" => \$run_worst, "gates" => \$run_gates, "counter=i" => \$counter, "block=s" => \$block, "top=s" => \$top);

# if run_gates is set, then implies both best and worst are run, so set up these variables
if ($run_gates eq 1) {
  $run_best = 1;
  $run_worst = 1;
}

# if we didn't specify any conditions to run, then assume all are to be run
if (($run_rtl eq 0) and ($run_best eq 0) and ($run_worst eq 0)) {
  $run_rtl = 1;
  $run_best = 1;
  $run_worst = 1;
}

# check that minimum arguments were specified, and exit if they weren't
if ( ($test_file eq "not_defined") or ($regress_file eq "not_defined") ) {
  print "\nImproper usage\n";
  print "Correct Usage create_regression_cmd <-block block name>\n";
  print "                                    <-tl test list filename>\n";
  print "                                    <-s submit regression cmd filename>\n";
  print "                                    [-rtl|-worst|-best|-gates] [-counter]\n";
  print "-tl is used to specify the file containing the list of tests to run\n";
  print "-s is used to specifiy the name of the file to store the bsub commands to submit.\n";
  print "-rtl: run rtl simulations.\n";
  print "-best: run best case simulations.\n";
  print "-worst: run worst case simulations.\n";
  print "-gates: run both best and worst case simulations.\n";
  print "if none of -rtl,-best,-worst or -gates is specified, then all three conditions are run.\n";
  print "-counter: redefine the start value of the job id, defaults to 1000.  Use this if you want to run more jobs while a regression\n";
  print "          is already in progress. Make sure the value is chosen such that there will not be an overlap with existing jobs.\n";
  print "-block: Determines which block the regression is for. Mandatory";
  exit;
}

# make sure the directory to store the logfiles exists (this may cause error messages if they already exist)
if (-d "logfiles") {
} else {
   system "mkdir logfiles";
}

# ------------------------------------------------------------------------------
# AMS
# ------------------------------------------------------------------------------
open(SCS,"../verilog/run.scs");
print SCS "*\ntransient tran stop=100s";
close SCS;

# open the output file
open(RP, ">$regress_file") || die "Can't Open regression file: $!\n";

# loop for the three conditions we will be simulating

   foreach $cond (rtl,best,worst) {
    print "   $cond\n";
    if ((($cond eq "rtl") and ($run_rtl eq 0)) or (($cond eq "best") and ($run_best eq 0)) or (($cond eq "worst") and ($run_worst eq 0))) {
      next;
    }
    
    # Verilog files
    # ------------------------------------------------------------------------------
    if ($cond eq rtl) {
      $vfiles="../../rtl_v/*.v -v ../verilog/library.v";
    } else {
      $vfiles="../../postlayout_v/*.v -v ../verilog/library.v -bbinst *DIODE* -bbinst io_diode*" ;
    }
    
    # Warning suppresion
    # ------------------------------------------------------------------------------
    $nowarn = "-ncerror SDFSNF +nowarn+NTCWID +nowarn+SDFNDP +nowarn+CUVWSP +nowarn+CUVMPW +nowarn+CSINFI +nowarn+SDFNET +nowarn+SDFINF +nowarn+SDFINC +nowarn+LIBNOU +nowarn+DLCLIB +nowarn+DLCPTH +nowarn+PSDNGL2 +nowarn+SANGL2 +nowarn+NTCNNC +nowarn+MEMODR";
    
    # SDF back annotation
    # ------------------------------------------------------------------------------
    if (($cond eq "best") | ($cond eq "worst")) {
      if (-d "timing") {
      } else {
         system "mkdir timing";
      }
      system "rm -f timing/*${cond}*";
      $sdfcmdfile="timing/sdf_annotation_$cond.cmd";
      $sdfcmd="-nontcglitch -define POSTLAYOUT_SIM -sdf_cmd_file $sdfcmdfile";
      open(SDFCMD, ">$sdfcmdfile");
      for $sdffile (<../../timing/*.${cond}.sdf>) {
        
        $sdffile =~ s/\.\.\/\.\.\/timing\/(.*)/$1/;
        $sdftop = $sdffile;
        $sdftop =~ s/\.${cond}\.sdf//;
        system "ncsdfc -logfile timing/ncsdfc_${sdffile}.log -output timing/${sdffile}.X ../../timing/$sdffile";
        print SDFCMD "COMPILED_SDF_FILE = \"timing/$sdffile.X\",\nSCOPE = testbench.$sdftop;\n";
      }
      close SDFCMD;
    }
    if ($cond eq "best") {
      $nowarn = "$nowarn +mindelays";
    }
    if ($cond eq "worst") {
      $nowarn = "$nowarn +maxdelays";
    }
    
    # Testbench files
    # ------------------------------------------------------------------------------
    $tbfiles = "../../testbench/timescale.v";
    if ( -e "../../testbench/testbench.v" ) {
       $tbfiles = "$tbfiles ../../testbench/testbench.v";
    } else {
       $tbfiles = "$tbfiles ../../testbench/testbench.sv";
    }
    for $tbfile (<../../testbench/modules_v/*.*>) {
       $tbfiles = "$tbfiles $tbfile";
    }

    # Remove previous log files
    # ------------------------------------------------------------------------------
    print RP "rm -f logfiles/*.$cond.log\n";
    if ($cond eq rtl) {
    print RP "rm -rf ../coverage/design/*\n\n\n";
    }
    system "rm -rf include/*.$cond";


    # Open the file with the tests for our current condition
    # ------------------------------------------------------------------------------
    open(TP, $test_file) || die "Can't Open test file: $test_file $!\n";

    while(<TP>) {
      # Get rid of newline
      chomp;

      # Skip comment lines and blank lines
      if (/^#/ || /^$/) {
        next;
      } else {
        @results = split(/\//);
        $vector = $results[0]; 
        $test_name = $results[1];
      }

      # Dont run scan tests in rtl mode
      if (($vector eq "scan") and ($cond eq "rtl")) {
        print "vector is $vector, testname is $test_name (skipped in RTL)\n";
        next;
      } else {
        print "vector is $vector, testname is $test_name\n";
      }
      
      # Log files
      $log = "logfiles/$vector.$test_name.$cond.log";
   
      # Include file
      if (-d "include") {} else {system "mkdir include";}
      if (-d "include/include.${vector}.${test_name}.${cond}") {} else {system "mkdir include/include.${vector}.${test_name}.${cond}";}
      open(INC, ">include/include.${vector}.${test_name}.${cond}/includes_file.v");
      
      # Include tasks files
      for $taskfile  (<../../testbench/tasks_v/*.*>) {
         print INC "`include \"$taskfile\"\n";
      }
      
      # Include stimulus files
      print INC "`include \"../../vectors/$vector/stimulus/${test_name}.v\"\n";
      
      # Code coverage (RTL only)
      if ($cond eq rtl) {
          if (-d "../coverage") {
          } else {
             system "mkdir ../coverage";
          }
          if (-e "../coverage/coverage.cov") {
          } else {
             open(COV, ">../coverage/coverage.cov");
             print COV "set_implicit_block_scoring -case -off\n";
             close COV;
          }
          $covdut = "";
          @top = split(/,/,$top);
          foreach $dut (@top) {
             $covdut = "$covdut -covdut $dut";
          }
          $cov_cmd="$covdut -coverage b:e:f -covwork ../coverage -covoverwrite -covfile ../coverage/coverage.cov -covtest test_${vector}_${test_name}";
      }

      close INC;

      # Work dir
      $work_dir = "logfiles/INCA_libs_${counter}";

      $command0 = "rm -f $log";
      $command1 = "irun -uselicense IES $cov_cmd -analogcontrol ../verilog/run.scs -l ${log}_tmp $sdfcmd $nowarn +access+rw +nclibdirname+${work_dir} +incdir+include/include.${vector}.${test_name}.${cond} $tbfiles $vfiles";
      $command2 = "rm -rf ${work_dir}" ;
      $command3 = "mv ${log}_tmp ${log}" ;

      if ((($cond eq "rtl") and ($run_rtl eq 1)) or (($cond eq "best") and ($run_best eq 1)) or (($cond eq "worst") and ($run_worst eq 1)) ) {
        print RP "$command0\n$command1\n$command2\n$command3\n";
        # print RP "$command2\n";
        # make the output readable by putting a blank line
        print RP "\n";
        print RP "\n";
      }
      $counter++;
    } # for loop
    # close test file (for worst we we need to reopen same file as best)
    close(TP);
}

close(RP);

# make sure the regression script is executable.
system "chmod 775 $regress_file";
