#!/usr/bin/env python

#######################################################################################
#   file   : tsarmap
#   date   : april 2014
#   author : Alain Greiner
#######################################################################################
# This generic script maps one or several multi-tasks applications on a specific 
# instance of the multi-processors/multi-clusters TSAR architecture. 
#
# It generates the files required for hardware and software compilation:
#
# 1) The "hard_config.h" file is used to generate the top.cppnetbsd file (hardware),
#    and to compile the tsar_preloader.elf, the GietVM boot.elf and kernel.elf files.
#
# 2) The optionals "map.bin" and vsegs.ld" files are used to configure the GietVM.
#
# 3) The optional "netbsd.dts" file can be used to configure NetBSD.
#
# 4) The optional "arch.bib" file can be used to configure ALMOS.
#
# 5) An optional "map.xml" file can be generated for debug. 
#######################################################################################
# The hardware parameters  are:
#  - x_size    : number of clusters in a row
#  - y_size    : number of clusters in a column
#  - nprocs    : number of processors per cluster
#######################################################################################
# The supported platforms are:
# - tsar_generic_iob
# - tsar_generic_leti
#######################################################################################
# The supported parallel applications are:
# - sort (one thread per processor)
# - transpose (one thread per processor)
#######################################################################################

from optparse import OptionParser

from mapping import *

from transpose import *
from sort import *

import sys

######################################################################################
#   define command line arguments   
######################################################################################

parser = OptionParser()

parser.add_option( '--arch', type = 'string', dest = 'arch_path',
                   help = 'define pathname to architecture' )

parser.add_option( '--x', type = 'int', dest = 'x_size', 
                   default = 2,
                   help = 'define number of clusters in a row' )

parser.add_option( '--y', type = 'int', dest = 'y_size', 
                   default = 2,
                   help = 'define number of clusters in a column' )

parser.add_option( '--p', type = 'int', dest = 'nprocs', 
                   default = 2,
                   help = 'define number of processors per cluster' )

parser.add_option( '--v', action = 'store_true', dest = 'verbose',
                   default = False,
                   help = 'display detailed report on map.bin file generation' )

parser.add_option( '--netbsd', type = 'string', dest = 'netbsd_path', 
                   help = 'define pathname for the netbsd.dts file' )

parser.add_option( '--almos', type = 'string', dest = 'almos_path', 
                   help = 'define pathname for the arch.bib file' )

parser.add_option( '--giet', type = 'string', dest = 'giet_path', 
                   help = 'define pathname for the map.bin & vsegs.ld file ' )

parser.add_option( '--xml', type = 'string', dest = 'xml_path', 
                   help = 'define pathname for the map.xml file' )

############  supported applications   ###############################################

parser.add_option( '--transpose', action = 'store_true', dest = 'transpose',
                   default = False,
                   help = 'map the "transpose" application for the GIET' )

parser.add_option( '--sort', action = 'store_true', dest = 'sort',     
                   default = False,
                   help = 'map the "sort" application for the GIET' )

######################################################################################
#   Get command line arguments
######################################################################################

(options,args) = parser.parse_args()

x_size        = options.x_size      # number of clusters in a row
y_size        = options.y_size      # number of clusters in a column
nprocs        = options.nprocs      # number of processors in a cluster

verbose       = options.verbose     # report on map.bin generation if True

netbsd_path   = options.netbsd_path # path for netbsd.dts file 
almos_path    = options.almos_path  # path for arch.bib file
giet_path     = options.giet_path   # path for map.bin & vsegs.ld files

arch_path     = options.arch_path   # path to selected architecture

xml_path      = options.xml_path    # path for map.xml file     

map_transpose = options.transpose   # map "sort" application if True
map_sort      = options.sort        # map "transpose" application if True

######################################################################################
#   build empty platform (no applications yet)
######################################################################################

if   ( arch_path == None  ):  
    print 'You must select a generic architecture on the command line' 
    sys.exit(1)

# dynamically append the architecture to PYTHON path (directory pathname)
sys.path.append( arch_path )

# dynamically import the PYTHON mapping generator module (file name)
select = __import__( 'genmap' )

# build mapping calling the function (function name)
mapping = select.genmap( x_size, y_size, nprocs )
print '[tsarmap] platform %s build' % mapping.name 

# generate the hard_confi.h file for top.cpp compilation
pathname = arch_path + '/hard_config.h'
f = open ( pathname, 'w' )
f.write( mapping.hard_config() )
print '[tsarmap] %s generated' % pathname

######################################################################################
#   complete mapping with application(s) as required
######################################################################################

if ( map_transpose ): 
    transpose( mapping )
    print '[tsarmap] application "transpose" loaded'

if ( map_sort ):      
    sort( mapping )
    print '[tsarmap] application "sort" loaded'

######################################################################################
#   Generate xml file if required.
#   It can be used for debug.
######################################################################################

if ( xml_path != None ):
    pathname = xml_path + '/map.xml'
    f = open ( pathname, 'w' )
    f.write( mapping.xml() )
    print '[tsarmap] %s generated for debug' % pathname

######################################################################################
#   Generate netbsd.dts file if required.
#   It is used for NetBSD configuration.
######################################################################################

if ( (netbsd_path != None) and (arch_path != None) ):
    pathname = netbsd_path + '/netbsd.dts'
    f = open ( pathname, 'w' )
    f.write( mapping.netbsd_dts() )
    print '[tsarmap] %s generated for netbsd' % pathname

######################################################################################
#   Generate arch.bib file if required.
#   It is used for ALMOS configuration.
######################################################################################

if ( (almos_path != None) and (arch_path != None) ):
    pathname = almos_path + '/arch.info'
    f = open ( pathname, 'w' )
    f.write( mapping.almos_arch() )
    print '[tsarmap] %s generated for almos' % pathname

######################################################################################
#   Generate map.bin, giet_vsegs.ld, and hard_config.h files if required.
#   They are used for GietVM compilation and configuration.
######################################################################################

if ( (giet_path != None) and (arch_path != None) ):

    pathname = giet_path + '/map.bin'
    f = open ( pathname, 'w' )
    f.write( str( mapping.cbin( verbose ) ) )
    print '[tsarmap] %s generated for giet_vm' % pathname

    pathname = giet_path + '/hard_config.h'
    f = open ( pathname, 'w' )
    f.write( mapping.hard_config() )
    print '[tsarmap] %s generated for giet_vm' % pathname

    pathname = giet_path + '/giet_vsegs.ld'
    f = open ( pathname, 'w' )
    f.write( mapping.giet_vsegs() )
    print '[tsarmap] %s generated for giet_vm' % pathname

