#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017-2020  The Project X-Ray Authors.
#
# Use of this source code is governed by a ISC-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/ISC
#
# SPDX-License-Identifier: ISC
'''
Take raw .bits files and decode them to higher level functionality

A segment as currently used is defined as a tile type + a memory region
Ex: BRAM_L_X6Y100:CLB_IO_CLK
'''

import sys, os, json, re
import copy
from prjxray import bitstream
from prjxray import db as prjxraydb
from prjxray import util


class NoDB(Exception):
    pass


# cache
segbitsdb = dict()


# int and sites are loaded together so that bit coverage can be checked together
# however, as currently written, each segment is essentially printed twice
def process_db(db, tile_type, process, verbose):
    ttdb = db.get_tile_type(tile_type)

    fns = [ttdb.tile_dbs.segbits, ttdb.tile_dbs.ppips]
    verbose and print("process_db(%s): %s" % (tile_type, fns))
    for fn in fns:
        if fn:
            with open(fn, "r") as f:
                for line in f:
                    process(line)


def get_database(db, tile_type, bit_only=False, verbose=False):
    tags = list()

    if tile_type in segbitsdb:
        return segbitsdb[tile_type]

    def process(l):
        # l like: CLBLL_L.SLICEL_X0.AMUX.CY !30_07 !30_11 30_06 30_08
        # Parse tags to do math when multiple tiles share an address space
        parts = l.split()
        name = parts[0]

        if parts[1] == 'always' or parts[1] == 'hint' or parts[1] == 'default':
            if bit_only:
                return
            tagbits = []
        else:
            tagbits = [util.parse_tagbit(x) for x in parts[1:]]

        tags.append(list([name] + tagbits))

    process_db(db, tile_type, process, verbose=verbose)

    if len(tags) == 0:
        raise NoDB(tile_type)

    segbitsdb[tile_type] = tags
    return tags


def mk_segbits(seginfo, bitdata):
    '''
    Given a tile memory region (seginfo), return list of bits in that region

    seginfo: mk_segments()s object supplying address range
    bitdata: all bits in the entire bitstream
    '''

    segbits = set()

    block = seginfo["block"]
    baseaddr = int(block["baseaddr"], 0)
    frames = block["frames"]
    word_offset = block["offset"]
    words = block["words"]

    for frame in range(baseaddr, baseaddr + frames):
        if frame not in bitdata:
            continue
        for wordidx in range(word_offset, word_offset + words):
            if wordidx not in bitdata[frame]:
                continue
            for bitidx in bitdata[frame][wordidx]:
                frame_addr = frame - baseaddr
                bit_addr = 32 * (wordidx - word_offset) + bitidx
                #segbits.add( "%02d_%02d" % (frame_addr, word_addr))
                segbits.add((frame_addr, bit_addr))

    return segbits


def gen_tilegrid_masks(tiles):
    """yield (addr_min, addr_max + 1, word_min, word_max + 1)"""
    for tilek, tilev in tiles.items():
        for block_type, blockj in tilev["bits"].items():
            baseaddr = int(blockj["baseaddr"], 0)
            frames = blockj["frames"]
            offset = blockj["offset"]
            words = blockj["words"]
            yield (baseaddr, baseaddr + frames, offset, offset + words)


def print_unknown_bits(tiles, bitdata):
    '''
    Print bits not covered by known tiles

    tiles: tilegrid json
    bitdata[addr][word] = set of bit indices (0 to 31)
    '''
    # Start with an open set and remove elements as we find them
    tocheck = copy.deepcopy(bitdata)

    for addr_min, addr_max_p1, word_min, word_max_p1 in gen_tilegrid_masks(
            tiles):
        for addr in range(addr_min, addr_max_p1):
            if addr not in tocheck:
                continue
            for word in range(word_min, word_max_p1):
                if word not in tocheck[addr]:
                    continue
                del tocheck[addr][word]

    # print uncovered locations
    print('Non-database bits:')
    for frame in sorted(tocheck.keys()):
        for wordidx in sorted(tocheck[frame].keys()):
            for bitidx in sorted(tocheck[frame][wordidx]):
                print("bit_%08x_%03d_%02d" % (frame, wordidx, bitidx))


def tagmatch(entry, segbits):
    '''Does tag appear in segbits?'''

    # Entry like "CLBLL_L.SLICEL_X0.AMUX.CY !30_07 !30_11 30_06 30_08".split()
    for bit in entry[1:]:
        isset, bitaddr = bit

        # Reject if bit polarity is incorrect
        if bitaddr not in segbits if isset else bitaddr in segbits:
            return False
    return True


def tag_matched(entry, segbits):
    for bit in entry[1:]:
        isset, bitaddr = bit
        if isset:
            segbits.remove(bitaddr)


# tile types that failed to decode
decode_warnings = set()


def seg_decode(db, seginfo, segbits, segments, bit_only=False, verbose=False):
    '''
    Remove matched tags from segbits
    Returns a list of all matched tags
    '''

    segtags = set()

    # Valid addresses for refereced tiles
    ref_block = seginfo["block"]
    # ref_frame_as = (int(ref_block["baseaddr"], 0), int(ref_block["baseaddr"], 0) + ref_block["frames"] - 1)
    ref_frame_as = (0, ref_block["frames"] - 1)
    ref_bit_as = (
        32 * ref_block["offset"],
        32 * (ref_block["offset"] + ref_block["words"]) - 1)

    def process(cmp_seginfo, ref_tile_name):
        tile_type = cmp_seginfo["tile"]["type"]

        # already failed?
        if tile_type in decode_warnings:
            return

        try:
            entries = get_database(
                db, tile_type, bit_only=bit_only, verbose=verbose)
        except NoDB:
            verbose and print("WARNING: failed to load DB for %s" % tile_type)
            assert tile_type != 'BRAM_L'
            decode_warnings.add(tile_type)
            return

        cmp_block = cmp_seginfo["block"]
        ref_frame_delta = int(cmp_block["baseaddr"], 0) - int(
            ref_block["baseaddr"], 0)
        ref_bit_delta = 32 * (cmp_block["offset"] - ref_block["offset"])

        def adjust_entry_addr(entry):
            '''Return bits that apply to this tile at the correct address'''
            tagname = entry[0]
            bits = entry[1:]
            if len(bits) == 0:
                return None
            ret = [tagname]

            def adjust_entry():
                '''Adjust entry in another tile address space to be in our reference tile address space'''
                for isset, old_bitaddr, in bits:
                    old_frame_addr, old_bit_addr = old_bitaddr
                    new_frame_addr = old_frame_addr + ref_frame_delta
                    if not (ref_frame_as[0] <= new_frame_addr <=
                            ref_frame_as[1]):
                        verbose and print(
                            "out frame range: %d <= %d <= %d" %
                            (ref_frame_as[0], new_frame_addr, ref_frame_as[1]))
                        return False

                    new_bit_addr = old_bit_addr + ref_bit_delta
                    # Verify in range of original tile
                    # This can happen if a smaller tile references a larger tile
                    if not (ref_bit_as[0] <= new_bit_addr <= ref_bit_as[1]):
                        verbose and print(
                            "out bit range: %d <= %d <= %d" %
                            (ref_bit_as[0], new_bit_addr, ref_bit_as[1]))
                        return False
                    ret.append((isset, (new_frame_addr, new_bit_addr)))
                    verbose and print(
                        "ent %02d_%02d => %02d_%02d" % (
                            old_frame_addr, old_bit_addr, new_frame_addr,
                            new_bit_addr))
                return True

            if not adjust_entry():
                return None
            return ret

        for entry in entries:
            if ref_tile_name:
                entry = adjust_entry_addr(entry)
                if entry is None:
                    continue
                verbose and print('adjusted entry', entry)

            if not tagmatch(entry, segbits):
                continue
            tag_matched(entry, segbits)
            tagname = entry[0]
            # Prefix matches not from this tile
            if ref_tile_name:
                segtags.add('%s:%s' % (ref_tile_name, tagname))
            else:
                segtags.add(tagname)

    # Reference tile
    process(seginfo, None)
    # Tiles that share our address space
    for (ref_tile_name, cmp_block_name) in seginfo['segtiles']:
        process(
            segments[mksegment(ref_tile_name, cmp_block_name)], ref_tile_name)

    return segtags


def print_seg(
        segname, seginfo, nbits, segbits, segtags, decode_emit, verbose=False):
    '''Print segment like used by segmaker/segmatch'''

    print("seg %s" % (segname, ))
    if verbose:
        print("Bits: %s" % nbits)
        print(
            "Address: %s, +%s" %
            (seginfo["block"]["baseaddr"], seginfo["block"]["frames"]))
        print(
            "Words: %s, +%s" %
            (seginfo["block"]["offset"], seginfo["block"]["words"]))

    # Bits that weren't decoded
    for bit in sorted(segbits):
        print("bit %02d_%02d" % bit)

    if decode_emit:
        for tag in sorted(segtags):
            print("tag %s" % tag)


def handle_segment(
        db,
        segname,
        bitdata,
        decode_emit,
        decode_omit,
        omit_empty_segs,
        segments,
        bit_only=False,
        verbose=False):

    seginfo = segments[segname]

    segbits = mk_segbits(seginfo, bitdata)
    nbits = len(segbits)

    if decode_emit or decode_omit:
        segtags = seg_decode(
            db, seginfo, segbits, segments, bit_only=bit_only, verbose=verbose)
    else:
        segtags = set()

    # Found something to print?
    keep = not omit_empty_segs or len(segbits) > 0 or (
        len(segtags) > 0 and not decode_omit)
    if not keep:
        return

    print()
    print_seg(
        segname,
        seginfo,
        nbits,
        segbits,
        segtags,
        decode_emit,
        verbose=verbose)


def overlap(a, b):
    return a[0] <= b[0] <= a[1] or b[0] <= a[0] <= b[1]


def mk_segtiles(tiles):
    '''
    Return a dictionary of tile_name:tiles
    Where tiles is a list of tiles that are in our address space

    Assumption: tiles in the same minor address region have the same base address and number frames

    As DB is written, not all have the same number of frames
    Ex: CLBLM_R_X7Y108 36 frames, INT_R_X7Y108 28 frames
    We could check for this, but don't think its worth the effort
    Maybe this should be corrected in the DB?
    '''

    segtiles = {}

    # Group by base address
    baseaddrs = {}
    for tile_name, tile in tiles.items():
        for block_name, block in tile['bits'].items():
            baseaddrs.setdefault(block["baseaddr"], []).append(
                (block["offset"], tile_name, block, block_name))

    for baseaddr, values in baseaddrs.items():
        '''
        There are only 256 addresses per minor address
        Just do a set brute force search for now?
        Maybe too slow with the number of tiles

        Around 50 IP blocks max per minor address
        '''

        # Sort by block offset
        values = sorted(values)

        for refi, (_ref_block_offset, ref_tile_name, ref_block,
                   ref_block_name) in enumerate(values):
            seglets = segtiles.setdefault(ref_tile_name, [])
            ref_as = (
                ref_block["offset"],
                ref_block["offset"] + ref_block["words"] - 1)

            for cmpi in range(refi + 1, len(values)):
                (_cmp_block_offset, cmp_tile_name, cmp_block,
                 cmp_block_name) = values[cmpi]
                cmp_as = (
                    cmp_block["offset"],
                    cmp_block["offset"] + cmp_block["words"] - 1)

                if overlap(ref_as, cmp_as):
                    seglets.append((cmp_tile_name, cmp_block_name))
                # sorting => first non-intersection means no future will intersect
                else:
                    break

    return segtiles


def mk_segments(tiles):
    segments = {}
    segtiles = mk_segtiles(tiles)

    for tile_name, tile in tiles.items():
        for block_name, block in tile['bits'].items():
            segname = mksegment(tile_name, block_name)
            segments[segname] = {
                'tile': tile,
                'tile_name': tile_name,
                'block': block,
                'block_name': block_name,
                'segtiles': segtiles[tile_name],
            }
    return segments


def mksegment(tile_name, block_name):
    '''Create a segment name'''
    return '%s:%s' % (tile_name, block_name)


def tile_segnames(tiles):
    '''Create a list of all (tile_name, block_name) from input tiles'''
    ret = []
    for tile_name, tile in tiles.items():
        if 'bits' not in tile:
            continue

        for block_name in tile['bits'].keys():
            ret.append(mksegment(tile_name, block_name))
    return ret


def load_tiles(db_root, part):
    # TODO: Migrate to new tilegrid format via library.
    with open("%s/%s/tilegrid.json" % (db_root, part), "r") as f:
        tiles = json.load(f)
    return tiles


def run(
        db_root,
        part,
        bits_file,
        segnames,
        omit_empty_segs=False,
        flag_unknown_bits=False,
        flag_decode_emit=False,
        flag_decode_omit=False,
        bit_only=False,
        verbose=False):
    db = prjxraydb.Database(db_root, part)
    tiles = load_tiles(db_root, part)
    segments = mk_segments(tiles)
    bitdata = bitstream.load_bitdata2(open(bits_file, "r"))

    if flag_unknown_bits:
        print_unknown_bits(tiles, bitdata)
        print("")

    # Default: print all
    if segnames:
        for i, segname in enumerate(segnames):
            # Default to common tile config area if tile given without explicit block
            if ':' not in segname:
                segnames[i] = mksegment(segname, 'CLB_IO_CLK')
    else:
        segnames = sorted(tile_segnames(tiles))
    print('Segments: %u' % len(segnames))

    # XXX: previously this was sorted by address, not name
    # revisit?
    for segname in segnames:
        handle_segment(
            db,
            segname,
            bitdata,
            flag_decode_emit,
            flag_decode_omit,
            omit_empty_segs,
            segments,
            bit_only=bit_only,
            verbose=verbose)


def main():
    import argparse

    parser = argparse.ArgumentParser(
        description="Decode bits within a tile's address space")

    util.db_root_arg(parser)
    util.part_arg(parser)
    parser.add_argument('--verbose', action='store_true', help='')
    parser.add_argument(
        '-z',
        action='store_true',
        help="do not print a 'seg' header for empty segments")
    parser.add_argument(
        '-b', action='store_true', help='print bits outside of known segments')
    parser.add_argument(
        '-d',
        action='store_true',
        help='decode known segment bits and write them as tags')
    parser.add_argument(
        '-D',
        action='store_true',
        help='decode known segment bits and omit them in the output')
    parser.add_argument(
        '--bit-only',
        action='store_true',
        help='only decode real bitstream directives')
    parser.add_argument('bits_file', help='')
    parser.add_argument(
        'segnames', nargs='*', help='List of tile or tile:block to print')
    args = parser.parse_args()

    run(
        args.db_root,
        args.part,
        args.bits_file,
        args.segnames,
        args.z,
        args.b,
        args.d,
        args.D,
        bit_only=args.bit_only,
        verbose=args.verbose)


if __name__ == '__main__':
    main()
