#!/usr/bin/env python3
# coding=utf-8
from __future__ import print_function

import os
import os.path as path
import re
import argparse
from datetime import datetime

script_dir = path.dirname(path.realpath(__file__))

defines = {}
for k, v in os.environ.items():
    if k.upper().startswith('V_'):
        defines[k[2:]] = v

print('Custom params:', ', '.join(['='.join(x) for x in defines.items()]))

parser = argparse.ArgumentParser()
parser.add_argument('--outc', default='none', help='Output C header')
parser.add_argument('--outv', default='none', help='Output Verilog header')

args = parser.parse_args()

if args.outc == 'none' and args.outv == 'none':
    print('Warning: not emitting any files. Specify arguments')

if args.outv != 'none':
    with open(args.outv, 'w') as f:
        print('''
// auto-generated by gen_config.py. DO NOT EDIT
// Generated at {date}

`ifndef VX_USER_CONFIG
`define VX_USER_CONFIG
'''[1:].format(date=datetime.now()), file=f)

        for k, v in defines.items():
            print('`define {} {}'.format(k, v), file=f)

        print('\n`endif', file=f)

if args.outc != 'none':
    with open(args.outc, 'w') as f:
        print('''
// auto-generated by gen_config.py. DO NOT EDIT
// Generated at {date}

#ifndef VX_USER_CONFIG
#define VX_USER_CONFIG
'''[1:].format(date=datetime.now()), file=f)

        for k, v in defines.items():
            print('#define {} {}'.format(k, v), file=f)

        print('\n#endif', file=f)

translation_rules = [
    (re.compile(r'^$'), r''),
    (re.compile(r'^(\s*)`ifndef\s+([^ ]+)'), r'\1#ifndef \2'),
    (re.compile(r'^(\s*)`define\s+([^ ]+)'), r'\1#define \2'),
    (re.compile(r'^(\s*)`include "VX_user_config\.vh"'), r''),
    (re.compile(r'^(\s*)`define\s+([^ ]+) (.+)'), r'\1#define \2 \3'),
    (re.compile(r'^(\s*)`endif\s+'), r'\1#endif'),
    (re.compile(r'^(\s*)//(.*)'), r'\1// \2'),
]

post_rules = [
    (re.compile(r"\d+'d(\d+)"), r'\1'),

    # non-standard C but supported by GCC and Clang
    (re.compile(r"\d+'b([01]+)"), r'0b\1'),
    (re.compile(r"\d+'h([\da-fA-F]+)"), r'0x\1'),

    # fix macro references (does not support escaped identifiers §5.6.1)
    (re.compile(r"`([A-Za-z_][$_0-9A-Za-z]*)"), r'\1'),
]

def post_process_line(line):
    for pat, repl in post_rules:
        line = pat.sub(repl, line)
    return line


in_expansion = False

if args.outc != 'none':
    with open(args.outc, 'a') as f:
        print('''
// auto-generated by gen_config.py. DO NOT EDIT
// Generated at {date}

// Translated from VX_config.vh:
'''[1:].format(date=datetime.now()), file=f)
        with open(path.join(script_dir, '../rtl/VX_config.vh'), 'r') as r:
            lineno = 0
            for line in r:
                if in_expansion:
                    f.write(post_process_line(line))
                    if not line.strip().endswith('\\'):
                        in_expansion = False
                else:
                    for pat, repl in translation_rules:
                        if pat.match(line):
                            if line.strip().endswith('\\'):
                                in_expansion = True
                            f.write(post_process_line(pat.sub(repl, line)))
                            break
                    else:
                        raise ValueError('failed to find rule for: "' + line + '" (' + str(lineno) + ')')
                lineno = lineno + 1

        print('''
// Misc

#define THREADS_PER_WARP NUM_THREADS
#define WARPS_PER_CORE NUM_WARPS
#define NUM_WI (NUM_WARPS * NUM_THREADS * NUM_CORES_PER_CLUSTER * NUM_CLUSTERS)

// legacy
#define TOTAL_THREADS NUM_WI
#define TOTAL_WARPS (NUM_WARPS * NUM_CORES_PER_CLUSTER * NUM_CLUSTERS)

// COLORS
#define GREEN "\\033[32m"
#define RED "\\033[31m"
#define DEFAULT "\\033[39m"
'''[1:], file=f)



