# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

from typing import Dict, List, NamedTuple, Tuple

from .lib import Name


def _yn_to_bool(yn: object) -> bool:
    yn_str = str(yn)
    if yn_str.lower() == 'yes':
        return True
    if yn_str.lower() == 'no':
        return False
    raise ValueError('Unknown yes/no value: {!r}.'.format(yn))


def _bool_to_yn(val: bool) -> str:
    return 'yes' if val else 'no'


def _to_int(val: object) -> int:
    if isinstance(val, int):
        return val
    return int(str(val))


def _check_choices(val: str, what: str, choices: List[str]) -> str:
    if val in choices:
        return val
    raise ValueError('{} is {!r}, which is not one of the expected values: {}.'
                     .format(what, val, choices))


class SourceClock:
    '''A clock source (input to the top-level)'''
    def __init__(self, raw: Dict[str, object]):
        self.name = str(raw['name'])
        self.aon = _yn_to_bool(raw['aon'])
        self.freq = _to_int(raw['freq'])
        self.ref = raw.get('ref', False)

    def _asdict(self) -> Dict[str, object]:
        return {
            'name': self.name,
            'aon': _bool_to_yn(self.aon),
            'freq': str(self.freq),
            'ref': self.ref
        }


class DerivedSourceClock(SourceClock):
    '''A derived source clock (divided down from some other clock)'''
    def __init__(self,
                 raw: Dict[str, object],
                 sources: Dict[str, SourceClock]):
        super().__init__(raw)
        self.div = _to_int(raw['div'])
        self.src = sources[str(raw['src'])]

    def _asdict(self) -> Dict[str, object]:
        ret = super()._asdict()
        ret['div'] = str(self.div)
        ret['src'] = self.src.name
        return ret


class ClockSignal:
    '''A clock signal in the design'''
    def __init__(self, name: str, src: SourceClock):
        self.name = name
        self.src = src
        self.endpoints = []  # type: List[Tuple[str, str]]

    def add_endpoint(self, ep_name: str, ep_port: str) -> None:
        self.endpoints.append((ep_name, ep_port))


class Group:
    def __init__(self,
                 raw: Dict[str, object],
                 what: str):
        self.name = str(raw['name'])
        self.src = str(raw['src'])
        self.sw_cg = _check_choices(str(raw['sw_cg']), 'sw_cg for ' + what,
                                    ['yes', 'no', 'hint'])
        if self.src == 'yes' and self.sw_cg != 'no':
            raise ValueError(f'Clock group {self.name} has an invalid '
                             f'combination of src and sw_cg: {self.src} and '
                             f'{self.sw_cg}, respectively.')

        self.unique = _yn_to_bool(raw.get('unique', 'no'))
        if self.sw_cg == 'no' and self.unique:
            raise ValueError(f'Clock group {self.name} has an invalid '
                             f'combination with sw_cg of {self.sw_cg} and '
                             f'unique set.')

        self.clocks = {}  # type: Dict[str, ClockSignal]

    def add_clock(self, clk_name: str, src: SourceClock) -> ClockSignal:
        # Duplicates are ok, so long as they have the same source.
        sig = self.clocks.get(clk_name)
        if sig is not None:
            if sig.src is not src:
                raise ValueError(f'Cannot add clock {clk_name} to group '
                                 f'{self.name} with source {src.name}: the '
                                 f'clock is there already with source '
                                 f'{sig.src.name}.')
        else:
            sig = ClockSignal(clk_name, src)
            self.clocks[clk_name] = sig

        return sig

    def _asdict(self) -> Dict[str, object]:
        return {
            'name': self.name,
            'src': self.src,
            'sw_cg': self.sw_cg,
            'unique': _bool_to_yn(self.unique),
            'clocks': {name: sig.src.name
                       for name, sig in self.clocks.items()}
        }


class TypedClocks(NamedTuple):
    # External clocks that are consumed only inside the clkmgr and are fed from
    # an external ast source.
    ast_clks: Dict[str, ClockSignal]

    # Clocks fed through clkmgr but not disturbed in any way. This maintains
    # the clocking structure consistency. This includes two groups of clocks:
    #
    #   - Clocks fed from the always-on source
    #   - Clocks fed to the powerup group
    ft_clks: Dict[str, ClockSignal]

    # Non-feedthrough clocks that have no software control. These clocks are
    # root-gated and the root-gated clock is then exposed directly in clocks_o.
    rg_clks: Dict[str, ClockSignal]

    # Non-feedthrough clocks that have direct software control. These are
    # root-gated, but (unlike rg_clks) then go through a second clock gate
    # which is controlled by software.
    sw_clks: Dict[str, ClockSignal]

    # Non-feedthrough clocks that have "hint" software control (with a feedback
    # mechanism to allow blocks to avoid being suspended when they are not
    # idle).
    hint_clks: Dict[str, ClockSignal]

    # A list of the of non-always-on clock sources that are exposed without
    # division, sorted by name. This doesn't include clock sources that are
    # only used to derive divided clocks (we might gate the divided clocks, but
    # don't bother gating the upstream source).
    rg_srcs: List[str]

    def all_clocks(self) -> Dict[str, ClockSignal]:
        ret = {}
        ret.update(self.ft_clks)
        ret.update(self.hint_clks)
        ret.update(self.rg_clks)
        ret.update(self.sw_clks)
        return ret

    def hint_names(self) -> Dict[str, str]:
        '''Return a dictionary with hint names for the hint clocks

        These are used as enum items that name the clock hint signals. The
        insertion ordering in this dictionary is important because it gives the
        mapping from enum name to index.

        '''
        # A map from endpoint to the list of hint clocks that it uses.
        ep_to_hints = {}
        for sig in self.hint_clks.values():
            for ep, port_name in sig.endpoints:
                ep_to_hints.setdefault(ep, []).append(sig.name)

        # A map from hint clock name to the associated enumeration name which
        # will appear in hint_names_e in clkmgr_pkg.sv. Note that this is
        # ordered alphabetically by endpoint: the precise ordering shouldn't
        # matter, but it's probably nicer to keep endpoints' signals together.
        hint_names = {}
        for ep, clks in sorted(ep_to_hints.items()):
            for clk in sorted(clks):
                # Remove any "clk" prefix
                clk_name = Name.from_snake_case(clk).remove_part('clk')
                hint_name = Name(['hint']) + clk_name
                hint_names[clk] = hint_name.as_camel_case()

        return hint_names


class Clocks:
    '''Clock connections for the chip'''
    def __init__(self, raw: Dict[str, object]):
        self.hier_paths = {}
        assert isinstance(raw['hier_paths'], dict)
        for grp_src, path in raw['hier_paths'].items():
            self.hier_paths[str(grp_src)] = str(path)

        assert isinstance(raw['srcs'], list)
        self.srcs = {}
        for r in raw['srcs']:
            clk = SourceClock(r)
            self.srcs[clk.name] = clk

        self.derived_srcs = {}
        assert isinstance(raw['derived_srcs'], list)
        for r in raw['derived_srcs']:
            clk = DerivedSourceClock(r, self.srcs)
            self.derived_srcs[clk.name] = clk

        self.all_srcs = self.srcs.copy()
        self.all_srcs.update(self.derived_srcs)

        self.groups = {}
        assert isinstance(raw['groups'], list)
        for idx, raw_grp in enumerate(raw['groups']):
            assert isinstance(raw_grp, dict)
            grp = Group(raw_grp, f'clocks.groups[{idx}]')
            self.groups[grp.name] = grp

    def _asdict(self) -> Dict[str, object]:
        return {
            'hier_paths': self.hier_paths,
            'srcs': list(self.srcs.values()),
            'derived_srcs': list(self.derived_srcs.values()),
            'groups': list(self.groups.values())
        }

    def add_clock_to_group(self,
                           grp: Group,
                           clk_name: str,
                           src_name: str) -> ClockSignal:
        src = self.all_srcs.get(src_name)
        if src is None:
            raise ValueError(f'Cannot add clock {clk_name} to group '
                             f'{grp.name}: the given source name is '
                             f'{src_name}, which is unknown.')
        return grp.add_clock(clk_name, src)

    def get_clock_by_name(self, name: str) -> object:
        ret = self.all_srcs.get(name)
        if ret is None:
            raise ValueError(f'{name} is not a valid clock')
        return ret

    def reset_signals(self) -> List[str]:
        '''Return the list of clock reset signal names

        These signals are inputs to the clock manager (from the reset
        manager)

        '''
        ret = []
        for src in self.srcs.values():
            ret.append(f'rst_{src.name}_ni')
        for src in self.derived_srcs.values():
            ret.append(f'rst_{src.name}_ni')
        return ret

    def typed_clocks(self) -> TypedClocks:
        '''Split the clocks by type'''
        ast_clks = {}
        ft_clks = {}
        rg_clks = {}
        sw_clks = {}
        hint_clks = {}
        rg_srcs_set = set()

        for grp in self.groups.values():
            if grp.name == 'powerup':
                # All clocks in the "powerup" group are considered feed-throughs.
                ft_clks.update(grp.clocks)
                continue

            for clk, sig in grp.clocks.items():
                if grp.src == "ext":
                    ast_clks[clk] = sig
                    continue

                if sig.src.aon:
                    # Any always-on clock is a feedthrough
                    ft_clks[clk] = sig
                    continue

                rg_srcs_set.add(sig.src.name)

                if grp.sw_cg == 'no':
                    # A non-feedthrough clock with no software control
                    rg_clks[clk] = sig
                    continue

                if grp.sw_cg == 'yes':
                    # A non-feedthrough clock with direct software control
                    sw_clks[clk] = sig
                    continue

                # The only other valid value for the sw_cg field is "hint", which
                # means a non-feedthrough clock with "hint" software control.
                assert grp.sw_cg == 'hint'
                hint_clks[clk] = sig
                continue

        # Define a canonical ordering for rg_srcs
        rg_srcs = list(sorted(rg_srcs_set))

        return TypedClocks(ast_clks=ast_clks,
                           ft_clks=ft_clks,
                           rg_clks=rg_clks,
                           sw_clks=sw_clks,
                           hint_clks=hint_clks,
                           rg_srcs=rg_srcs)

    def make_clock_to_group(self) -> Dict[str, Group]:
        '''Return a map from clock name to the group containing the clock'''
        c2g = {}
        for grp in self.groups.values():
            for clk_name in grp.clocks.keys():
                c2g[clk_name] = grp
        return c2g
