import json
import os
from utils import util

# Break frames into WORD_SIZE bit words.
WORD_SIZE_BITS = 32

# How many 32-bit words for frame in a 7-series bitstream?
FRAME_WORD_COUNT = 101

# What alignment is expect for columns.
FRAME_ALIGNMENT = 0x80
'''
Sample:
bit_0002000f_079_06

Where:
-0002000f: FDRI address
-079: FDIR word number (0-100)
-06: bit index (0-31)
'''


def load_bitdata(f):
    """ Read bit file and return bitdata map.
    Similar to segbits file

    bitdata is a map of of two sets.
    The map key is the frame address.
    The first sets are the word columns that have any bits set.
    Word columsn are WORD_SIZE_BITS wide.
    The second sets are bit index within the frame and word if it is set.
    """
    bitdata = dict()

    for line in f:
        line = line.split("_")
        frame = int(line[1], 16)
        wordidx = int(line[2], 10)
        bitidx = int(line[3], 10)

        if frame not in bitdata:
            bitdata[frame] = set(), set()

        bitdata[frame][0].add(wordidx)
        bitdata[frame][1].add(wordidx * WORD_SIZE_BITS + bitidx)

    return bitdata


# used by segprint
# TODO: merge these
def load_bitdata2(f):
    '''
    return as bitdata[frame][wordidx].add(bitidx)
    ie indexed by frame, word index, and then a set with bit indexes
    Similar to .bits file: bit_00020012_014_20
    '''

    bitdata = dict()

    for lineraw in f:
        lineraw = lineraw.strip()
        line = lineraw.split("_")
        try:
            frame = int(line[1], 16)
            wordidx = int(line[2], 10)
            bitidx = int(line[3], 10)
        except:
            print("Invalid line %s" % lineraw)
            raise

        if frame not in bitdata:
            bitdata[frame] = dict()

        if wordidx not in bitdata[frame]:
            bitdata[frame][wordidx] = set()

        bitdata[frame][wordidx].add(bitidx)
    return bitdata


def gen_part_base_addrs():
    """
    Return (block_type, top_bottom, cfg_row, cfg_col, frame_count)
    Where:
    -block_type ("bus"): typically CLB_IO_CLK, sometimes BLOCK_RAM
    -top_bottom: either "top" or "bottom"
    -cfg_row: a relative row
    -cfg_col: a relative column
    -frame_count: number of frames to fully configure this minor address

    Example:
    ('CLB_IO_CLK', 'bottom', 0, 3, 36)
    ('BLOCK_RAM', 'top', 0, 1, 128)
    ('CLB_IO_CLK', 'top', 1, 34, 28)
    """
    fn = os.getenv("URAY_PART_YAML").replace(".yaml", ".json")
    j = json.load(open(fn, "r"))
    for tbk, tbv in j["global_clock_regions"].items():
        for rowk, rowv in tbv["rows"].items():
            for busk, busv in rowv["configuration_buses"].items():
                for colk, colv in busv["configuration_columns"].items():
                    yield (busk, tbk, int(rowk), int(colk),
                           colv["frame_count"])


def addr_bits2word(block_type, top_bottom, cfg_row, cfg_col, minor_addr):
    """Convert a deconstructed address to a 32 bit word"""
    # https://www.xilinx.com/support/documentation/user_guides/ug470_7Series_Config.pdf
    ret = 0
    ret |= util.block_type_s2i[block_type] << 23
    ret |= {"top": 0, "bottom": 1}[top_bottom] << 22
    ret |= cfg_row << 17
    ret |= cfg_col << 7
    ret |= minor_addr
    return ret
