#!/usr/bin/env python3
#
# Copyright (c) 2015-2020 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import argparse
import os
import sys
import textwrap

import codegen

h = None
c = None


def generate_register_configs(set):
    register_types = {
        'FLEX': 'flex_regs',
        'NOA': 'mux_regs',
        'OA': 'b_counter_regs',
    }

    c("void %s_%s_add_registers(struct intel_perf *perf, struct intel_perf_metric_set *metric_set)" %
      (set.gen.chipset, set.underscore_name))
    c("{")
    c.indent(4)

    # allocate memory
    total_n_registers = {}
    register_configs = set.findall('register_config')
    for register_config in register_configs:
        t = register_types[register_config.get('type')]
        if t not in total_n_registers:
            total_n_registers[t] = len(register_config.findall('register'))
        else:
            total_n_registers[t] += len(register_config.findall('register'))

    for reg in total_n_registers:
        c("metric_set->{0} = calloc({1}, sizeof(struct intel_perf_register_prog));".format(reg, total_n_registers[reg]))
    c("\n")

    # fill in register/values
    register_configs = set.findall('register_config')
    for register_config in register_configs:
        t = register_types[register_config.get('type')]

        availability = register_config.get('availability')
        if availability:
            set.gen.output_availability(set, availability, register_config.get('type') + ' register config')
            c.indent(4)

        for register in register_config.findall('register'):
            c("metric_set->%s[metric_set->n_%s++] = (struct intel_perf_register_prog) { .reg = %s, .val = %s };" %
              (t, t, register.get('address'), register.get('value')))

        if availability:
            c.outdent(4)
            c("}")
        c("\n")

    c.outdent(4)
    c("}")


def main():
    global c
    global h
    global xml_equations

    parser = argparse.ArgumentParser()
    parser.add_argument("--header", help="Header file to write")
    parser.add_argument("--code", help="C file to write")
    parser.add_argument("--xml-file", help="Xml file to generate register configurations from")

    args = parser.parse_args()

    # Note: either arg may == None
    h = codegen.Codegen(args.header)
    c = codegen.Codegen(args.code)

    gen = codegen.Gen(args.xml_file, c)

    copyright = textwrap.dedent("""\
        /* Autogenerated file, DO NOT EDIT manually! generated by {}
         *
         * Copyright (c) 2020 Intel Corporation
         *
         * Permission is hereby granted, free of charge, to any person obtaining a
         * copy of this software and associated documentation files (the "Software"),
         * to deal in the Software without restriction, including without limitation
         * the rights to use, copy, modify, merge, publish, distribute, sublicense,
         * and/or sell copies of the Software, and to permit persons to whom the
         * Software is furnished to do so, subject to the following conditions:
         *
         * The above copyright notice and this permission notice (including the next
         * paragraph) shall be included in all copies or substantial portions of the
         * Software.
         *
         * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
         * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
         * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
         * DEALINGS IN THE SOFTWARE.
         */

        """).format(os.path.basename(__file__))


    header_file = os.path.basename(args.header)
    header_define = "__%s__" % header_file.replace('.', '_').upper()

    h(copyright)
    h("#ifndef %s" % header_define)
    h("#define %s" % header_define)
    h("\n")
    h("struct intel_perf;")
    h("struct intel_perf_metric_set;")
    h("\n")
    for set in gen.sets:
        h("void %s_%s_add_registers(struct intel_perf *perf, struct intel_perf_metric_set *metric_set);" %
          (gen.chipset, set.underscore_name))
    h("\n")
    h("#endif /* %s */" % header_define)

    c(copyright)
    c("\n")
    c("#include <stdlib.h>")
    c("\n")
    c("#include \"%s\"" % header_file)
    c("#include \"i915/perf.h\"")

    for set in gen.sets:
        c("\n")
        generate_register_configs(set)


if __name__ == '__main__':
    main()
