#--------------------------------------------------------------------
# File      : gen_arch_info_large.sh
#--------------------------------------------------------------------

import getpass
import socket
import time
import sys

X_MAX = 0
Y_MAX = 0
CPU_PER_CLUSTER = 0
BSCPU = 0
BSTTY = 0
BSDMA = 0
MEMC_SIZE = 0
P_WDITH = 4
NB_TTY = 4
TTY_CHANNEL_SIZE = 0X00000010
TTY_SIZE = 0X00001000
OUTPUT_IRQ_PER_PROC = 4
DMA_SIZE = 0X00001000
XCU_SIZE = 0X00001000
BDV_SIZE = 0X00001000
FBF_SIZE = 0X00200000

MEMC_TGTID = 0
XICU_TGTID = 1
MDMA_TGTID = 2
MTTY_TGTID = 3
BDEV_TGTID = 4
MNIC_TGTID = 5
BROM_TGTID = 6
CDMA_TGTID = 7
SIMH_TGTID = 8
FBUF_TGTID = 9


# PHYSICAL ADDRESS WIDTH
ADDR_WIDTH = 32

# DEFAULT VALUES
DEFAULT_X_MAX = 8
DEFAULT_Y_MAX = 8
DEFAULT_CPU_PER_CLUSTER = 4
CLUSTER_INC = 0

def print_comments(cmd):
        print "# TSAR hardware description in BIB (Boot Information Block) format"
        print "# This file is autogenerated by the command: " + cmd +  " %d %d %d %d" % (X_MAX, Y_MAX, CPU_PER_CLUSTER, BSCPU)
        print "# It is ready to be passed to info2bib utility so the binary format can be generated"
        print " "
        print "# " + getpass.getuser() + " on " + socket.gethostname() + " " + time.strftime("%H:%M:%S")
        print " "
        print " "
        
def print_header():
        print "[HEADER]"
        print "        REVISION=1"
        print "        ARCH=SOCLIB-TSAR"
        print "        XMAX=%d" % X_MAX 
        print "        YMAX=%d" % Y_MAX
        print "        BSCPU=%d" % BSCPU
        print "        BSTTY=0x%x" % BSTTY
        print "        BSDMA=0x%x" % BSDMA
        print " "
        print " "

def print_cluster(offset, cid):
        mem_base = offset
        mem_size = MEMC_SIZE
        xcu_base = (offset + (CLUSTER_INC / 2) + (XICU_TGTID << 19))
        dma_base = (offset + (CLUSTER_INC / 2) + (MDMA_TGTID << 19))
        print "[CLUSTER]"
        cpu_num=0;
        while (cpu_num != CPU_PER_CLUSTER):
                gid = (cid << CPU_PER_CLUSTER) + cpu_num
                print "        [CPU]    ID=%d OUTIRQ=%d" % (gid, (cpu_num * OUTPUT_IRQ_PER_PROC)) 
                cpu_num = cpu_num + 1
        
        print "        [DEV]    ID=RAM       BASE=%#.8x    SIZE=%#.8x    IRQ=-1    IRQTYPE=NONE" % (mem_base, mem_size)
        print "        [DEV]    ID=XICU      BASE=%#.8x    SIZE=%#.8x    IRQ=-1    IRQTYPE=NONE" % (xcu_base, DMA_SIZE)
        print "        [DEV]    ID=DMA       BASE=%#.8x    SIZE=%#.8x    IRQ=8     IRQTYPE=HWI"  % (dma_base, XCU_SIZE)
        print " "
        print " "

def print_io_cluster(offset, cid):
        mem_base = offset
        mem_size = MEMC_SIZE
        xcu_base = (offset + (CLUSTER_INC / 2) + (XICU_TGTID << 19))
        dma_base = (offset + (CLUSTER_INC / 2) + (MDMA_TGTID << 19))
        bdv_base = (offset + (CLUSTER_INC / 2) + (BDEV_TGTID << 19))
        tty_base = (offset + (CLUSTER_INC / 2) + (MTTY_TGTID << 19))
        fbf_base = (offset + (CLUSTER_INC / 2) + (FBUF_TGTID << 19))
        
        print "[CLUSTER]"
        cpu_num = 0
        while (cpu_num != CPU_PER_CLUSTER):
                gid = (cid << CPU_PER_CLUSTER) + cpu_num
                print "        [CPU]    ID=%d OUTIRQ=%d" % (gid, (cpu_num * OUTPUT_IRQ_PER_PROC)) 
                cpu_num = cpu_num + 1
        
        print "        [DEV]    ID=RAM       BASE=%#.8x    SIZE=%#.8x    IRQ=-1    IRQTYPE=NONE" % (mem_base, mem_size)
        print "        [DEV]    ID=XICU      BASE=%#.8x    SIZE=%#.8x    IRQ=-1    IRQTYPE=NONE" % (xcu_base, XCU_SIZE)
        print "        [DEV]    ID=DMA       BASE=%#.8x    SIZE=%#.8x    IRQ=8     IRQTYPE=HWI"  % (dma_base, DMA_SIZE)
        print "        [DEV]    ID=BLKDEV    BASE=%#.8x    SIZE=%#.8x    IRQ=31    IRQTYPE=HWI"  % (bdv_base, BDV_SIZE)
        ntty = 0
        irq = 16
        while (ntty < NB_TTY):
                tty_base_i = tty_base + ntty * TTY_CHANNEL_SIZE
                print "        [DEV]    ID=TTY       BASE=%#.8x    SIZE=%#.8x    IRQ=%d    IRQTYPE=HWI" % (tty_base_i, TTY_CHANNEL_SIZE, irq)
                irq = irq + 1
                ntty = ntty + 1
        print "        [DEV]    ID=FB        BASE=%#.8x    SIZE=%#.8x    IRQ=-1    IRQTYPE=NONE" % (fbf_base, FBF_SIZE)
        print " "
        print " "

def gen_arch_info(x, y, x_width, y_width, bscpu, arch_info_name):
        fp = open(arch_info_name, 'w')
        stdout = sys.stdout
        sys.stdout = fp
        global X_MAX
        global Y_MAX
        global CPU_PER_CLUSTER
        global CLUSTER_INC
        global MEMC_SIZE
        global BSCPU
        global BSDMA
        global BSTTY
        
        #------------------------
        
        X_MAX = x
        Y_MAX = y
        cpu_per_cluster = DEFAULT_CPU_PER_CLUSTER
        CPU_PER_CLUSTER = cpu_per_cluster
        
        #------------------------
        CLUSTER_INC = (0x80000000 >> (x_width + y_width)) * 2
        max_memc_size = 0x40000000 / (X_MAX * Y_MAX)
        size = min(max_memc_size, 0x10000000)
        MEMC_SIZE = size

        ##########################################################################################
        #we force io_cid to 0 because this is the only cluster we know which will be present 
        #in all platform where the number of clusters is independant of x_width and y_width values
        io_cid = 0 
        ##########################################################################################

        BSCPU = bscpu
        
        break_loop = 0
        xi = 0
        yi = 0
        while (xi < X_MAX):
                while (yi < Y_MAX):
                        cid = xi * (1 << y_width) + yi
                        offset = cid << (ADDR_WIDTH - x_width - y_width)
                        if cid == io_cid:
                                BSDMA = offset + (CLUSTER_INC / 2) + (MDMA_TGTID << 19)
                                BSTTY = offset + (CLUSTER_INC / 2) + (MTTY_TGTID << 19)
                                break_loop = 1
                                break
                        else:
                                bsdma="error"
                        yi = yi + 1

                if break_loop == 1:
                        break
                yi = 0
                xi = xi + 1
        
        # Generate the description
        print_comments(sys.argv[0])
        print_header()
        
        xi = 0
        yi = 0
        while (xi < X_MAX):
                while (yi < Y_MAX):
                        cid = xi * (1 << y_width) + yi
                        offset = cid  << (ADDR_WIDTH - (x_width + y_width))
                        if cid == io_cid:
                                print_io_cluster(offset, cid)
                        else:
                                print_cluster(offset, cid)
                        yi = yi + 1
                yi = 0
                xi = xi + 1
        sys.stdout = stdout
        fp.close()

