#!/usr/bin/env python3
#
#  Copyright (C) 2015  Clifford Wolf <clifford@clifford.at>
#
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
#
#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

import icebox
from icebox import re_match_cached, re_search_cached
import getopt, sys, re

print_bits = False
print_map = False
single_tile = None
print_all = False

def usage():
    print("""
Usage: icebox_explain [options] [bitmap.asc]

    -b
        print config bit names for each config statement

    -m
        print tile config bitmaps

    -A
        don't skip uninteresting tiles

    -t '<x-coordinate> <y-coordinate>'
        print only the specified tile
""")
    sys.exit(0)

try:
    opts, args = getopt.getopt(sys.argv[1:], "bmAt:")
except:
    usage()

for o, a in opts:
    if o == "-b":
        print_bits = True
    elif o == "-m":
        print_map = True
    elif o == "-A":
        print_all = True
    elif o == "-t":
        single_tile = tuple([int(s) for s in a.split()])
    else:
        usage()

if len(args) == 0:
    args.append("/dev/stdin")

if len(args) != 1:
    usage()

print("Reading file '%s'.." % args[0])
ic = icebox.iceconfig()
ic.read_file(args[0])
print("Fabric size (without IO tiles): %d x %d" % (ic.max_x-1, ic.max_y-1))

def print_tile(stmt, ic, x, y, tile, db):
    if single_tile is not None and single_tile != (x, y):
        return

    bits = set()
    mapped_bits = set()
    for k, line in enumerate(tile):
        for i in range(len(line)):
            if line[i] == "1":
                bits.add("B%d[%d]" % (k, i))
            else:
                bits.add("!B%d[%d]" % (k, i))

    if re_search_cached(r"logic_tile", stmt):
        active_luts = set([i for i in range(8) if "1" in icebox.get_lutff_bits(tile, i)])

    text = set()
    used_lc = set()
    text_default_mask = 0
    for entry in db:
        if re_match_cached(r"LC_", entry[1]):
            continue
        if entry[1] in ("routing", "buffer"):
            if not ic.tile_has_net(x, y, entry[2]): continue
            if not ic.tile_has_net(x, y, entry[3]): continue
        match = True
        for bit in entry[0]:
            if not bit in bits:
                match = False
        if match:
            for bit in entry[0]:
                mapped_bits.add(bit)
            if entry[1] == "IoCtrl" and entry[2] == "IE_0":
                text_default_mask |= 1
            if entry[1] == "IoCtrl" and entry[2] == "IE_1":
                text_default_mask |= 2
            if entry[1] == "RamConfig" and entry[2] == "PowerUp":
                text_default_mask |= 4
            if print_bits:
                text.add("<%s> %s" % (" ".join(entry[0]), " ".join(entry[1:])))
            else:
                text.add(" ".join(entry[1:]))
    bitinfo = list()
    print_bitinfo = False
    for k, line in enumerate(tile):
        bitinfo.append("")
        extra_text = ""
        for i in range(len(line)):
            if 36 <= i <= 45 and re_search_cached(r"(logic_tile|dsp\d_tile|ipcon_tile)", stmt):
                lutff_idx = k // 2
                lutff_bitnum = (i-36) + 10*(k%2)
                if line[i] == "1":
                    used_lc.add(lutff_idx)
                    bitinfo[-1] += "*"
                else:
                    bitinfo[-1] += "-"
            elif line[i] == "1" and "B%d[%d]" % (k, i) not in mapped_bits:
                print_bitinfo = True
                extra_text += " B%d[%d]" % (k, i)
                bitinfo[-1] += "?"
            else:
                bitinfo[-1] += "+" if line[i] == "1" else "-"
        bitinfo[-1] += extra_text
    for lcidx in sorted(used_lc):
        lutff_options = "".join(icebox.get_lutff_seq_bits(tile, lcidx))
        if lutff_options[0] == "1": lutff_options += " CarryEnable"
        if lutff_options[1] == "1": lutff_options += " DffEnable"
        if lutff_options[2] == "1": lutff_options += " Set_NoReset"
        if lutff_options[3] == "1": lutff_options += " AsyncSetReset"
        text.add("LC_%d %s %s" % (lcidx, "".join(icebox.get_lutff_lut_bits(tile, lcidx)), lutff_options))
    if not print_bitinfo and not print_all:
        if text_default_mask == 3 and len(text) == 2:
            return
        if text_default_mask == 4 and len(text) == 1:
            return
    if len(text) or print_bitinfo or print_all:
        print("\n%s" % stmt)
        if print_bitinfo:
            print("Warning: No DB entries for some bits:")
        if print_bitinfo or print_map:
            for k, line in enumerate(bitinfo):
                print("%4s %s" % ("B%d" % k, line))
        for line in sorted(text):
            print(line)

for idx in ic.io_tiles:
    print_tile(".io_tile %d %d" % idx, ic, idx[0], idx[1], ic.io_tiles[idx], ic.tile_db(idx[0], idx[1]))

for idx in ic.logic_tiles:
    print_tile(".logic_tile %d %d" % idx, ic, idx[0], idx[1], ic.logic_tiles[idx], ic.tile_db(idx[0], idx[1]))

for idx in ic.ramb_tiles:
    print_tile(".ramb_tile %d %d" % idx, ic, idx[0], idx[1], ic.ramb_tiles[idx], ic.tile_db(idx[0], idx[1]))

for idx in ic.ramt_tiles:
    print_tile(".ramt_tile %d %d" % idx, ic, idx[0], idx[1], ic.ramt_tiles[idx], ic.tile_db(idx[0], idx[1]))

for i in range(4):
    for idx in ic.dsp_tiles[i]:
        print_tile(".dsp%d_tile %d %d" % (i, idx[0], idx[1]), ic, idx[0], idx[1], ic.dsp_tiles[i][idx], ic.tile_db(idx[0], idx[1]))

for idx in ic.ipcon_tiles:
    print_tile(".ipcon_tile %d %d" % idx, ic, idx[0], idx[1], ic.ipcon_tiles[idx], ic.tile_db(idx[0], idx[1]))

for bit in ic.extra_bits:
    print()
    print(".extra_bit %d %d %d" % bit)
    print(" ".join(ic.lookup_extra_bit(bit)))

print()

