#! /usr/bin/perl
# /* 
#  * 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 build an emulator
#  *
#  * Authors: David A. Penry <dpenry@cs.princeton.edu>
#  *
#  * This script builds an emulator.  It finds the correct include files
#  * for the type of information, builds a small make file with necessary
#  * parameters of the build, and then calls make.
#  *
#  */

$| = 1;

# Check the environment

$IMPACT = $ENV{"IMPACT_ROOT"};
$LIBERTY_COMP_BIN = $ENV{"LIBERTY_COMP_BIN"};
$LIBERTY_SCRIPT_BIN = $ENV{"LIBERTY_SCRIPT_BIN"};
$LIBERTY_EMU_DATA = $ENV{"LIBERTY_EMU_DATA"};

if($LIBERTY_EMU_DATA eq "") {
    die "LIBERTY_EMU_DATA is not set"
    }

$LIBERTY_EMUMODS = $LIBERTY_EMU_DATA . "/emulator/perlmods";

die "\nLIBERTY_SCRIPT_BIN is not set\n"
    if ($LIBERTY_SCRIPT_BIN eq "");

if($LIBERTY_COMP_BIN eq "") {
    $COMPILER="lc-legacy";
} else {
    $COMPILER="$LIBERTY_COMP_BIN/lc-legacy";
}

# Check the options

$EXTOPT ="";
$M4OPT ="";
$OPT = "-g";
$COMPOPT = "";
$LEVEL="4";
$SPLITSIZE=200;
$ISA=$ENV{"LIBERTY_ISA"};
$LINKOPT="";
if ($ISA eq "") { $ISA="Lcode"; }

$curr_needed = 0;
while ($#ARGV >=0) {
    $this = $ARGV[0];
    if ($this =~ /^-/) {
	if ($this eq "-gcc") {
	    shift @ARGV;
	    $OPTI .= " " . $ARGV[0];
	}
	elsif ($this eq "-m4") {
	    shift @ARGV;
	    $M4OPT .= " " . $ARGV[0];
	}
	elsif ($this eq "-link") {
	    shift @ARGV;
	    $LINKOPT .= " " . $ARGV[0];
	}
	elsif ($this eq "-X") {
	    $M4OPT .= " --define=__OS_USE_X";
	}
	elsif ($this eq "-level") {
	    shift @ARGV;
	    $LEVEL = $ARGV[0];
	}
	elsif ($this eq "-splitsize") {
	    shift @ARGV;
	    $SPLITSIZE = $ARGV[0]; 
	}
	elsif ($this eq "-isa") {
	    shift @ARGV;
	    $ISA = $ARGV[0]; 
	}
	elsif ($curr_needed==0) {
	    $emtype = $this;
	    $curr_needed++;
	}
	else {
	    &usage("Unrecognized option '" . $this . "'");
	}
    }
    else {
	&usage("Unrecognized argument '" . $this . "'");
    }
    shift @ARGV;
}

if ($curr_needed !=1) {
    &usage();
    exit 1;
}

LoadEMU($emtype);
$PRDIR=$Liberty::Emulator::emulation_dir;
$MAKEOPT=$Liberty::Emulator::MAKEOPT;

if (0) {
if ($emtype eq "-t") {
    $PRDIR="PR_emulate";
} elsif ($emtype eq "-s") {
    $PRDIR="PR_simulate";
} elsif ($emtype eq "-p") {
    $PRDIR="PR_profile";
} elsif ($emtype eq "-cp") {
    $PRDIR="PR_context_cfg";
} elsif ($emtype eq "-mp") {
    $PRDIR="PR_pf_malloc";
} elsif ($emtype eq "-memp") {
    $PRDIR="PR_pf_mem";
} elsif ($emtype eq "-b") {
    $PRDIR="PR_branch";
} elsif ($emtype eq "-cache") {
    $PRDIR="PR_cache";
} elsif ($emtype eq "-cache_event") {
    $PRDIR="PR_cache";
    $MAKEOPT="CACHE=both-event.o";
} elsif ($emtype eq "-P") {
    print "-P not supported yet\n";
    exit 1;
} else {
    &usage();
    exit 1;
}
}

$OPT .= " " . ${EXTOPT};
$M4OPT = "--define=RT_ONE_FUNC_LEVEL=${LEVEL} --define=PR_style=${PRDIR} ${M4OPT}";

$glibinc = `glib-config --cflags`;
chop($glibinc);
$gliblib = `glib-config --libs`;
chop($gliblib);
    
open(MAKEFILE, ">proginfo.mk") || die("Unable to write proginfo.mk");
print MAKEFILE "
LIBERTY_COMP_BIN=${LIBERTY_COMP_BIN}
LIBERTY_EMU_DATA=${LIBERTY_EMU_DATA}
M4OPT=${M4OPT}
CCOPTS=${OPTI} 
LINKOPTS=${LINKOPT}
LEVEL=${LEVEL}
GLIBINC=${glibinc}
GLIBLIB=${gliblib}
HOSTOS=OS_Linux32
RUNTIME=RT_${ISA}
SPLITSIZE=${SPLITSIZE}
PROGNAME=unknown
";
    close(MAKEFILE);

&dosysfail("make -f ${LIBERTY_EMU_DATA}/emulator/${PRDIR}/PR_buildprog.mk ${MAKEOPT}");

exit 0;

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

sub dosys() {
    $s=$_[0];
    print "le-buildprog==> " . $s . "\n";
    system $s;
}

sub dosysfail() {
    $s=$_[0];
    print "le-buildprog==> " . $s . "\n";
    system ($s) == 0 || die "Failed in $s\n";
}

sub LoadEMU() {
    $thisemu = $_[0];
    print "Loading emulation $thisemu\n";

    # find the emulation module and load it
    if (-e "./emulation-$thisemu.pm") {
	require "./PR_script_$thisemu.pm";
    }
    elsif (-e "$LIBERTY_EMUMODS/PR_script_$thisemu.pm") {
	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() {
    $diestr = "
Usage: le-buildprog <emulation type> [options]

       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 .= "
       options:
        -isa <isa name>         - RT_<isa> to use
        -X                      - include the X shared memory interface
        -gcc <extension>        - gcc arguments (\"-gcc '-O2 -g'\" for example)
        -m4 <args>              - m4 arguments
        -link <args>            - linker arguments
        -splitsize <size>       - sets the maximum size of C/M4 files
        -level <level>          - set the one-func level (1=monolithic,
                                                          2=func per func (?), 
                                                          3=func per basic block,
                                                          4=func per instr)

  Environment variables
        USER_BENCH_PATH[1-4]    - The default benchmarks
                                  directories (overriden above)
        LIBERTY                 - Path the the liberty compiler source tree
                                  FIXME: Should be a pointer to install loc
        IMPACT_ROOT             - Location of the IMPACT install(not needed 
                                  with -noimpact if BENCH or -benchmarks_dir
                                  is used)
        LIBERTY_ISA             - Default ISA

  Example:
      le-buildprog -t -level 4 -splitsize 3000
";

    die $diestr;
}

