#!/usr/bin/python
# @date   22 September, 2014
# @author cfuguet <cesar.fuguet-tortolero@lip6.fr>

import os
import subprocess
import arch
import faultyprocs
import argparse

# get command-line arguments
parser = argparse.ArgumentParser(description = 'Run simulation')

parser.add_argument(
    type = str, dest = 'path',
    help = 'relative or absolute path to the platform')

parser.add_argument(
    '--output', '-o', type = str, dest = 'outpath', default = './output',
    help = 'relative or absolute path to the output directory')

parser.add_argument(
    '--xsize', '-x', type = int, dest = 'x', default = 2,
    help = '# of clusters in a row')

parser.add_argument(
    '--ysize', '-y', type = int, dest = 'y', default = 2,
    help = '# of clusters in a column')

parser.add_argument(
    '--nprocs', '-n', type = int, dest = 'nprocs', default = 4,
    help = '# of processors per cluster')

parser.add_argument(
    '--quiet', '-q', type = bool, dest = 'quiet', default = False,
    help = 'be quiet!!!' )

args = parser.parse_args()

# faulty processor list
faultylist = [(0,0,1), (0,0,2), (0,1,2)]

# translate the relative path (if needed) into an absolute path
basedir = os.path.abspath(args.path)
outdir = os.path.abspath(args.outpath)
print "[ run.py ] platform base directory: {0}".format(basedir)
print "[ run.py ] output directory: {0}".format(outdir)

# 1. generate configuration and ouput directories
try:
    os.makedirs(os.path.join(outdir, "config"), 0755)
except OSError:
    pass # directory already exists => do nothing

# 2. generate hard_config.h and fault_config.h files
faultpath = os.path.join(outdir, "config/fault_config.h")
hardpath = os.path.join(outdir, "config/hard_config.h")
xmlpath = os.path.join(outdir, "config/map.xml")
arch.main(args.x, args.y, args.nprocs, hardpath, xmlpath)
faultyprocs.generate(faultylist, faultpath)

# create a log file
logfile = open(os.path.join(outdir, "log"), "w")

# 3. compile simulator executable
dst = os.path.join(basedir, "hard_config.h")
if os.path.lexists(dst): os.unlink(dst)
os.symlink(hardpath, dst)

print "[ run.py ] compiling simulator"
command = []
command.extend(['make'])
command.extend(['-C', basedir])
subprocess.call(command, stdout=logfile, stderr=logfile)

# 4. compile distributed boot executable
dst = os.path.join(outdir, "config/boot_config.h")
if os.path.lexists(dst): os.unlink(dst)
os.symlink(os.path.join(basedir, "soft/config/boot_config.h"), dst)

print "[ run.py ] compiling distributed boot procedure"
command = []
command.extend(['make'])
command.extend(['-C', os.path.join(basedir, "soft")])
command.extend(["CONFDIR=" + outdir])
subprocess.call(command, stdout=logfile, stderr=logfile)

# 5. execute simulator
os.environ["DISTRIBUTED_BOOT"] = "1"
if args.quiet: os.environ["SOCLIB_TTY"] = "FILES"

if (args.x * args.y) <= 4:
    ompthreads = args.x * args.y
elif (args.x * args.y) <= 16:
    ompthreads = 4
else:
    ompthreads = 8

print "[ run.py ] starting simulation"
command = []
command.extend([os.path.join(basedir, "simul.x")])
command.extend(["-SOFT", os.path.join(basedir, "soft/build/soft.elf")])
command.extend(["-DISK", "/dev/null"])
command.extend(["-THREADS", str(ompthreads)])
command.extend(["-NCYCLES", "1000000"])
subprocess.call(command, stdout=logfile, stderr=logfile)

logfile.close()

# 6. move simulation terminal output into the target config dir
os.rename("term0", os.path.join(outdir, "term"))

# vim: tabstop=4 : softtabstop=4 : shiftwidth=4 : expandtab
