#!/usr/bin/env python3

import os
import re
import sys
import json


def tag2fasm(grid, seg, tag):
    '''Given tilegrid, segment name and tag, return fasm directive'''
    segj = grid['segments'][seg]

    def clbf(seg, tile, tag_post):
        # seg: SEG_CLBLM_L_X10Y102
        # tile_type: CLBLM_L
        # tag_post: SLICEM_X0.ALUT.INIT[43]
        # To: CLBLM_L_X10Y102.SLICE_X12Y102.ALUT.INIT[43] 1
        m = re.match(r'(SLICE[LM])_X([01])[.](.*)', tag_post)
        slicelm = m.group(1)
        off01 = int(m.group(2))
        post = m.group(3)

        # xxx: actually this might not work on decimal overflow (9 => 10)
        for site in grid['tiles'][tile]['sites'].keys():
            m = re.match(r'SLICE_X(.*)Y.*', site)
            sitex = int(m.group(1))
            if sitex % 2 == off01:
                break
        else:
            raise Exception("Failed to match site")

        return '%s.%s.%s 1' % (tile, site, post)

    def intf(seg, tile, tag_post):
        # Make the selection an argument of the configruation
        m = re.match(r'(.*)[.]([A-Za-z0-9_]+)', tag_post)
        which = m.group(1)
        value = m.group(2)
        site = {
            'clblm_l': 'CENTER_INTER_L',
            'clblm_r': 'CENTER_INTER_R',
            'hclk_l': 'HCLK_L',
            'hclk_r': 'HCLK_R',
        }[segj['type']]
        return '%s.%s.%s %s' % (tile, site, which, value)

    m = re.match(r'([A-Za-z0-9_]+)[.](.*)', tag)
    tile_type = m.group(1)
    tag_post = m.group(2)

    # Find associated tile
    for tile in segj['tiles']:
        if grid['tiles'][tile]['type'] == tile_type:
            break
    else:
        raise Exception("Couldn't find tile type %s" % tile_type)

    tag2asm = {
        'CLBLM_L': clbf,
        'CLBLM_R': clbf,
        'INT_L': intf,
        'INT_R': intf,
        'HCLK_L': intf,
        'HCLK_R': intf,
    }
    f = tag2asm.get(tile_type, None)
    if f is None:
        raise Exception("Unhandled segment type %s" % tile_type)
    return f(seg, tile, tag_post)


def run(f_in, f_out, sparse=False):
    with open("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"),
                                       os.getenv("XRAY_DATABASE")), "r") as f:
        grid = json.load(f)

    seg = None
    for l in f_in:
        l = l.strip()
        if not l:
            continue
        # seg SEG_CLBLM_L_X10Y102
        # tag CLBLM_L.SLICEM_X0.ALUT.INIT[00]
        m = re.match('(seg|tag) (.*)', l)
        if not m:
            raise Exception("Invalid line %s" % l)
        type = m.group(1)
        if type == 'seg':
            seg = m.group(2)
        elif type == 'tag':
            f_out.write(tag2fasm(grid, seg, m.group(2)) + '\n')
        else:
            raise Exception("Invalid type %s" % type)


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(
        description='Convert segprint -d output to .fasm file (FPGA assembly)')

    parser.add_argument(
        'fn_in', default='/dev/stdin', nargs='?', help='Input segment file')
    parser.add_argument(
        'fn_out', default='/dev/stdout', nargs='?', help='Output .fasm file')

    args = parser.parse_args()
    run(open(args.fn_in, 'r'), open(args.fn_out, 'w'))
