#!/usr/bin/env python

##########################################################################################
#  File   : genarch.py
#  Date   : 2016
#  Author : Alain Greiner
#  Copyright (c)  UPMC Sorbonne Universites
#########################################################################################
# This python script generates the "arch_info.bin" file required by the ALMOS-MK
# operating system bootloader and describing the target hardware architecture.
# It uses an architecture specific, python script that must be called "arch_info.py".
#
# The source directory containing the "arch_info.py" file and the destination directory
# to store the "arch_info.bin" file are defined by parameters on the command line:
#  --arch=string     : path to directory containing the "arch_info.py" file
#  --bin=string      : path to directory store the "arch_info.bin" file
#
# As the target architecture is generic, the following hardware parameters can be
# defined on the command line:
#  --x_size=int      : number of clusters in a row
#  --y_size=int      : number of clusters in a column
#  --nb_cores=int    : number of cores per cluster
#  --nb_ttys=int     : number of TTY channels 
#  --nb_nics=int     : number of NIC channels 
#  --fbf_size=int    : frame buffer width & heigth
#  --ioc_type=string : can be IOC_BDV , IOC_HBA , IOC_SDC , IOC_SPI
#
# The following parameters can be used to generate the optional "hard_config.h" file,
# that is required to configurate the SystemC virtual prototype, and the "arch_info.xml" 
# file for debug.
#  --hard=string     : path to directory to store the "hard_config.h" file
#  --xml=string      : path to directory to store the "arch_info.xml" file
#
#########################################################################################

import sys

from arch_classes import *
from optparse import OptionParser

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

parser = OptionParser()

parser.add_option( '--arch', type = 'string', dest = 'arch_path',
                   help = 'define pathname to directory containing arch_info.py file' )

parser.add_option( '--bin', type = 'string', dest = 'bin_path',
                   help = 'define pathname to directory to store arch_info.bin file' )

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

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

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

parser.add_option( '--nb_ttys', type = 'int', dest = 'nb_ttys', 
                   default = 1,
                   help = 'define number of TTY channels' )

parser.add_option( '--nb_nics', type = 'int', dest = 'nb_nics',
                   default = 1,
                   help = 'define number ot NIC channels' )

parser.add_option( '--fbf_size', type = 'int', dest = 'fbf_size', 
                   default = 128,
                   help = 'define frame buffer width and heigth' )

parser.add_option( '--ioc_type', type = 'string', dest = 'ioc_type',
                   default = 'IOC_BDV',
                   help = 'define type of IOC: BDV / HBA / SDC / RDK / SPI' )

parser.add_option( '--sys_clk', type = 'int', dest = 'sys_clk', 
                   default = 25000,
                   help = 'define system clock frequency (25MHz for FPGA, 600MHz for TSARLET)' )

parser.add_option( '--segs_set', type = 'string', dest = 'segs_set',
                   default = 'SIMU',
                   help = 'define which set of base addresses to use (may differ between simulation and real machine' )

parser.add_option( '--hard', type = 'string', dest = 'hard_path',
                   help = 'define pathname to directory for the hard_config.h file ' )

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

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

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

(options,args) = parser.parse_args()

arch_path      = options.arch_path   # path to arch_info.py file
bin_path       = options.bin_path    # path for arch_info.bin file

x_size         = options.x_size      # number of clusters in a row
y_size         = options.y_size      # number of clusters in a column
nb_cores       = options.nb_cores    # number of cores in a cluster
nb_ttys        = options.nb_ttys     # number of TTY channels           
fbf_size       = options.fbf_size    # frame buffer width & heigth
nb_nics        = options.nb_nics     # number of NIC channels           
ioc_type       = options.ioc_type    # ioc controller type
sys_clk        = options.sys_clk     # system clock frequency in kHz
segs_set       = options.segs_set    # Set of base addresses used (simu or real)

hard_path      = options.hard_path   # path for hard_config.h file
xml_path       = options.xml_path    # path for arch_info.xml file     

verbose        = options.verbose     # report on arch_info.bin generation


###################################################################################
#   Build the archinfo structure for the selected arch_info.py
###################################################################################

if   ( arch_path == None  ):  
    print 'You must define a path to the arch_info.py file on command line' 
    sys.exit(1)

# dynamically append arch_path to PYTHONPATH
sys.path.append( arch_path )

# import the arch_info.py module (using file name without suffix)
select = __import__( 'arch_info' )
print select

# build the arch_info structure by calling the arch function
archinfo = select.arch( x_size,
                        y_size, 
                        nb_cores,
                        nb_ttys, 
                        nb_nics, 
                        fbf_size, 
                        ioc_type,
                        segs_set )

print '[genarch] archinfo build for %s' % archinfo.name 

###################################################################################
#   Generate arch_info.xml file if required.
###################################################################################

if ( xml_path != None ):
    pathname = xml_path + '/arch_info.xml'
    f = open ( pathname, 'w' )
    f.write( archinfo.xml() )

    print '[genarch] %s generated' % pathname

###################################################################################
#   Generate arch_info.bin file if required.
###################################################################################

if ( bin_path != None ):
    pathname = bin_path + '/arch_info.bin'
    f = open ( pathname, 'wb' )
    f.write( archinfo.cbin( verbose ) )
    print '[genarch] %s generated' % pathname

###################################################################################
#   Generate hard_config.h file if required.
###################################################################################

if ( hard_path != None ):

    pathname = hard_path + '/hard_config.h'
    f = open ( pathname, 'w' )
    f.write( archinfo.hard_config( ioc_type, sys_clk ) )
    print '[genarch] %s generated' % pathname

