#!/usr/bin/python

################################################################################
##
## The script is part of the SPEC and SVEC PTS. It is used to generate SDBFS
## image that is then stored in Flash or EEPROM memory. The image contains MAC
## address and optionally also an FPGA bitstream. The main purpose of including
## it to the PTS is to allow manufacturers assigning official MAC addresses to
## SPEC and SVEC boards.
##
## Copyright (C) 2017 CERN (www.cern.ch)
## Author: Grzegorz Daniluk <grzegorz.daniluk@cern.ch>
##
################################################################################

import sys
import re
import subprocess
import os
import shutil

#class CSDBGenerator :
SDBFS_MAC  = "{path}sdbfs-{type}/mac-address"
SDBFS_BSTR = "{path}sdbfs-{type}/bitstream"
SDBFS_IMG  = "{path}sdbfs-{type}-{mac}.bin"
GEN_SPEC_CMD = "{path}./gensdbfs -b 65536 {path}sdbfs-spec {img}"
GEN_SVEC_CMD = "{path}./gensdbfs -b 262144 {path}sdbfs-svec {img}"


###########################################################
def check_mac(mac):
    if not re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", mac.lower()):
        print "Not a valid MAC address"
        return 0

    return 1

###########################################################

# type can be either "spec" or "svec"
def gen_sdb_image(type, mac, bstr, output=None):

    if mac and not check_mac(mac):
        return 

    # Translate MAC to be always in XX-XX-XX-XX-XX-XX format
    mac = mac.replace(':', '-')
    # Get the absolute path where this script resides. This lets us have always
    # access to the sdbfs-spec/svec structure, no matter where this script is
    # called.
    abs_path = os.path.dirname(os.path.abspath(__file__)) + '/'

    # 1. write MAC address to the file in SDBFS
    mac_bytes = [int(i, 16) for i in mac.split('-')]
    sdbfs_mac = SDBFS_MAC.format(path=abs_path, type=type)
    f = open(sdbfs_mac, 'wb')
    f.truncate()
    for byte in mac_bytes:
        f.write(chr(byte))
    f.close()

    # 2. copy bitstream to SDBFS, if needed
    sdbfs_bstr = SDBFS_BSTR.format(path=abs_path, type=type) #<abs_path>/sdbfs-<type>/bitstream
    if bstr:
        print "Including bitstream " + bstr
        shutil.copy(bstr, sdbfs_bstr)
    else:
        #truncate bitstream file if not given
        f = open(sdbfs_bstr, 'wb')
        f.truncate()
        f.close()

    # 3. generate SDBFS image
    sdbfs_img = SDBFS_IMG.format(path=abs_path, type=type, mac=mac)
    # gensdbfs for spec/svec
    if type == "spec":
        cmd = GEN_SPEC_CMD.format(path=abs_path, img=sdbfs_img)
    else:
        cmd = GEN_SVEC_CMD.format(path=abs_path, img=sdbfs_img)
    subprocess.Popen(cmd, shell=True).wait()
    print "Generated " + sdbfs_img
    # 4. Copy generated SDBFS image to <output>
    if output:
        shutil.copy(sdbfs_img, output)
        print "Generated image (" + sdbfs_img + ") copied to " + output

###########################################################
if __name__ == "__main__":
    if len(sys.argv) < 3:
        print "Wrong syntax"
        print sys.argv[0] + " <spec/svec> <mac> [bitstream]"
        sys.exit()
    
    type = sys.argv[1]
    if type != "spec" and type != "svec":
        print "Wrong syntax"
        print sys.argv[0] + " <spec/svec> <mac> [bitstream]"
        sys.exit()
    
    #mac = check_mac(sys.argv[2])
    mac = sys.argv[2]
    
    if len(sys.argv) > 3:
        bitstream = sys.argv[3]
    else:
        bitstream = ""
    
    gen_sdb_image(type, mac, bitstream)
