# Copyright 2020 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Tools to analyze Cortex-M CPU state context captured during an exception."""

from typing import Optional, Tuple

from pw_cpu_exception_cortex_m import cortex_m_constants
from pw_cpu_exception_cortex_m_protos import cpu_state_pb2
import pw_symbolizer

# These registers are symbolized when dumped.
_SYMBOLIZED_REGISTERS = ('pc', 'lr', 'bfar', 'mmfar', 'msp', 'psp', 'r0', 'r1',
                         'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10',
                         'r11', 'r12')


class CortexMExceptionAnalyzer:
    """This class provides helper functions to dump a ArmV7mCpuState proto."""
    def __init__(self,
                 cpu_state,
                 symbolizer: Optional[pw_symbolizer.Symbolizer] = None):
        self._cpu_state = cpu_state
        self._symbolizer = symbolizer
        self._active_cfsr_fields: Optional[Tuple[cortex_m_constants.BitField,
                                                 ...]] = None

    def active_cfsr_fields(self) -> Tuple[cortex_m_constants.BitField, ...]:
        """Returns a list of BitFields for each active CFSR flag."""

        if self._active_cfsr_fields is not None:
            return self._active_cfsr_fields

        temp_field_list = []
        if self._cpu_state.HasField('cfsr'):
            for bit_field in cortex_m_constants.PW_CORTEX_M_CFSR_BIT_FIELDS:
                if self._cpu_state.cfsr & bit_field.bit_mask:
                    temp_field_list.append(bit_field)
        self._active_cfsr_fields = tuple(temp_field_list)
        return self._active_cfsr_fields

    def is_fault_active(self) -> bool:
        """Returns true if the current CPU state indicates a fault is active."""
        if self._cpu_state.HasField('cfsr') and self._cpu_state.cfsr != 0:
            return True
        if self._cpu_state.HasField('icsr'):
            exception_number = (
                self._cpu_state.icsr
                & cortex_m_constants.PW_CORTEX_M_ICSR_VECTACTIVE_MASK)
            if (cortex_m_constants.PW_CORTEX_M_HARD_FAULT_ISR_NUM <=
                    exception_number <=
                    cortex_m_constants.PW_CORTEX_M_USAGE_FAULT_ISR_NUM):
                return True
        return False

    def is_nested_fault(self) -> bool:
        """Returns true if the current CPU state indicates a nested fault."""
        if not self.is_fault_active():
            return False
        if (self._cpu_state.HasField('hfsr') and self._cpu_state.hfsr
                & cortex_m_constants.PW_CORTEX_M_HFSR_FORCED_MASK):
            return True
        return False

    def exception_cause(self, show_active_cfsr_fields=True) -> str:
        """Analyzes CPU state to tries and classify the exception.

        Examples:
            show_active_cfsr_fields=False
              unknown exception
              memory management fault at 0x00000000
              usage fault, imprecise bus fault

            show_active_cfsr_fields=True
              usage fault [DIVBYZERO]
              memory management fault at 0x00000000 [DACCVIOL] [MMARVALID]
        """
        cause = ''
        # The CFSR can accumulate multiple exceptions.
        split_major_cause = lambda cause: cause if not cause else cause + ', '

        if self._cpu_state.HasField('cfsr') and self.is_fault_active():
            if (self._cpu_state.cfsr
                    & cortex_m_constants.PW_CORTEX_M_CFSR_USAGE_FAULT_MASK):
                cause += 'usage fault'

            if (self._cpu_state.cfsr
                    & cortex_m_constants.PW_CORTEX_M_CFSR_MEM_FAULT_MASK):
                cause = split_major_cause(cause)
                cause += 'memory management fault'
                if (self._cpu_state.cfsr
                        & cortex_m_constants.PW_CORTEX_M_CFSR_MMARVALID_MASK):
                    addr = '???' if not self._cpu_state.HasField(
                        'mmfar') else f'0x{self._cpu_state.mmfar:08x}'
                    cause += f' at {addr}'

            if (self._cpu_state.cfsr
                    & cortex_m_constants.PW_CORTEX_M_CFSR_BUS_FAULT_MASK):
                cause = split_major_cause(cause)
                if (self._cpu_state.cfsr &
                        cortex_m_constants.PW_CORTEX_M_CFSR_IMPRECISERR_MASK):
                    cause += 'imprecise '
                cause += 'bus fault'
                if (self._cpu_state.cfsr
                        & cortex_m_constants.PW_CORTEX_M_CFSR_BFARVALID_MASK):
                    addr = '???' if not self._cpu_state.HasField(
                        'bfar') else f'0x{self._cpu_state.bfar:08x}'
                    cause += f' at {addr}'
            if show_active_cfsr_fields:
                for field in self.active_cfsr_fields():
                    cause += f' [{field.name}]'

        return cause if cause else 'unknown exception'

    def dump_registers(self) -> str:
        """Dumps all captured CPU registers as a multi-line string."""
        registers = []
        for field in self._cpu_state.DESCRIPTOR.fields:
            if self._cpu_state.HasField(field.name):
                register_value = getattr(self._cpu_state, field.name)
                register_str = f'{field.name:<10} 0x{register_value:08x}'
                if (self._symbolizer is not None
                        and field.name in _SYMBOLIZED_REGISTERS):
                    symbol = self._symbolizer.symbolize(register_value)
                    if symbol.name:
                        register_str += f' {symbol}'
                registers.append(register_str)
        return '\n'.join(registers)

    def dump_active_active_cfsr_fields(self) -> str:
        """Dumps CFSR flags with their descriptions as a multi-line string."""
        fields = []
        for field in self.active_cfsr_fields():
            fields.append(f'{field.name:<11} {field.description}')
            if isinstance(field.long_description, tuple):
                long_desc = '    {}'.format('\n    '.join(
                    field.long_description))
                fields.append(long_desc)
        return '\n'.join(fields)

    def __str__(self):
        dump = [f'Exception caused by a {self.exception_cause(False)}.', '']
        if self.active_cfsr_fields():
            dump.extend((
                'Active Crash Fault Status Register (CFSR) fields:',
                self.dump_active_active_cfsr_fields(),
                '',
            ))
        else:
            dump.extend((
                'No active Crash Fault Status Register (CFSR) fields.',
                '',
            ))
        dump.extend((
            'All registers:',
            self.dump_registers(),
        ))
        return '\n'.join(dump)


def process_snapshot(
        serialized_snapshot: bytes,
        symbolizer: Optional[pw_symbolizer.Symbolizer] = None) -> str:
    """Returns the stringified result of a SnapshotCpuStateOverlay message run
    though a CortexMExceptionAnalyzer.
    """
    snapshot = cpu_state_pb2.SnapshotCpuStateOverlay()
    snapshot.ParseFromString(serialized_snapshot)

    if snapshot.HasField('armv7m_cpu_state'):
        state_analyzer = CortexMExceptionAnalyzer(snapshot.armv7m_cpu_state,
                                                  symbolizer)
        return f'{state_analyzer}\n'

    return ''
