def generateVerilog(bitwidth, treetype):
    verilog_file = open("Adder.v", "w")
    verilog_file.write("module prefixadder( \n")
    verilog_file.write("input  [%s : 0] A,\n" % (bitwidth - 1))
    verilog_file.write("input  [%s : 0] B, \n" % (bitwidth - 1))
    verilog_file.write("output  [%s : 0] Sum, \n" % (bitwidth - 1))
    verilog_file.write("output  Cout, \n")
    verilog_file.write("output  [%s : 0] Cg); \n" % (bitwidth - 1))
    #from AdderTree import StructureTree;

    Tree = StructureTree(bitwidth, 0, treetype)
    Depth = len(Tree)
    verilog_file.write("wire [%s : 0] p; \n" % (bitwidth - 1))
    verilog_file.write("wire [%s : 0] g; \n" % (bitwidth - 1))
    for pi in range(0, bitwidth):
        verilog_file.write("assign p[{0}] = A[{0}] ^ B[{0}]; \n".format(pi))
        verilog_file.write("assign g[{0}] = A[{0}] & B[{0}]; \n".format(pi))

    for i in range(0, Depth):
        for j in range(0, bitwidth):
            verilog_file.write("wire cp{0}[{1}],cg{0}[{1}];\n".format(i, j))

    verilog_file.close()
def SimulateAdder(n):
    from AdderTree import StructureTree
    Tree = StructureTree(n, 0, 1)

    pgsstats = [[0] * n for i in range(len(Tree) + 1)]
    pngsstats = [[0] * n for i in range(len(Tree) + 1)]
    for index1 in range(0, len(pngsstats)):
        for index2 in range(0, len(pngsstats[index1])):
            pngsstats[index1][index2] = [0, 0]

    xrand = np.random.normal(128, 10, 2**n)
    yrand = np.random.normal(128, 10, 2**n)

    for x in range(1, 2**n):
        #x = 2**(n-2)
        #if (x>0):
        for y in range(1, 2**n):
            #sum = x + y
            #xbin = bin(x)
            #ybin = bin(y)
            #xbin = '{0:08b}'.format(int(xrand[x]))
            #ybin = '{0:08b}'.format(int(yrand[y]))
            xbin = format(x, '016b')
            ybin = format(y, '016b')
            A = [int(xbin[i]) for i in range(0, n)]
            B = [int(ybin[i]) for i in range(0, n)]
            #A = xbin[0:];
            #B = ybin[0:];
            p = []
            g = []
            for i in range(0, n):
                p.append(0)
                g.append(0)
                #p=[];
                #g=[];
                #print(p);
                #print('A =')
                #print(A)
                #print ('B =')
                #print(B)
                p[i] = A[i] or B[i]
                g[i] = A[i] and B[i]
            #print ('p =')
            #print (p);
            #print('\n');
            #print('g =')
            #print(g);
            #print('\n');
            Depth = 2 * int(math.log2(n)) - 1
            pgs = InterpretAdderTree(Tree, n, Depth, p, g)
            #print(pgs);
            for z in range(0, len(pgs)):
                #print('pgs '+str(z)+'=')
                #print(pgs[z]);
                for zz in range(0, len(pgs[z])):
                    if (z > 0):
                        if pgs[z][zz] != pgs[z - 1][zz]:
                            #print(z,zz)
                            pgsstats[z][zz] += 1
            for z1 in range(0, len(pgs)):
                #print('pgs '+str(z)+'=')
                #print(pgs[z]);
                for zz1 in range(0, len(pgs[z1])):
                    if (z1 > 0):
                        if pgs[z1][zz1][0] != pgs[z1 - 1][zz1][0]:
                            #print(z,zz)
                            pngsstats[z1][zz1][0] += 1
                        if pgs[z1][zz1][1] != pgs[z1 - 1][zz1][1]:
                            #print(z,zz)
                            pngsstats[z1][zz1][1] += 1
def SimulateAdderFilter(n, adder, filter):
    from AdderTree import StructureTree
    Tree = StructureTree(n, 0, adder)
    # use function to get tree delay for each bit
    # use function to get tree unit count
    # use function to estimate power
    TreeD = TreeDelay(Tree, 5, 1)
    TreeS = TreeSize(Tree, 5, 1)
    TreeP = TreePower(Tree, 5, 1)
    TempP = [0 for x in range(len(Tree))]
    for i in range(0, len(Tree)):
        TempP[i] = math.fsum(TreeP[i])
    TotalP = math.fsum(TempP)
    print('Delay')
    print(TreeD)
    print('Power')
    print(TreeP)
    print(TotalP)
    print('Size')
    print(TreeS)
    from Filter_Image import LoadImageData
    sobelx = [[1, 0, -1], [2, 0, -2], [1, 0, -1]]
    sobely = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]]
    Filter = sobelx
    FilterName = 'Sobel'
    if (filter == 1):
        Filter = sobelx
        FilterName = 'Sobel'
    elif (filter == 2):
        Filter = [[0, 1, 0], [1, -4, 1], [0, 1, 0]]
        FilterName = 'Edge Detection I'
    elif (filter == 3):
        Filter = [[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]
        FilterName = 'Edge Detection II'
    elif (filter == 4):
        Filter = [[0, -1, 0], [-1, 5, -1], [0, -1, 0]]
        FilterName = 'Sharpen'
    elif (filter == 5):
        Filter = [[1 / 9, 1 / 9, 1 / 9], [1 / 9, 1 / 9, 1 / 9],
                  [1 / 9, 1 / 9, 1 / 9]]
        FilterName = 'Box Blur'
    elif (filter == 6):
        Filter = [[1 / 16, 2 / 16, 1 / 16], [2 / 16, 4 / 16, 2 / 16],
                  [1 / 16, 2 / 16, 1 / 16]]
        FilterName = 'Gaussian Blur'

    addarray = LoadImageData(Filter)
    pgsstats = [[0] * n for i in range(len(Tree) + 1)]
    pngsstats = [[0] * n for i in range(len(Tree) + 1)]
    for index1 in range(0, len(pngsstats)):
        for index2 in range(0, len(pngsstats[index1])):
            pngsstats[index1][index2] = [0, 0]
    psgs = [[0] * 3 for i in range(n)]
    xrand = np.random.normal(128, 10, 2**n)
    yrand = np.random.normal(128, 10, 2**n)
    xx2_grid = [(x, x2) for x in range(0, len(addarray))
                for x2 in range(0, len(addarray[0]))]
    for x, x2 in (xx2_grid):
        # x = 2**(n-2)
        # if (x>0):
        if (addarray[x][x2][0]) < 0:
            temp = addarray[x][x2][0] + 2**n
            xbin = format(int(temp), '016b')
            sum = int(temp)
        else:
            xbin = format(int(addarray[x][x2][0]), '016b')
            sum = int(addarray[x][x2][0])
        for y in range(1, len(addarray[x][x2]) - 1):
            # sum = x + y
            # xbin = bin(x)
            # ybin = bin(y)
            # xbin = '{0:08b}'.format(int(xrand[x]))
            # ybin = '{0:08b}'.format(int(yrand[y]))
            added = int(addarray[x][x2][y])
            if added < 0:
                temp = added + 2**n
                ybin = format(int(temp), '016b')
            else:
                ybin = format(int(added), '016b')
            A = [int(xbin[i]) for i in range(0, n)]
            B = [int(ybin[i]) for i in range(0, n)]
            # A = xbin[0:];
            # B = ybin[0:];
            p = []
            g = []

            for i in range(0, n):
                p.append(0)
                g.append(0)
                # p=[];
                # g=[];
                # print(p);
                # print('A =')
                # print(A)
                # print ('B =')
                # print(B)
                p[i] = A[i] or B[i]
                g[i] = A[i] and B[i]
                if p[i] == 1:
                    psgs[i][0] = psgs[i][0] + 1
                if g[i] == 1:
                    psgs[i][1] = psgs[i][1] + 1
                psgs[i][2] += 1
                ## Test Vectors
                #p = [1,1,0,0,0,1,1,1,0,1,0,0,0,0,1,1]
                #g = [0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0]
                ###
            # print ('p =')
            # print (p);
            # print('\n');
            # print('g =')
            # print(g);
            # print('\n');
            #Depth = 2 * int(math.log2(n)) - 1
            Depth = len(Tree)
            pgs = InterpretAdderTree(Tree, n, Depth, p, g)
            # print(pgs);
            for z in range(0, len(pgs)):
                # print('pgs '+str(z)+'=')
                # print(pgs[z]);
                for zz in range(0, len(pgs[z])):
                    if (z > 0):
                        if pgs[z][zz] != pgs[z - 1][zz]:
                            # print(z,zz)
                            pgsstats[z][zz] += 1
            for z1 in range(0, len(pgs)):
                # print('pgs '+str(z)+'=')
                # print(pgs[z]);
                for zz1 in range(0, len(pgs[z1])):
                    if (z1 > 0):
                        if pgs[z1][zz1][0] != pgs[z1 - 1][zz1][0]:
                            # print(z,zz)
                            pngsstats[z1][zz1][0] += 1
                        if pgs[z1][zz1][1] != pgs[z1 - 1][zz1][1]:
                            # print(z,zz)
                            pngsstats[z1][zz1][1] += 1
            sum = sum + added
            if sum < 0:
                temp = sum + 2**n
                xbin = format(temp, '016b')
            else:
                xbin = format(sum, '016b')
    #print('Stats')
    #print(pgsstats)
    pgstatsArray = np.array(pgsstats)
    pngstatsArray = np.array(pngsstats)
    #print(pgstatsArray)
    #print('P and G stats')
    pngstatsArray = pngstatsArray / (62 * 62 * 27)
    #print(pngstatsArray)
    Results = open(r"results7.txt", "a")
    Results.write('#######################################')
    Results.write('\n\n')

    AdderName = ''
    if (adder == 1):
        AdderName = 'Brent Kung'
    elif (adder == 2):
        AdderName = 'Han Carlson'
    elif (adder == 3):
        AdderName = 'Sklansky'
    elif (adder == 4):
        AdderName = 'Knowles'
    elif (adder == 5):
        AdderName = 'KoggeStone'
    elif (adder == 6):
        AdderName = 'Ladner Fischer'
    Results.write('This is  the results from %a for %a Adder' %
                  (FilterName, AdderName))
    Results.write('\n\n')
    for line in range(0, len(pngstatsArray)):
        Results.write(str(pngstatsArray[line]))
        Results.write('\n')

    Results.write('Tree Delay \n')
    Results.write(str(TreeD))
    Results.write('\n\n')
    Results.write('Tree Size' + str(TreeS))
    Results.write('\n\n')
    Results.write('Tree Power' + str(TotalP))
    Results.write('\n\n')
    Results.write(str(TreeP))
    return pngsstats, psgs