#! /bin/sh
#! perl
eval '(exit $?0)' && eval 'exec perl -S -x $0 ${1+"$@"}'
                    & eval 'exec perl -S -x $0 $argv:q'
                            if $running_under_some_shell;
# /* 
#  * Copyright (c) 2000-2002 The Liberty Computer Architecture Research
#  * Group. (http://www.liberty-research.org)
#  *
#  * All rights reserved.
#  * 
#  * Permission is hereby granted, without written agreement and without
#  * license or royalty fees, to use, copy, modify, and distribute this
#  * software and its documentation for any purpose, provided that the
#  * above copyright notice and the following two paragraphs appear in
#  * all copies of this software.
#  * 
#  * IN NO EVENT SHALL THE LIBERTY COMPUTER ARCHITECTURE RESEARCH GROUP
#  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
#  * OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE
#  * AND ITS DOCUMENTATION, EVEN IF THE LIBERTY COMPUTER ARCHITECTURE
#  * RESEARCH GROUP HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#  * 
#  * THE LIBERTY COMPUTER ARCHITECTURE RESEARCH GROUP SPECIFICALLY
#  * DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
#  * AND THE LIBERTY COMPUTER ARCHITECTURE RESEARCH GROUP HAS NO
#  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
#  * OR MODIFICATIONS.
#  *
#  */
# /*%
#  * 
#  * Script to go from source->assembly->X->EM4->emulator->run
#  *
#  * Authors: David August <august@cs.princeton.edu>
#  *          Spyridon Triantafyllis <strianta@cs.princeton.edu>
#  *          David A. Penry <dpenry@cs.princeton.edu>
#  *
#  * This script is independent of both ISA and emulation style.
#  * DO NOT MODIFY UNLESS YOU KNOW WHAT YOU ARE DOING
#  *
#  * It finds the ISA to use through either the $LIBERTY_ISA environment 
#  * variable or the first command line option.  It then loads an ISA 
#  * package from the local directory or the emulator Perl module 
#  * install location.  The file name is RT_ISA_<isa>.pm.  This package 
#  * Liberty::ISA contains routines for argument parsing, argument 
#  * validation, compilation, and initial Xcode generation.
#  *
#  * It finds the emulation style to use through the first command line
#  * option after all ISA options are removed.  It then loads an emulator
#  * package from the local directory or the emulator Perl module
#  * install location.  The file name is PR_script_<style>.pm.  This
#  * package Liberty::Emulator contains routines for argument parsing,
#  * argument validation, emulation Xcode preprocessing, pre-run commands,
#  * and post-run commands.
#  *
#  * The steps are then:
#  *  1) Compiles source to assembly using the ISA routine
#  *     (this can be skipped with -nocompile or -spath)
#  *  2) Translates the assembly to Xcode using the ISA routine
#  *     (skip with -noXgen)
#  *  3) Translates the Xcode as needed for the emulator 
#  *     (skip with -noemubuild)
#  *  4) Translates the resultant Xcode to EM4 (skip with -noemubuild)
#  *  5) Calls le-buildprog to build an emulator (skip with -noemubuild)
#  *  6) Builds a native version of the benchmark (skip with -nonative)
#  *  7) Calls l-run to run/check the native program (skip with -nonative)
#  *  8) Calls l-run to run/check the emulated program (skip with -norun, also
#  *     doesn't happen if building an emulator for the Liberty simulator)
#  *
#  * Note that the benchmark is read as a line from stdin; multiple benchmarks
#  * can be listed.  Also, # can be used for comments.
#  *
#  */

$| = 1;

##### Check the environment

$LIBERTY_COMP_BIN = $ENV{"LIBERTY_COMP_BIN"};
$LIBERTY_COMPILER_BIN = $ENV{"LIBERTY_COMPILER_BIN"};
$LIBERTY_SCRIPT_BIN = $ENV{"LIBERTY_SCRIPT_BIN"};
$LIBERTY_SCRIPT_DATA = $ENV{"LIBERTY_SCRIPT_DATA"};
$LIBERTY_EMU_DATA = $ENV{"LIBERTY_EMU_DATA"};
$LIBERTY_ISA = $ENV{"LIBERTY_ISA"};

die 
"No Liberty installation has been specified.  Specify this through the 
LIBERTY_SCRIPT_BIN and LIBERTY_SCRIPT_DATA environment variables.
" if ($LIBERTY_SCRIPT_BIN eq "" || $LIBERTY_SCRIPT_DATA eq "");

#do $LIBERTY_SCRIPT_DATA . "/scripts/perlsubs.pl";
do $LIBERTY_SCRIPT_DATA . "perlsubs.pl";

die 
"No Liberty emulator installation has been specified.  Specify this 
through the LIBERTY_EMU_DATA environment variable.
" if ($LIBERTY_EMU_DATA eq "");

$LIBERTY_EMUMODS = $LIBERTY_EMU_DATA . "/emulator/perlmods";
print "${LIBERTY_EMUMODS}\n";

# Set up some defaults which we don't complain about...
# Look for new compiler first
if($LIBERTY_COMPILER_BIN eq "") {
    $NEWCOMPILER=0;
    if($LIBERTY_COMP_BIN eq "") { $COMPILER="lc-legacy"; }
    else { $COMPILER="$LIBERTY_COMP_BIN/lc-legacy"; }
} else {
    $NEWCOMPILER=1;
    $COMPILER="${LIBERTY_COMPILER_BIN}/compiler";
}

if ($LIBERTY_ISA eq "") { $LIBERTY_ISA = "Lcode"};

# And look for Impact
$IMPACT = $ENV{"IMPACT_ROOT"};
die "
IMPACT_ROOT is not set.  IMPACT scripts and environment variables are
needed to determine how to build and run benchmarks.
" if ($IMPACT eq "");

#### Check the options

$WORKDIR=`pwd`; chomp($WORKDIR);
$curr_needed = 0;
$ISA_LOADED = 0;
$EMU_LOADED = 0;

$NOCOMPILE = 0;
$NOINLINING = 0;
$SPATH = "";

$NOXGEN = 0;
$XCDIR = ".";
$XLIBDIR = "";
$XCARGS = "";
%EXCLUDE_FILES = ();

$NOBUILD=0;
$LEVEL="4";
$SPLITSIZE=500;
$M4OPT ="";
$OPTI = "-g";
$NOBENCH=0;
$EXTRALINK="";
$NOEM4GEN=0;
$EM4LIBDIR="";

$NONATIVE=0;
$NORUN=0;
$INPUTSET="";

$SAID_MARKS = 0;
@ARGS =("O");
LoadISA($LIBERTY_ISA);
@ARGS = Liberty::ISA::parse_args(@ARGS);
LoadEMU("-t");
$curr_needed++;

if ($curr_needed !=1) {
    &usage("Missing emulation type argument");
    exit 1;
}

# if we didn't have *any* options, load the ISA.  Shouldn't get here
# anyway
if (!$ISA_LOADED) {
    $ISA = "Lcode";
    $ISA_LOADED = 1;
    LoadISA($ISA);
}

# If we compile and make the emulator, we'd better make Xcode
if (!$NOCOMPILE && !$NOBUILD) {
    $NOXGEN = 0;
    $XPATH = "";
}

# Check that arguments were good for the ISA 
if (($s = Liberty::ISA::validate_args()) ne "") {
    &usage($s);
}
if (($s = Liberty::Emulator::validate_args()) ne "") {
    &usage($s);
}


MAIN: while(<STDIN>)
{
    s/#.*$//;
    next MAIN if (/^$/);
    split;
    $line = $_[0];
    next MAIN if ($line eq "");

    system("echo RUNNING ${line} $sourcetype $emtype: >> results");
    print "RUNNING ${line} $sourcetype $emtype:\n";
    system("echo Started: `date` >> results");

    # Check for benchmark directory
    $BENCH_DIR = "$WORKDIR/${line}";

    
    # Now make the directory to work in and go there

    &createdirifnotthere("${line}", 0777);
    chdir("${line}");

    print "YO: ${BENCH_DIR} :OY\n";

    #&Liberty::Emulator::do_Xcodeprep($line);

    if (! $NOBUILD) {

	chdir("${line}.EM4");
	
        $setup = "";
	
	if ($setup ne "") { 
	    if ($EXTRALINK ne "") {
	      $linkopts=" -link " . &putquotes($setup . " " . $EXTRALINK);
	    } else {
	      $linkopts=" -link " . &putquotes($setup);
	    }
	}
	else {
	    if ($EXTRALINK ne "") {
	      $linkopts=" -link " . &putquotes($EXTRALINK);
	    } else {
	      $linkopts="";
	    }
	}

	&dosysfail("le-buildprog $emtype -level ${LEVEL}"
		   . " -m4 " . &putquotes($M4OPT) 
		   . " -gcc " . &putquotes($OPTI) 
		   . " -splitsize ${SPLITSIZE} "
		   . $linkopts . " -isa $thisisa");

	
    }
    else {
	die "$line.EM4 output directory missing" unless (-d "$line.EM4");
	chdir("$line.EM4");
    }

    if (!$NORUN) {

	&createdirifnotthere("emu", 0777);
	
	$BENCHOPT = ""; 


	chdir ("emu");
	&Liberty::Emulator::do_beforerun($line);
        
	print "Running generated:\n";
	&dosys("$LIBERTY_SCRIPT_BIN/l-run  ${BENCH_DIR}");

	&Liberty::Emulator::do_afterrun($line);

	chdir("..");
    }

    chdir("../..");
}

exit 0;

############################### Subroutines ###########################


sub LoadISA() {
    $thisisa = $_[0];

    # find the ISA compilation module and load it
    if (-e "./RT_ISA_$thisisa.pm") {
	print "Loading ISA $thisisa from ./RT_ISA_$thisisa.pm\n";
	require "./RT_ISA_$thisisa.pm";
    }
    elsif (-e "$LIBERTY_EMUMODS/RT_ISA_$thisisa.pm") {
	print "Loading ISA $thisisa from " 
	    . "$LIBERTY_EMUMODS/RT_ISA_$thisisa.pm\n";
	require "$LIBERTY_EMUMODS/RT_ISA_$thisisa.pm";
    }
    else { die "Unable to find compilation macros for ISA '$thisisa'"; }
    $ISA = $thisisa;
    $ISA_LOADED = 1;
}

sub LoadEMU() {
    $thisemu = $_[0];
    print "$thisemu";
    # find the emulation module and load it
    if (-e "./emulation-$thisemu.pm") {
	print "Loading emulation $thisemu from ./PR_script_$thisemu.pm\n";
	require "./PR_script_$thisemu.pm";
    }
    elsif (-e "$LIBERTY_EMUMODS/PR_script_$thisemu.pm") {
	print "Loading emulation $thisemu from "
	    . "$LIBERTY_EMUMODS/PR_script_$thisemu.pm\n";
	require "$LIBERTY_EMUMODS/PR_script_$thisemu.pm";
    }
    else { 
	die "Unable to find emulation macros for emulation type '$thisemu'"; 
    }
    $emtype = $thisemu;
    $EMU_LOADED = 1;
}

sub usage() {
    $prog = $0; $prog=~s+.*/++;
    if ($_[0] ne "") { $diestr = "$prog ERROR: $_[0]\n"; }
    else { $diestr = ""; }
    $diestr .=  "
Usage: $prog [-isa ISA] [ISA options] emutype [emu options] [other options]
         OR
       $prog -emutype emutype [-isa ISA] [ISA options] [emu options]
                                  [other options]

 Prepares an emulator for a benchmark and then runs the emulator.

 Arguments:
        emutype                 - the type of emulator to build
        -emutype <emutype>      - the type of emulator to build
                                  (can only be used as first option)

   The benchmark names are read from stdin.

 Emulation types:
";
    # Find emulation types
    $types=`find . $LIBERTY_EMUMODS -maxdepth 1 -name 'PR_script_*.pm' -printf '%p '`;
    @types = split(' ',$types);
    foreach $t (@types) {
	$name = $t;
	$name =~ s/^.*\/PR_script_//; $name =~ s/.pm$//;
	$descr = `grep '^.description[ \t]*=' $t`;
	chomp($descr);
	$descr =~ s/^[^\"]*\"//; $descr =~ s/\".*$//;
	$diestr .= sprintf("        %-23s - %s\n",$name,$descr);
    }

    $diestr .= "
 Defined ISAs:
";

    # Find ISAs:
    $findcmd = "find . $LIBERTY_EMUMODS -maxdepth 1 -name 'RT_ISA_*.pm' " .
	"-printf '%p '";
    $types=`$findcmd`;
    @types = split(' ',$types);
    foreach $t (@types) {
	$name = $t;
	$name =~ s/^.*\/RT_ISA_//; $name =~ s/.pm$//;
	$descr = `grep '^.description[ \t]*=' $t`;
	chomp($descr);
	$descr =~ s/^[^\"]*\"//; $descr =~ s/\".*$//;
	$diestr .= sprintf("        %-23s - %s\n",$name,$descr);
    }

    $diestr .= "
 Global options:
        -h|-help                - This message
        -nocompile              - do no compilation
        -ni                     - no inlining
        -spath <dir>            - set assembly files library directory tree 
                                  root; implies -nocompile
                                  (archived assembly files are in 
                                   <dir>/<benchmark>)
        -noXgen                 - do no Xcode generation
        -cfg                    - build and print call graph and CFG.
        -Xdir  <dir>            - set gzipped Xcode library directory
                                  implies -noXgen and -nocompile
        -skip_file <file_root>  - excludes a file from conversion to Xcode
		                  this option can be repeated

	-noEM4gen               - do no EM4 generation
        -EM4dir  <dir>          - set gzipped EM4 library directory
                                  implies -noEM4gen, -noXgen, -nocompile

	-nobuild                - do no build
        -X                      - include the X shared memory interface
        -m4 <extension>         - m4 arguments (-m4 '-o debug' for example)
        -gcc <extension>        - gcc arguments (-gcc '-O2 -g' for example)
        -link <extension>       - link arguments (-link '-lm' for example)
        -splitsize <size>       - sets the maximum size of C/M4 files
        -level <level>          - set the one-func level
				    3=func per basic block
                                    4=func per instr

        -norun                  - don't run the emulator (or native) binary
        -nonative               - don't build the native binary
        -input <input set>      - use another input set

	-nobench                - do not treat as a benchmark:
				  - do not lookup compile/link options
				  - do not lookup run information
				  - do not compare results
        -benchmarks_dir <dir>   - set benchmarks directory
                                  (benchmarks are in <dir>/<benchmark>)
        -bench_dir <dir>        - set individual benchmark directory
                                  (benchmark is in <dir>)

";
    if ($ISA_LOADED) {
	$diestr .= Liberty::ISA::usage();
	$diestr .= "\n";
    }
    if ($EMU_LOADED) {
	$diestr .= Liberty::Emulator::usage();
    }

    $diestr .= "
 Environment variables:
        USER_BENCH_PATH[1-4]    - The default benchmarks
                                  directories (override with -benchmarks_dir)
	LIBERTY_COMP_BIN        - Path to the Liberty compiler binary install
                                  directory
	LIBERTY_SCRIPT_BIN      - Path to the Liberty script install
                                  directory
	LIBERTY_SCRIPT_DATA     - Path to the Liberty script shared data
                                  install directory
	LIBERTY_EMU_DATA        - Path to the Liberty emulator data install
                                  directory
        LIBERTY_ISA             - ISA to use (can be overridden with -isa)
        IMPACT_ROOT             - Location of the IMPACT installation

 Output locations:
   Emulators are created in ./<benchmark>/<benchmark.EM4>.
   Native run output is put in ./<benchmark>/<benchmark.EM4>/native
   Emulator run output is put in ./<benchmark>/<benchmark.EM4>/emu

 Example:
      To run the wc test emulator for Impact, do:
          echo wc|l-bench O -t
";


    die $diestr;
}

