# See LICENSE.incore file for details

import os,re
import multiprocessing as mp

import time
import shutil
from riscv_ctg.log import logger
import riscv_ctg.utils as utils
import riscv_ctg.constants as const
from riscv_isac.cgf_normalize import expand_cgf
from riscv_ctg.generator import Generator
from math import *
from riscv_ctg.__init__ import __version__

def create_test(usage_str, node,label,base_isa,max_inst):
    global op_template
    global ramdomize
    global out_dir
    global xlen
    flen = 0
    if 'opcode' not in node:
        return
    if 'ignore' in node:
        logger.info("Ignoring :" + str(label))
        if node['ignore']:
            return
    for opcode in node['opcode']:
        op_node=None
        if opcode not in op_template:
            for op,foo in op_template.items():
                if op!='metadata' and foo['std_op'] is not None and opcode==foo['std_op']:
                    op_node = foo
                    break
        else:
            op_node = op_template[opcode]

        if op_node is  None:
            logger.warning("Skipping :" + str(opcode))
            return
        if xlen not in op_node['xlen']:
            logger.warning("Skipping {0} since its not supported in current XLEN:".format(opcode))
            return
        if 'flen' in op_node:
            if '.d' in opcode:
                flen = 64
            elif '.s' in opcode:
                flen = 32
            else:
                flen = op_node['flen'][0]
            #if flen not in op_node['flen']:
            #    return
        fprefix = os.path.join(out_dir,str(label))
        logger.info('Generating Test for :' + str(label) +"-" + opcode)
        formattype  = op_node['formattype']
        gen = Generator(formattype,op_node,opcode,randomize,xlen,flen,base_isa)
        op_comb = gen.opcomb(node)
        val_comb = gen.valcomb(node)
        instr_dict = gen.correct_val(gen.testreg(gen.swreg(gen.gen_inst(op_comb, val_comb, node))))
        logger.info("Writing tests for :"+str(label))
        my_dict = gen.reformat_instr(instr_dict)
        gen.write_test(fprefix,node,label,my_dict, op_node, usage_str, max_inst)

def ctg(verbose, out, random ,xlen_arg, cgf_file,num_procs,base_isa, max_inst,list_duplicate):
    global op_template
    global randomize
    global out_dir
    global xlen
    logger.level(verbose)
    logger.info('****** RISC-V Compliance Test Generator {0} *******'.format(__version__ ))
    logger.info('Copyright (c) 2020, InCore Semiconductors Pvt. Ltd.')
    logger.info('All Rights Reserved.')
    logger.info("Copying env folder to Output directory.")
    env_dir = os.path.join(out,"env")
    if not os.path.exists(env_dir):
        shutil.copytree(const.env,env_dir)
    xlen = int(xlen_arg)
    out_dir = out
    randomize = random
    mytime = time.asctime(time.gmtime(time.time()) ) + ' GMT'
    cgf_argument = ''
    for cf in cgf_file:
        cgf_argument += '//                  --cgf {} \\\n'.format(cf)
    randomize_argument = ''
    if random is True:
        randomize_argument = ' \\\n//                  --randomize'
    usage_str = const.usage.safe_substitute(base_isa=base_isa, \
            cgf=cgf_argument, version = __version__, time=mytime, \
            randomize=randomize_argument,xlen=str(xlen_arg))
    op_template = utils.load_yaml(const.template_file)
    cgf = expand_cgf(cgf_file,xlen,list_duplicate)
    pool = mp.Pool(num_procs)
    results = pool.starmap(create_test, [(usage_str, node,label,base_isa,max_inst) for label,node in cgf.items()])
    pool.close()


[((69, 4, 69, 25), 'riscv_ctg.log.logger.level', 'logger.level', ({(69, 17, 69, 24): 'verbose'}, {}), '(verbose)', False, 'from riscv_ctg.log import logger\n'), ((71, 4, 71, 70), 'riscv_ctg.log.logger.info', 'logger.info', ({(71, 16, 71, 69): '"""Copyright (c) 2020, InCore Semiconductors Pvt. Ltd."""'}, {}), "('Copyright (c) 2020, InCore Semiconductors Pvt. Ltd.')", False, 'from riscv_ctg.log import logger\n'), ((72, 4, 72, 39), 'riscv_ctg.log.logger.info', 'logger.info', ({(72, 16, 72, 38): '"""All Rights Reserved."""'}, {}), "('All Rights Reserved.')", False, 'from riscv_ctg.log import logger\n'), ((73, 4, 73, 58), 'riscv_ctg.log.logger.info', 'logger.info', ({(73, 16, 73, 57): '"""Copying env folder to Output directory."""'}, {}), "('Copying env folder to Output directory.')", False, 'from riscv_ctg.log import logger\n'), ((74, 14, 74, 37), 'os.path.join', 'os.path.join', ({(74, 27, 74, 30): 'out', (74, 31, 74, 36): '"""env"""'}, {}), "(out, 'env')", False, 'import os, re\n'), ((90, 18, 90, 54), 'riscv_ctg.utils.load_yaml', 'utils.load_yaml', ({(90, 34, 90, 53): 'const.template_file'}, {}), '(const.template_file)', True, 'import riscv_ctg.utils as utils\n'), ((91, 10, 91, 50), 'riscv_isac.cgf_normalize.expand_cgf', 'expand_cgf', ({(91, 21, 91, 29): 'cgf_file', (91, 30, 91, 34): 'xlen', (91, 35, 91, 49): 'list_duplicate'}, {}), '(cgf_file, xlen, list_duplicate)', False, 'from riscv_isac.cgf_normalize import expand_cgf\n'), ((92, 11, 92, 29), 'multiprocessing.Pool', 'mp.Pool', ({(92, 19, 92, 28): 'num_procs'}, {}), '(num_procs)', True, 'import multiprocessing as mp\n'), ((56, 14, 56, 79), 'riscv_ctg.generator.Generator', 'Generator', ({(56, 24, 56, 34): 'formattype', (56, 35, 56, 42): 'op_node', (56, 43, 56, 49): 'opcode', (56, 50, 56, 59): 'randomize', (56, 60, 56, 64): 'xlen', (56, 65, 56, 69): 'flen', (56, 70, 56, 78): 'base_isa'}, {}), '(formattype, op_node, opcode, randomize, xlen, flen, base_isa)', False, 'from riscv_ctg.generator import Generator\n'), ((75, 11, 75, 34), 'os.path.exists', 'os.path.exists', ({(75, 26, 75, 33): 'env_dir'}, {}), '(env_dir)', False, 'import os, re\n'), ((76, 8, 76, 42), 'shutil.copytree', 'shutil.copytree', ({(76, 24, 76, 33): 'const.env', (76, 34, 76, 41): 'env_dir'}, {}), '(const.env, env_dir)', False, 'import shutil\n'), ((80, 38, 80, 49), 'time.time', 'time.time', ({}, {}), '()', False, 'import time\n')]