#!/usr/local/bin/perl -w
#
# simpram_runpram.raw
#
# (C) 1997 by Jochen Rhrig, modified by Michael Bosch
#
# Versions are corrected at make install-time
# DO NOT CHANGE OR REMOVE THE # --<version-name>-- COMMENTS !!!

$SIMPRAM_RUNPRAM_VERSION  = "TEST";
$PRAMOS_VERSION           = "4v5";
$HOST_VERSION             = "4v5";


if($0 =~ /.*runpram[^\/]*$/)
{
    print "running as runpram\n";
    $simpram = 0;
    $runpram = 1;
}
elsif($0 =~ /.*simpram[^\/]*$/)
{
    print "running as simpram\n";
    $simpram = 1;
    $runpram = 0;
}
else
{
    print "Wrong command name \7\n";
    exit(1);
}

$SIMPRAM_RUNPRAM_VERSION_LONG = ($simpram?"simpram":$runpram?"runpram":"???")." $SIMPRAM_RUNPRAM_VERSION (C) 1997 by Jochen Rhrig, modified by Michael Bosch";

$PRAM_HOME    = "/home/pram/";
$PRAM_BIN_DIR = $PRAM_HOME."bin/";
$PRAM_ETC_DIR = $PRAM_HOME."etc/";
$PRAM_LIB_DIR = $PRAM_HOME."lib/";

$HOST_ETC_PATH = $PRAM_ETC_DIR."/host/$HOST_VERSION/";
$HOST_MODULE_PATH = $HOST_ETC_PATH;

$GTODUS_PROG  = $PRAM_LIB_DIR."/simpram/gettimeofday_usec";
                  # this program splits up the current value of gettimeofday()
                  # into two 32bit values that represent a 64bit microsecond
                  # value

$WRITE_STDIN_PROG = $PRAM_LIB_DIR."/simpram/write_stdin";
$ENV{WRITE_STDIN_PROG} = $WRITE_STDIN_PROG; # writes to the stdin-buffer of
                                            # the connected terminal

$TMPDIR = ($ENV{'TMPDIR'} ? $ENV{'TMPDIR'}
          : $ENV{'TMP'} ? $ENV{'TMP'}
          : $ENV{'TEMPDIR'} ? $ENV{'TEMPDIR'}
          : "/tmp")."/";

$JTAGNET_COMMAND = $PRAM_BIN_DIR."jtagnet";

$bgproc_pid = 0;
#$log_file = "$libdir/pramsim.log";

# $DUMMY_COD_FILE = $PRAM_LIB_DIR."__DUMMYPROG.cod";

#print "start: $user $HOST $$ ">> $log_file;
#date >> $log_file;

#
# PRAM Simulator
#

$PRAMSIM  = $PRAM_BIN_DIR."pramsim";
$PRAMTOOL = $PRAM_BIN_DIR."pramtool";
$TIME    = "/usr/bin/time";

$PRAMSIM_OPT = "";
$PRAMSIM_OUTFILE_DEFAULT = "/dev/null";
$PRAMSIM_OUTFILE = $PRAMSIM_OUTFILE_DEFAULT;

#
# Grenzwerte
#

if($simpram)
{
    $MAX_PHYSNUM = 128;
}
$MAX_VIRTNUM = 31; # maximal stehen dem Benutzer 31 von 32 vPen zur Verfgung
                   # da ein vP pro pP als Serviceprozessor reserviert ist
$MAX_IOCPNUM = $MAX_VIRTNUM-1;  # maximale Zahl der io-copy-Prozessoren pro pP

#
# Default-Werte
#

$lddata = 11;           # Size of .lddata-segment
$sheap  = 8000000;      # shared Heap
$pstack = 8192;         # lokaler Stack
$pheap  = 2048;         # lokaler Heap
$pargs  = 1000;         # Dummer default.

$PHYSNUM   = 3;  # Zahl der pPen
$VIRTNUM_USER = 1; # Zahl der vPen pro pP (ohne Serviceprozessor)
if($runpram)
{
    $VPPERPP = 32; # hardwaremig einzustellende Zahl der vPen pro pP
                   # (8, 16, 24 oder 32)
}
$IOCPNUM=0;          # Zahl der io-copy-Prozessoren pro pP

$SYSTEM_STACK_SIZE = 4096; # Gre (in Word) des Betriebssystemstacks

$JTAGNET_PARAMS = 0; # Parameter fr jtagnet

$HASH_FACTOR = 1;

$TRACE_OUTPUT = "";

$STRACE = "";

$NONINTERACTIVE = 0; # if set to 1 noninteractive mode is activated

$pmesgfile = "";

if($runpram)
{
    if(!defined $ENV{'PRAM_DEV_PREFIX'})
    {
	die "Environment variable PRAM_DEV_PREFIX is not set\7\n";
    }

    if(!defined $ENV{'PRAM_CFG_FILE'})
    {
	die "Environment variable PRAM_CFG_FILE is not set\7\n";
    }

    open(AC, "<$ENV{'PRAM_CFG_FILE'}")
	|| die "cannot open $ENV{PRAM_CFG_FILE}\7\n";

    while(<AC>)
    {
	if(!(/^#/ || /^[ \t]*$/)) # skip comment lines and empty lines
	{
	    @_ = split /[ \t\n]+/;
	    if($_[0] eq "set" && $_[1] eq "num_of_pp")
	    {
		$PHYSNUM = $_[2];
	    }
	    if($_[0] eq "rng" && $_[1] eq "global")
	    {
		$MAX_GLOBAL_MEMSIZE = hex($_[4]);
	    }
	}
    }
    close AC;

    if(!defined $PHYSNUM)
    {
	die "Couldn`t get PHYSNUM/num_of_pp from $ENV{PRAM_CFG_FILE}\7\n";
    }
    $MAX_PHYSNUM = $PHYSNUM;
    if($VERBOSE) {print "Got $PHYSNUM pPs\n";}
}

# Pfade Simulator und Hostprogramm

$PRAMOS_FILE     = $PRAM_LIB_DIR."pramos/".$PRAMOS_VERSION."/pramos_pram";
$PRAMOS_COD_FILE = $PRAMOS_FILE.".cod";

$PRAMOS_KSHBRK_SIZE_BASE = 512*1024; # gemessen: 88071
$PRAMOS_KSHBRK_SIZE_VP   =   2*1024+$SYSTEM_STACK_SIZE; # gemessen:  1098
$PRAMOS_KSHBRK_SIZE_PP   =  10*1024; # gemessen:   112

$PRAMOS_KSHBRK_SIZE_LOCATION = 0xe; # adress in global PRAM memory where the
				    # size of the global kernel kshbrk is
				    # stored for PRAMOS

$PRAMOS_IOCPNUM_LOCATION = 0xf;    # adress in global PRAM memory where the
				   # number of io-copy-processors is stored
				   # for PRAMOS

#$GLOBAL_MEMSIZE        = 0x1200000; this is calculated now
$GLOBAL_MEMSIZE_LOCATION = 0xd; # adress in global PRAM memory where the
                                # size of the global PRAM memory is
                                # stored for PRAMOS
$LOCAL_MEMSIZE   = 0x20000;     # 128 kWord local memory
$PROGRAM_MEMSIZE = 0x80000;     # 512 kWord program memory
$PROGRAM_MEMSIZE_LOCATION = 0x13; # adress in global PRAM memory where the
                                # size of the PRAM program memory is
                                # stored for PRAMOS


$PRAMOS_GETTIMEOFDAY_HI_LOCATION = 17; # adress in global PRAM memory where the
$PRAMOS_GETTIMEOFDAY_LO_LOCATION = 18; # 64 bit microsecond offset for the
                                       # calculation of the gettimeofday()
                                       # value is stored for PRAMOS

$PRAMOS_PROGRAM_TERMINATION_INDICATOR_LOCATION = 20;
$PRAMOS_SYSTEM_STACK_SIZE_LOCATION = 21;

$SR_TMPDIR =$TMPDIR."simpram_runpram-".$$."/";
mkdir($SR_TMPDIR, 0755) || die "Cant create directory $SR_TMPDIR\7\n";

if($simpram)
{
    $DEVICE_PREFIX = $SR_TMPDIR;
}

if($runpram)
{
    $DEVICE_PREFIX = $ENV{'PRAM_DEV_PREFIX'};
}

if($VERBOSE){print "DEVICE_PREFIX = $DEVICE_PREFIX\n";}

$PRAM_DEVICE_SUFFIX = "glmem";
$PROG_DEVICE_SUFFIX = "prgmem";
$PRAM_DEVICE = $DEVICE_PREFIX.$PRAM_DEVICE_SUFFIX;
$PROG_DEVICE = $DEVICE_PREFIX.$PROG_DEVICE_SUFFIX;
$INTS_DEVICE = $DEVICE_PREFIX."extint";
$CONTROL_DEVICE = $DEVICE_PREFIX."control";

$ACCESS_CFG = $DEVICE_PREFIX."access.cfg";
$HOST_LOADERRC  = $SR_TMPDIR."ldrc";
$HOST_LOADEROUT = $SR_TMPDIR."codfile";

#
# Usage- and Help-Functions
#

sub usage
{
    print "$_[0]\7\n";
    print "help with $0 -help\n";
    exit 1;
}

sub help
{
    printf("usage: $0 [options] coff-file args-for-pram-program\n");
    printf("  -sheap    %-10d\t\t".
	   "shared heap used by shmalloc()\n", $sheap);
    printf("  -pstack   %-10d\t\t".
	   "private stack\n", $pstack);
    printf("  -pheap    %-10d\t\t".
	   "private heap used by malloc()\n", $pheap);
    printf("  -physnum  %-10d\t\t".
	   "number of physical processors (pPs) ".
	   "(1..$MAX_PHYSNUM)\n", $PHYSNUM);
    printf("  -virtnum  %-10d\t\t".
	   "number of virtual processors per pP ".
	   "(1..$MAX_VIRTNUM) \n".
	   "                      \t\t".
	   "(without serviceprocessor)\n", $VIRTNUM_USER);
    printf("  -procs    %-3d %-2d    \t\t".
	   "-physnum and -virtnum combined\n", $PHYSNUM, $VIRTNUM_USER);
    if($runpram)
    {
	printf("  -vpperpp  <#vp per pp>\t".
	       "number of vps per pp (8, 16, 24 or 32)\n".
	       "\t\t\t\t(currently set to $VPPERPP)\n");
	printf("  -hash <hashfactor>\t".
	       "hashfactor\n".
	       "\t\t\t\t(currently set to $HASH_FACTOR)\n");
    }
    printf("  -iocpnum  %-10d\t\t".
	   "number of io-copy-processors per pP (1..$MAX_IOCPNUM) \n",
	   $IOCPNUM);
    if($runpram)
    {
	printf("  -jtagnet <jtagnet-params>\t".
	       "parameter fr jtagnet\n".
	       "\t\t\t\t(currently set to $JTAGNET_PARAMS)\n");
    }
    if($simpram)
    {
	printf("  -pramsim  <pramsim-file>\t".
	       "path of PRAM-simulator\n".
	       "\t\t\t\t(currently set to $PRAMSIM)\n");
    }
    printf("  -pramosfile <pramos-file>\t".
	   "path of PRAMOS-File\n".
	   "\t\t\t\t(currently set to $PRAMOS_FILE)\n");
    printf("  -host_etc_path <path>\t".
	   "etc/-path for host\n".
	   "\t\t\t\t(currently set to $HOST_ETC_PATH)\n");
    printf("  -host_logfile <logfile>\t".
	   "name of logfile for host-output\n".
	   "\t\t\t\t(logging is only enabeled in interactive mode)\n");
    printf("  -host_module_path <path>\t".
	   "location of host modules\n".
	   "\t\t\t\t(currently set to $HOST_MODULE_PATH)\n");
    if($simpram)
    {
	printf("  -simopt  \"%-10s\"\t".
	       "simulator options (MUST BE QUOTED!)\n",
	       $PRAMSIM_OPT ? "$PRAMSIM_OPT" : "<pramsim options>");
    }
    if($runpram)
    {
	printf("  -pramtoolopt \"%-10s\"\t".
	       "pramtool options (MUST BE QUOTED!)\n",
	       $PRAMTOOL_OPT ? "$PRAMTOOL_OPT" : "<pramtool options>");
    }
    if($simpram)
    {
	printf("  -simoutfile <simout-file>\t".
	       "file to which simulator output is redirected\n".
	       "\t\t\t\tin noninteractive mode\n".
	       "\t\t\t\t(currently set to $PRAMSIM_OUTFILE)\n");
    }
    if($simpram)
    {
	printf("  -trace   <filename prefix>\t".
	       "output trace-files %s\n",
	       $TRACE_OUTPUT ? "to $TRACE_OUTPUT.*" : "(not specified)");
    }
    printf("  -tmpdir <filename>\t\t".
	   "directory for temporary files\n".
	   "\t\t\t\t(currently set to $TMPDIR)\n");
    if($simpram)
    {
	printf("  -renice  <niceinc>\t\t".
	       "increment nice level of simulation by <niceinc>\n".
	       "\t\t\t\t(niceinc %s)\n",
	       defined($nicelevel)?"set to $nicelevel":"not set");
    }
    if($simpram)
    {
	printf("  -str           \t\t".
	       "strace simulator (switched %s)\n", $STRACE ? "on" : "off");
    }
    printf("  -pmesg <file>\t\t\tsave pmesg output in <file>\n");
    printf("  -noninteractive\t\tstart in non-interactive mode\n");
    printf("  -verbose\t\t\tshow some additional output\n");
    printf("  -version\t\t\t$SIMPRAM_RUNPRAM_VERSION_LONG\n");
    printf("  -help\t\t\t\tshow this message\n");
    printf("The shown values are default values possibly changed by your options\n");
    exit 0;
}

#
# Signal Handler for proper Cleanup
#

sub cleanup
{
    if($NONINTERACTIVE)
    {
        if($bgproc_pid != 0)
	{
	    kill -2, $bgproc_pid; # kill host process directly
	}
    }
    else
    {
        if($bgproc_pid != 0)
	{
	    kill 9, $bgproc_pid; # kill xterm in which the host process is running
	}
    }

    if($simpram)
    {
	unlink $PRAM_DEVICE, $PROG_DEVICE, $INTS_DEVICE, $CONTROL_DEVICE;
	unlink $ACCESS_CFG;
    }

    unlink $HOST_LOADERRC, $OBJFILE_TMP;

    rmdir $SR_TMPDIR;
    unlink substr($SR_TMPDIR, 0, -1)."_owned_by";
}

$SIG{'INT'} = 'cleanup';
$SIG{'__DIE__'} = 'cleanup';

#
# Process command-line arguments
#

$all_args_processed = 0;
 PROCESS_ARGS:
    while($#ARGV >= 0 && !$all_args_processed)
    {
	if($ARGV[0] eq "-sheap")
	{shift; $sheap = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-pstack")
	{shift; $pstack = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-pheap")
	{shift; $pheap = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-physnum")
	{shift; $PHYSNUM = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-virtnum")
	{shift; $VIRTNUM_USER = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-procs")
	{shift; $PHYSNUM = shift; $VIRTNUM_USER = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-vpperpp" && $runpram)
	{shift; $VPPERPP = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-hash" && $runpram)
	{shift; $HASH_FACTOR = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-iocpnum")
	{shift; $IOCPNUM = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-jtagnet" && $runpram)
	{shift; $JTAGNET_PARAMS = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-pramsim" && $simpram)
	{shift; $PRAMSIM = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-pramosfile")
	{shift; $PRAMOS_FILE = shift; $PRAMOS_COD_FILE = $PRAMOS_FILE.".cod";
	 next PROCESS_ARGS;}
	if($ARGV[0] eq "-host_etc_path")
	{shift; $HOST_ETC_PATH = shift()."/"; next PROCESS_ARGS;}
	if($ARGV[0] eq "-host_logfile")
	{shift; $ENV{'HOST_LOGFILE'} = shift()."/"; next PROCESS_ARGS;}
	if($ARGV[0] eq "-host_module_path")
	{shift; $HOST_MODULE_PATH = shift()."/"; next PROCESS_ARGS;}
	if($ARGV[0] eq "-trace" && $simpram)
	{shift; $TRACE_OUTPUT=shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-str" && $simpram)
	{shift; $STRACE="truss"; next PROCESS_ARGS;}
	if($ARGV[0] eq "-simopt" && $simpram)
	{shift; $PRAMSIM_OPT=" ".shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-pramtoolopt" && $runpram)
	{shift; $PRAMTOOL_OPT=" ".shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-simoutfile" && $simpram)
	{shift; $PRAMSIM_OUTFILE = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-pmesg")
	{shift; $pmesgfile = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-tmpdir")
	{shift; $TMPDIR = shift; next PROCESS_ARGS;}
	if($ARGV[0] eq "-renice" && $simpram)
	{
	    shift; $nicelevel = shift;
	    $run="/usr/ucb/renice +$nicelevel $$ 2>1 1> /dev/null";
	    if($VERBOSE){print "$$ $run"};
	    system $run;
	    next PROCESS_ARGS;
	}
	if($ARGV[0] eq "-noninteractive")
	{shift; $NONINTERACTIVE=1; next PROCESS_ARGS;}
	if($ARGV[0] eq "-verbose")
	{shift; $VERBOSE=1; next PROCESS_ARGS;}
	if($ARGV[0] eq "-version")
	{print "$SIMPRAM_RUNPRAM_VERSION_LONG\n"; exit 0;}
	if($ARGV[0] eq "-help")
	{&help;}
	if($ARGV[0] =~ /-.*/)
	{&usage("Unknown option $ARGV[0]");shift;}
	$all_args_processed = 1;
    }

if($#ARGV < 0)
{
    &usage("You could at least specify a coff-file");
}

if(!$NONINTERACTIVE && $PRAMSIM_OUTFILE ne $PRAMSIM_OUTFILE_DEFAULT)
{
    printf("Option \"-simoutfile\" has no effect in interactive mode".
	    " - ignoring option\7\n");
    $PRAMSIM_OUTFILE = $PRAMSIM_OUTFILE_DEFAULT;
}

if($NONINTERACTIVE && defined($ENV{'HOST_LOGFILE'}))
{
    printf("Option \"-host_logfile\" has no effect in noninteractive mode".
	    " - ignoring option\7\n");
}

if($PHYSNUM > $MAX_PHYSNUM || $PHYSNUM < 1)
{
    &usage("physnum out of range (1..$MAX_PHYSNUM)");
}

if($VIRTNUM_USER > $MAX_VIRTNUM || $VIRTNUM_USER < 1)
{
    &usage("virtnum out of range (1..$MAX_VIRTNUM)");
}

if($runpram
   && $VPPERPP != 8 && $VPPERPP != 16 && $VPPERPP != 24 &&$VPPERPP != 32)
{
    &usage("wrong number of vp per pp (must be one of 8, 16, 24 or 32)");
}

if($IOCPNUM > $MAX_IOCPNUM || $IOCPNUM < 0)
{
    &usage("iocpnum out of range (0..$MAX_IOCPNUM)");
}

if($VIRTNUM_USER+$IOCPNUM > $MAX_VIRTNUM)
{
    &usage("virtnum + iocpnum must not exceed $MAX_VIRTNUM");
}

if($JTAGNET_PARAMS eq "0")
{
    $JTAGNET_PARAMS = $PHYSNUM;
}

$VIRTNUM_TOTAL = $VIRTNUM_USER    # total number of vP per pP - we need one
                 + $IOCPNUM       # more than the user (for the PRAMOS
                 + 1;             # service-processor)

$OBJFILE=$ARGV[0];
if(!-e $OBJFILE){ die "File $OBJFILE doesn't exist\7\n"};

$OBJFILE_TMP = $SR_TMPDIR."obj";

if($OBJFILE =~ /.*\.gz/)
{
    if($VERBOSE){printf("unzipping $OBJFILE\n")};
    system "gunzip --to-stdout $OBJFILE >$OBJFILE_TMP";
    $OBJFILE=$OBJFILE_TMP;
}

if($VERBOSE){print "Using $TMPDIR as \"device\"-file directory\n"};

#
# Calculate the size of the total amount of global (shared) memory
#

# Determine data segment sizes of the program that is to be simulated

open(OBJDUMP, "$PRAM_BIN_DIR/objdump --header $OBJFILE|");

 SECTION_SIZES:
    while(<OBJDUMP>)
    {
	if(/\.gpbss/)
	{
	    ($d1, $d2, $pbss) = split;
	    next SECTION_SIZES;
	}
	if(/\.gpdata/)
	{
	    ($d1, $d2, $pdata) = split;
	    next SECTION_SIZES;
	}
	if(/\.gsbss/)
	{
	    ($d1, $d2, $sbss) = split;
	    next SECTION_SIZES;
	}
	if(/\.gsdata/)
	{
	    ($d1, $d2, $sdata) = split;
	    next SECTION_SIZES;
	}
    }
close(OBJDUMP);

$pbss  = (hex $pbss )/4;
$pdata = (hex $pdata)/4;
$sbss  = (hex $sbss )/4;
$sdata = (hex $sdata)/4;

if($VERBOSE){printf "gpbss length  = %d word\n", $pbss };
if($VERBOSE){printf "gpdata length = %d word\n", $pdata};
if($VERBOSE){printf "gsbss length  = %d word\n", $sbss };
if($VERBOSE){printf "gsdata length = %d word\n", $sdata};

$private = $pheap + $pstack + $pdata + $pbss + $pargs;
$shared  = $sdata + $sbss + $sheap + $lddata;

$procnum = $PHYSNUM * $VIRTNUM_USER;

$GLOBAL_MEMSIZE = $private * $procnum + $shared;

if($VERBOSE){print "section private shared\n"};
if($VERBOSE){print "lddata	$lddata\n"};
if($VERBOSE){print "stack	$pstack\n"};
if($VERBOSE){print "heap	$pheap	$sheap\n"};
if($VERBOSE){print "data	$pdata	$sdata\n"};
if($VERBOSE){print "bss	$pbss	$sbss\n"};
if($VERBOSE){print "args	$pargs\n"};
if($VERBOSE){print "       ----------------\n"};
if($VERBOSE){print "$procnum *	$private +	"
		     ."$shared = $GLOBAL_MEMSIZE Words\n"};

if($procnum == 1)
{
    # If we run the program on one vP an additional amount of memory is
    # needed to ensure correct copying of the private segments at program
    # startup

    $additional = $pdata + $pbss + $pargs;
    $GLOBAL_MEMSIZE += $additional;

    if($VERBOSE)
    {
	print "Using only one processor. Additional $additional bytes.\n";
    }

    print "\n";
}

#
# Determine data segment sizes of PRAMOS
#

open(OBJDUMP, "$PRAM_BIN_DIR/objdump --header $PRAMOS_FILE|");

 SECTION_SIZES:
    while(<OBJDUMP>)
    {
	if(/\.gpbss/)
	{
	    ($d1, $d2, $pramos_pbss) = split;
	    next SECTION_SIZES;
	}
	if(/\.gpdata/)
	{
	    ($d1, $d2, $pramos_pdata) = split;
	    next SECTION_SIZES;
	}
	if(/\.gsbss/)
	{
	    ($d1, $d2, $pramos_sbss) = split;
	    next SECTION_SIZES;
	}
	if(/\.gsdata/)
	{
	    ($d1, $d2, $pramos_sdata) = split;
	    next SECTION_SIZES;
	}
	if(/\.pbsdat/)
	{
	    ($d1, $d2, $pramos_pbsdat) = split;
	    next SECTION_SIZES;
	}
    }

close(OBJDUMP);

$pramos_pbss   = (hex $pramos_pbss )/4; # THIS SHOULD ALWAYS BE 0
$pramos_pdata  = (hex $pramos_pdata)/4; # THIS SHOULD ALWAYS BE 0
$pramos_sbss   = (hex $pramos_sbss )/4;
$pramos_sdata  = (hex $pramos_sdata)/4;
$pramos_pbsdat = (hex $pramos_pbsdat)/4;

$pramos_kshbrk_size = $PRAMOS_KSHBRK_SIZE_BASE
    + $PHYSNUM * ($PRAMOS_KSHBRK_SIZE_PP
		  + $VIRTNUM_TOTAL * $PRAMOS_KSHBRK_SIZE_VP);

if($VERBOSE){printf "PRAMOS-gpbss length  = %d\n", $pramos_pbss};
if($VERBOSE){printf "PRAMOS-gpdata length = %d\n", $pramos_pdata};
if($VERBOSE){printf "PRAMOS-gsbss length  = %d\n", $pramos_sbss};
if($VERBOSE){printf "PRAMOS-gsdata length = %d\n", $pramos_sdata};
if($VERBOSE){printf "PRAMOS-pbsdat length = %d\n", $pramos_pbsdat};
if($VERBOSE){printf "PRAMOS-kshbrk length = %d\n", $pramos_kshbrk_size};

$GLOBAL_MEMSIZE += $pramos_pbss + $pramos_pdata
                + $pramos_sbss + $pramos_sdata
                + $pramos_pbsdat
                + $pramos_kshbrk_size;

# Round the size of the global memory to a 64K border

$GLOBAL_MEMSIZE = (($GLOBAL_MEMSIZE+0x1ffff) & 0xffff0000);

if($runpram && $GLOBAL_MEMSIZE > $MAX_GLOBAL_MEMSIZE)
{
    die "Not enough memory $GLOBAL_MEMSIZE > $MAX_GLOBAL_MEMSIZE";
}

#
# Generate config file for access-lib
#

if($simpram)
{
    if($VERBOSE){printf("Generating access.cfg file $ACCESS_CFG")};

    $ENV{'PRAM_DEV_PREFIX'} = $DEVICE_PREFIX;
    $ENV{'PRAM_CFG_FILE'} = $ACCESS_CFG;

    open(AC, ">$ACCESS_CFG") || die "couldn't create file $ACCESS_CFG";
    print AC
	"rng global $PRAM_DEVICE_SUFFIX 0 $GLOBAL_MEMSIZE 0 0 0\n"
	."rng program $PROG_DEVICE_SUFFIX 0 $PROGRAM_MEMSIZE 0 0 1\n"
	."set num_of_pp $PHYSNUM\n"
	."set version sim\n"
	."set sleep 100\n";
    close AC;
    open(AC, ">$CONTROL_DEVICE")
	|| die "cannot create fake control device";
    close AC;
}

#
# Set up variables etc. for Host-Program Startup
#

if($VERBOSE){printf("Generating loaderc-file ...\n")};

if(-e $HOST_LOADERRC)
{
    die "File $HOST_LOADERRC exists - please remove or rename it\7\n";
}

open(HLDR, ">$HOST_LOADERRC") || die "Couldn't create file $HOST_LOADERRC";

printf HLDR "sctdata          \n";
printf HLDR "{                \n";
printf HLDR "  org *          \n";
printf HLDR "  .lddata     S  \n";
printf HLDR "  .gsdata     S  \n";
printf HLDR "  .gsbss      S  \n";
printf HLDR "  org 0xc0000000 \n";
printf HLDR "  .gpdata     P  \n";
printf HLDR "  .gpbss      P  \n";
printf HLDR "  .args       P  \n";
printf HLDR "}                \n";
printf HLDR "lddata           \n";
printf HLDR "{                \n";
printf HLDR "  procs    %8d N \n", $VIRTNUM_USER*$PHYSNUM;
printf HLDR "  textlen  %8d T \n", 0;
printf HLDR "  pstack   %8d P \n", $pstack;
printf HLDR "  pheap    %8d P \n", $pheap;
printf HLDR "  sheap    %8d S \n", $sheap;
printf HLDR "}                     \n";

close HLDR;

$HOST             = $HOST_MODULE_PATH."pramos_host";
$START_HOST       = $PRAM_LIB_DIR."simpram/".$SIMPRAM_RUNPRAM_VERSION."/simpram_runpram_host";

$ENV{'HOST'} = $HOST;
$ENV{'HOST_LOADERRC'}  = $HOST_LOADERRC;
$ENV{'HOST_LOADEROUT'} = $HOST_LOADEROUT;

$ENV{'PROGRAM'} = join(" ", @ARGV);

$ENV{'SBP_HOSTETCPATH'}    = $HOST_ETC_PATH;
$ENV{'SBP_HOSTMODULEPATH'} = $HOST_MODULE_PATH;
$ENV{'SBP_HOSTRC'}         = $HOST_ETC_PATH."hostrc";
$ENV{'SBP_HOSTMODULEFILE'} = $HOST_ETC_PATH."host_modules";
$ENV{'SBP_LOADER'}         = "host-loader";
$ENV{'SBP_PRAMOS_ISSUE'}   = $HOST_ETC_PATH."issue";
$ENV{'SBP_PRAMOS_MOTD'}    = $HOST_ETC_PATH."motd";
$ENV{'SBP_HOSTRC'}         = ".hostrc.dummy";

#
# Set up variables etc. for Host-Program Startup
#

($GTODUS_HI, $GTODUS_LO) =  split(/ /, `$GTODUS_PROG`);

if($VERBOSE){print("gettimofday_offset_hi = $GTODUS_HI\n".
		   "gettimofday_offset_lo = $GTODUS_LO\n");};

if($simpram)
{
    $pramsim_run = "exec $TIME $STRACE $PRAMSIM ".
		       "--no-rc-file           ".
		       "--net-datatest         ".
		       "--net-op-test	       ".
		       "-M $GLOBAL_MEMSIZE     ".
		       "-P $PROGRAM_MEMSIZE    ".
		       "-L $LOCAL_MEMSIZE      ".
		       "-p $PHYSNUM            ".
		       "-v $VIRTNUM_TOTAL      ".
		       "-l 1		       ".
		       "-i		       ".
		       "--set global-devname $PRAM_DEVICE ".
		       "--set   prog-devname $PROG_DEVICE ".
		       "--set   ints-devname $INTS_DEVICE ".
		       "--set file $OBJFILE   ".
		       "--set pramos-file $PRAMOS_FILE ".
		       "--init-string \"f $GLOBAL_MEMSIZE_LOCATION $GLOBAL_MEMSIZE, ".
				       "f $PROGRAM_MEMSIZE_LOCATION $PROGRAM_MEMSIZE, ".
				       "f $PRAMOS_KSHBRK_SIZE_LOCATION $pramos_kshbrk_size, ".
				       "f $PRAMOS_SYSTEM_STACK_SIZE_LOCATION $SYSTEM_STACK_SIZE, \n".

				       "f $PRAMOS_IOCPNUM_LOCATION $IOCPNUM, ".
				       "f $PRAMOS_GETTIMEOFDAY_HI_LOCATION $GTODUS_HI, ".
				       "f $PRAMOS_GETTIMEOFDAY_LO_LOCATION $GTODUS_LO, ".
				       "g".
				       "\"".
		       ($TRACE_OUTPUT?" --trace $TRACE_OUTPUT":"").
		       "$PRAMSIM_OPT".
		       " $PRAMOS_COD_FILE";

    if($VERBOSE) {print($pramsim_run);};
}

if($runpram)
{
    $pramtool_run = "$TIME $STRACE $PRAMTOOL ";
}

#
# Start the whole thing up
#

#if($runpram)
if(0)
{
    @pwent = getpwuid($>); # $> holds the effective user id

    if($pwent[0] ne "pram")
    {
	die "runpram can only be run by the SB-PRAM administrator\7\n";
    }
}

$ENV{NONINTERACTIVE} = $NONINTERACTIVE;

print "Starting up Host ...\n";

unless($bgproc_pid = fork)
{
    if($VERBOSE){print "bgproc_pid = $bgproc_pid\n"}

    $title = $OBJFILE."-Host";

    if($VERBOSE){print "HOST       = $HOST\n"};
    if($VERBOSE){print "START_HOST = $START_HOST\n"};

    if($NONINTERACTIVE)
    {
	 exec "$START_HOST";
    }
    else
    {
	 exec "xterm -sl 3000 -title $title -name simpram_host -e $START_HOST";
    }
}

if($simpram)
{
    print "Starting up Simulator ...\n";
    if($VERBOSE){print "$pramsim_run\n";};

#    printf "%s", "]2;".$OBJFILE."-Simulator";
                                    # This sets the title in the xterm
    if($NONINTERACTIVE)
    {
	close(STDIN); # to stop the simulator after having executed the program
	open(STDOUT, ">".$PRAMSIM_OUTFILE)
	    || die "Couldn't open file $PRAMSIM_OUTFILE";;
	open(STDERR, ">&STDOUT");
    }

    system $pramsim_run;
}
elsif($runpram)
{
    $pmesg = "";
    if($pmesgfile ne "")
    {
	$pmesg = "!pmesg >".$pmesgfile."&\n";
    }
    if($VERBOSE){print "pmesg: $pmesg"};

    print "Starting up pramtool ...\n";
    if($NONINTERACTIVE)
    {
	close(STDIN); # to stop the simulator after having executed the program
#	open(STDOUT, ">".$PRAMSIM_OUTFILE)
#	    || die "Couldn't open file $PRAMSIM_OUTFILE";;
	open(STDERR, ">&STDOUT");
    }
    $run_jtagnet = "$JTAGNET_COMMAND $JTAGNET_PARAMS";

    print "$run_jtagnet\n";

    system($run_jtagnet);

    open(PRAMTOOL, "| $pramtool_run") || die("Can't execute $pramtool_run\7\n");
    printf PRAMTOOL
	"reset\n"
	."noupload_start\n"
	."sethash $HASH_FACTOR\n"
	."f g:12 0\n"
	."cpulist *\n"
	."upload $PRAMOS_COD_FILE\n"
#	."cpulist $PHYSNUM-%d\n"
#	."upload $DUMMY_COD_FILE\n"
	."cpulist *\n"
	."f g:0 $HASH_FACTOR\n"
	."f g:$GLOBAL_MEMSIZE_LOCATION $GLOBAL_MEMSIZE\n"
	."f g:$PRAMOS_KSHBRK_SIZE_LOCATION $pramos_kshbrk_size\n"
	."f g:$PRAMOS_SYSTEM_STACK_SIZE_LOCATION $SYSTEM_STACK_SIZE\n"
	."settime g:$PRAMOS_GETTIMEOFDAY_HI_LOCATION\n"
	."f g:10 %d\n"
#	."f g:0x502 0x30\n"
	."m g:0-0x20\n"
	."default_mem fpga\n"
	."reset 2\n"
	."f e*:8 3\n"
#	."f e*:2 0x81\n"
	."f 4 0\n"
	."default_mem global\n"
	."m g:0-0x20\n"
	.$pmesg
	."waitfor g:$PRAMOS_PROGRAM_TERMINATION_INDICATOR_LOCATION 1\n",
#	$MAX_PHYSNUM - 1,
	(($VPPERPP&8)<<18)|(($VPPERPP&16)<<16);
    close PRAMTOOL;
}
else
{
    fprintf stderr "Ooops, neither \$simpram nor \$runpram are set\n";
    exit(1);
}

#
# Termination
#

sleep 3;

&cleanup;

exit 0;
