# Copyright (C) 2020 Arm Limited or its affiliates. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# 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
#
# 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.
# Description:
# Holds a container for Ethos-U and System architecture parameters.
import enum
from collections import namedtuple
from configparser import ConfigParser

import numpy as np

from .api import NpuAccelerator
from .errors import CliOptionError
from .errors import ConfigOptionError
from .ethos_u55_regs.ethos_u55_regs import resampling_mode
from .numeric_util import full_shape
from .numeric_util import round_up
from .numeric_util import round_up_divide
from .operation import Kernel
from .operation import NpuBlockType
from .operation import PointXYZ
from .supported_operators import SupportedOperators
from .tensor import BandwidthDirection
from .tensor import MemArea
from .tensor import MemType
from .tensor import TensorFormat
from .tensor import TensorPurpose


class Block:
    def __init__(self, w, h, d):
        self.width = w
        self.height = h
        self.depth = d

    def __eq__(self, other):
        if self.width == other.width and self.height == other.height and self.depth == other.depth:
            return True
        else:
            return False

    def __repr__(self):
        return "<Block: {0},{1},{2}>".format(self.width, self.height, self.depth)

    @classmethod
    def from_string(cls, s):
        w, h, c = (int(v) for v in s.split("x"))
        return cls(w, h, c)

    @classmethod
    def from_shape(cls, shape) -> "Block":
        """Converts the shape to a Block"""
        shp = full_shape(3, shape, 1)
        # Note: index from end, as len(shp) may be > 3
        return Block(shp[-2], shp[-3], shp[-1])


class Rect:
    def __init__(self, x, y, z, x2, y2, z2):
        self.x = x
        self.y = y
        self.z = z
        self.x2 = x2
        self.y2 = y2
        self.z2 = z2

    def start(self):
        return PointXYZ(self.x, self.y, self.z)

    def end(self):
        return PointXYZ(self.x2, self.y2, self.z2)

    def size(self):
        return Block(self.x2 - self.x + 1, self.y2 - self.y + 1, self.z2 - self.z + 1)

    def __repr__(self):
        return "<Rect: ({0},{1},{2}) ({3},{4},{5})>".format(self.x, self.y, self.z, self.x2, self.y2, self.z2)


class SHRAMElements:
    IFM8 = 0
    IFM16 = 1
    IFM8_Elementwise = 2
    IFM16_Elementwise = 3
    IFM32 = 4
    Acc16 = 5
    Acc32 = 6
    Acc40 = 7
    Last = Acc40
    BitSizes = np.array([8, 16, 8, 16, 32, 16, 32, 40], np.int32)
    ByteSizes = BitSizes // 8
    PostAlign = np.array([8, 8, 8, 8, 8, 1, 1, 1], np.int32)
    PreAlign = np.array([1, 1, 1, 1, 1, 8, 8, 8], np.int32)


class SHRAMBlockConfig:
    def __init__(self, sizes, banks):
        assert len(banks) == SHRAMElements.Last + 1
        self.sizes = sizes
        self.banks = banks


# Area indices must match Ethos-U SHRAM layout spec
class SharedBufferArea(enum.IntEnum):
    OFM = 0
    Weights = 1
    IFM = 2
    Accumulators = 3
    Size = Accumulators + 1


class Accelerator(enum.Enum):
    Ethos_U55_32 = "ethos-u55-32"
    Ethos_U55_64 = "ethos-u55-64"
    Ethos_U55_128 = "ethos-u55-128"
    Ethos_U55_256 = "ethos-u55-256"
    Ethos_U65_256 = "ethos-u65-256"
    Ethos_U65_512 = "ethos-u65-512"

    @classmethod
    def member_list(cls):
        return [e.value for e in cls]

    @classmethod
    def from_npu_accelerator(cls, npu_accelerator: NpuAccelerator) -> "Accelerator":
        """Converts the given public API object to Accelerator (used internally)"""
        accelerator_map = {
            NpuAccelerator.Ethos_U55_32: cls.Ethos_U55_32,
            NpuAccelerator.Ethos_U55_64: cls.Ethos_U55_64,
            NpuAccelerator.Ethos_U55_128: cls.Ethos_U55_128,
            NpuAccelerator.Ethos_U55_256: cls.Ethos_U55_256,
            NpuAccelerator.Ethos_U65_256: cls.Ethos_U65_256,
            NpuAccelerator.Ethos_U65_512: cls.Ethos_U65_512,
        }
        assert npu_accelerator in accelerator_map, f"Unsupported accelerator {npu_accelerator}"
        return accelerator_map[npu_accelerator]


@enum.unique
class MemPort(enum.Enum):
    Axi0 = enum.auto()
    Axi1 = enum.auto()


class ArchitectureFeatures:
    """This class is a container for various parameters of the Ethos-U core
    and system configuration that can be tuned, either by command line
    parameters or by the Ethos-U architects. The class is often passed
    around to passes that need to do architecture-dependent actions.

    Note the difference between ArchitectureFeatures and CompilerOptions
    - ArchitectureFeatures is for changing the Ethos-U and system architecture
    - CompilerOptions is for changing the behaviour of the compiler
    """

    ArchitectureConfig = namedtuple(
        "ArchitectureConfig", "macs cores ofm_ublock ifm_ublock shram_banks shram_granules elem_units"
    )
    accelerator_configs = {
        Accelerator.Ethos_U65_512: ArchitectureConfig(
            256, 2, Block(2, 2, 8), Block(2, 2, 8), 48, [8, 8, 8, 8, 16, 8, 16, 20], 8
        ),
        Accelerator.Ethos_U65_256: ArchitectureConfig(
            256, 1, Block(2, 2, 8), Block(2, 2, 8), 48, [8, 8, 8, 8, 16, 8, 16, 20], 8
        ),
        Accelerator.Ethos_U55_256: ArchitectureConfig(
            256, 1, Block(2, 2, 8), Block(2, 2, 8), 48, [8, 8, 8, 8, 16, 8, 16, 20], 8
        ),
        Accelerator.Ethos_U55_128: ArchitectureConfig(
            128, 1, Block(2, 1, 8), Block(2, 2, 8), 24, [4, 4, 4, 4, 8, 4, 8, 12], 4
        ),
        Accelerator.Ethos_U55_64: ArchitectureConfig(
            64, 1, Block(1, 1, 8), Block(1, 1, 8), 16, [2, 2, 2, 2, 4, 4, 4, 8], 2
        ),
        Accelerator.Ethos_U55_32: ArchitectureConfig(
            32, 1, Block(1, 1, 4), Block(1, 1, 8), 16, [2, 2, 2, 2, 4, 4, 4, 4], 1
        ),
    }

    OFMSplitDepth = 16
    SubKernelMax = Block(8, 8, 65536)

    DEFAULT_CONFIG = "internal-default"
    MAX_BLOCKDEP = 3

    def __init__(
        self,
        vela_config_files,
        accelerator_config,
        system_config,
        memory_mode,
        override_block_config,
        block_config_limit,
        max_blockdep,
        weight_estimation_scaling,
        verbose_config,
    ):
        accelerator_config = accelerator_config.lower()
        if accelerator_config not in Accelerator.member_list():
            raise CliOptionError("--accelerator-config", self.accelerator_config, "Unknown accelerator configuration")
        self.accelerator_config = Accelerator(accelerator_config)
        accel_config = ArchitectureFeatures.accelerator_configs[self.accelerator_config]
        self.config = accel_config

        self.system_config = system_config
        self.memory_mode = memory_mode
        self.is_ethos_u65_system = self.accelerator_config in (Accelerator.Ethos_U65_256, Accelerator.Ethos_U65_512)

        self.max_outstanding_dma = 2 if self.is_ethos_u65_system else 1
        self.max_outstanding_kernels = 3

        self.ncores = accel_config.cores
        self.ofm_ublock = accel_config.ofm_ublock
        self.ifm_ublock = accel_config.ifm_ublock
        self.ofm_block_max = Block(64, 32, 128)
        self.override_block_config = override_block_config
        self.block_config_limit = block_config_limit

        self.max_blockdep = max_blockdep
        self.weight_estimation_scaling = weight_estimation_scaling

        dpu_min_height = accel_config.ofm_ublock.height
        dpu_min_width = accel_config.ofm_ublock.width
        dpu_dot_product_width = 8
        dpu_min_ofm_channels = accel_config.ofm_ublock.depth

        self.num_elem_wise_units = accel_config.elem_units
        self.num_macs_per_cycle = dpu_min_height * dpu_min_width * dpu_dot_product_width * dpu_min_ofm_channels

        # Get system configuration and memory mode
        self._get_vela_config(vela_config_files, verbose_config)

        self.axi_port_width = 128 if self.is_ethos_u65_system else 64
        self.memory_bandwidths_per_cycle = self.axi_port_width * self.memory_clock_scales / 8

        self.memory_bandwidths_per_second = self.memory_bandwidths_per_cycle * self.core_clock

        # Get output/activation performance numbers
        self._generate_output_perf_tables(self.accelerator_config)

        # sizes as N x H x W x C. we need to round up to these when allocating storage
        self.storage_rounding_quantums = {
            TensorFormat.Unknown: (1, 1, 1, 1),
            TensorFormat.WeightsCompressed: (1, 1, 1, 1),
            TensorFormat.NHWC: (1, 1, 1, 1),
            TensorFormat.NHCWB16: (1, 1, 1, 16),
        }

        # brick sizes as N x H x W x C. We have to fetch whole bricks at a time
        self.brick_sizes = {
            TensorFormat.Unknown: (1, 1, 1, 1),
            TensorFormat.WeightsCompressed: (1, 1, 1, 1),
            TensorFormat.NHWC: (1, 1, 1, 1),
            TensorFormat.NHCWB16: (1, 1, 1, 16),
        }

        self.default_weight_format = TensorFormat.WeightsCompressed
        self.default_feature_map_format = TensorFormat.NHWC

        self.tensor_storage_mem_area = {
            # permanent mem_area
            TensorPurpose.Unknown: MemArea.Unknown,
            TensorPurpose.Weights: self.permanent_storage_mem_area,
            TensorPurpose.FeatureMap: self.feature_map_storage_mem_area,
            TensorPurpose.LUT: self.permanent_storage_mem_area,
        }

        self.tensor_storage_mem_type = {
            TensorPurpose.Unknown: MemType.Unknown,
            TensorPurpose.Weights: MemType.Permanent_NPU,
            TensorPurpose.FeatureMap: MemType.Scratch,
            TensorPurpose.LUT: MemType.Scratch,
        }

        self.min_block_sizes = {
            NpuBlockType.Default: (dpu_min_height, dpu_min_width),
            NpuBlockType.VectorProduct: (1, 1),
            NpuBlockType.ConvolutionMxN: (dpu_min_height, dpu_min_width),
            NpuBlockType.Pooling: (dpu_min_height, dpu_min_width),
            NpuBlockType.ConvolutionDepthWise: (dpu_min_height, dpu_min_width),
            NpuBlockType.ElementWise: (1, 1),
            NpuBlockType.ReduceSum: (dpu_min_height, dpu_min_width),
        }

        self.sub_kernel_limits = {
            NpuBlockType.Default: (8, 8),
            NpuBlockType.VectorProduct: (1, 1),
            NpuBlockType.ConvolutionMxN: (8, 8),
            NpuBlockType.Pooling: (8, 8),
            NpuBlockType.ConvolutionDepthWise: (8, 8),
            NpuBlockType.ElementWise: (1, 1),
            NpuBlockType.ReduceSum: (8, 8),
        }

        # weights for scheduler search
        from .npu_performance import make_bandwidth_array

        self.bandwidth_weights = make_bandwidth_array()
        self.bandwidth_weights[MemArea.Sram] = 1.0
        self.bandwidth_weights[MemArea.Dram] = 10.0
        self.bandwidth_weights[MemArea.OnChipFlash] = 2.0
        self.bandwidth_weights[MemArea.OffChipFlash] = 20.0
        self.cycles_weight = 40
        self.max_sram_used_weight = 1000

        if self.is_spilling_enabled():
            self.max_sram_used_weight = 0

        # Shared Buffer Block allocations
        self.shram_bank_size = 1024  # bytes
        self.shram_size_bytes = accel_config.shram_banks * self.shram_bank_size
        self.shram_reserved_output_banks = 2
        self.shram_reserved_weight_banks = 0
        self.shram_reserved_unused_banks = 2 if accel_config.shram_banks > 16 else 0
        self.shram_total_banks = accel_config.shram_banks - self.shram_reserved_unused_banks
        self.shram_bank_granules = np.array(accel_config.shram_granules, np.int32)
        self.shram_lut_size = 2048
        # SHRAM base address of the activation lookup table
        self.shram_lut_address = self.shram_bank_size * self.available_shram_banks(True)

        # Build a map of acceptable IFM/OFM block configurations up to the maximum
        # IFM/OFM block size.
        ifm_block_max = self.get_ifm_block_size(32, self.ofm_block_max, Kernel(8, 8))
        self.block_config_map = dict()
        self.generate_block_config_map(Block(ifm_block_max.width, ifm_block_max.height, 128))

        # Setup supported operators and restriction checkers class
        self.supported_operators = SupportedOperators()

    # Returns available number of SHRAM banks depending on activation lookup table
    # being used or not
    def available_shram_banks(self, uses_activation_lut):
        banks = self.shram_total_banks
        if uses_activation_lut and self.shram_reserved_unused_banks == 0:
            banks -= 2
        return banks

    # Calculate block configuration for ALL known IFM operations and
    # accumulator sizes. Consumers will need to select their preferred
    # operation and bit-width at read-time.
    def generate_block_config(self, width, height, depth):
        # Number of bytes required for any SHRAM element for a FM of given dimensions.
        # For IFM: size = H*W*Align(D*BYTE_WIDTH, 8)
        # For ACC: size = H*W*Align(D,8)*BYTE_WIDTH
        d1 = round_up(depth, SHRAMElements.PreAlign)
        d2 = round_up(d1 * SHRAMElements.ByteSizes, SHRAMElements.PostAlign)
        size_bytes = (height * width) * d2

        # Convert byte size (rounded) to size in banks
        size_banks = round_up_divide(size_bytes, self.shram_bank_size)
        size_banks *= 2  # Double buffer the IFM/Acc (need twice as many banks)
        # Round bank requirement to bank granularity
        required_banks = round_up(size_banks, self.shram_bank_granules)
        return SHRAMBlockConfig(size_bytes, required_banks)

    @staticmethod
    def make_block_config_key(width, height, depth):
        return (int(height), int(width), int(depth))

    def get_block_config(self, width, height, depth):
        assert depth <= self.ofm_block_max.depth
        key = ArchitectureFeatures.make_block_config_key(width, height, depth)
        config = self.block_config_map.get(key, None)
        return config

    # Generate a key:value map of possible block configurations, where the
    # key is compounded from the block dimensions: 0x00HHWWCC
    def generate_block_config_map(self, block: Block):
        for h in range(1, block.height + 1):
            for w in range(1, block.width + 1):
                # All possible IFM/OFM depth values
                for c in [4, 8, 12, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128]:
                    key = ArchitectureFeatures.make_block_config_key(w, h, c)
                    self.block_config_map[key] = self.generate_block_config(w, h, c)

    def _generate_output_perf_tables(self, accel_config):
        if accel_config == Accelerator.Ethos_U55_32:
            self.output_cycles_per_elem = (2.0, 3.0, 3.0, 3.0, 4.0, 6.0, 1.0, 2.0)
            self.activation_cycles_per_elem = (1.0, 1.0, 0.0)
        elif accel_config == Accelerator.Ethos_U55_64:
            self.output_cycles_per_elem = (1.0, 1.5, 1.5, 1.5, 2.0, 3.0, 0.5, 1.0)
            self.activation_cycles_per_elem = (1.0, 1.0, 0.0)
        elif accel_config == Accelerator.Ethos_U55_128:
            self.output_cycles_per_elem = (0.75, 1.25, 0.75, 0.75, 1.0, 1.5, 0.25, 0.5)
            self.activation_cycles_per_elem = (1.0, 0.5, 0.0)
        elif accel_config in (Accelerator.Ethos_U55_256, Accelerator.Ethos_U65_256):
            self.output_cycles_per_elem = (0.625, 1.125, 0.5, 0.375, 0.5, 0.75, 0.125, 0.25)
            self.activation_cycles_per_elem = (1.0, 0.25, 0.0)
        else:
            assert accel_config == Accelerator.Ethos_U65_512
            self.output_cycles_per_elem = (0.3125, 0.5625, 0.25, 0.1875, 0.25, 0.375, 0.0625, 0.125)
            self.activation_cycles_per_elem = (0.5, 0.125, 0.0)

    def calc_ifm_block_depth(self, ifm_depth, ifm_bits):
        assert ifm_bits in (8, 16, 32)
        assert ifm_depth > 0
        ifm_depth = round_up(ifm_depth, self.ifm_ublock.depth)
        max_block_depth = 8 * 32 // ifm_bits
        return min(max_block_depth, ifm_depth)

    # Calculate the size of the IFM block given a depth, target OFM block and a kernel
    def get_ifm_block_size(
        self,
        ifm_block_depth,
        ofm_block: Block,
        kernel: Kernel,
        subkernel: Block = Block(8, 8, 65536),
        ifm_resampling_mode=resampling_mode.NONE,
    ):
        upscaling = 1 if ifm_resampling_mode == resampling_mode.NONE else 2
        # Height
        ifm_odd_2x_height_enable = 0
        dilated_kernel_height = ((kernel.height - 1) * kernel.dilation.y) + 1
        ifm_block_height = (
            (ofm_block.height - 1) * kernel.stride.y
            + min(subkernel.height, dilated_kernel_height)
            + ifm_odd_2x_height_enable
        ) // upscaling

        ifm_block_height = round_up(ifm_block_height, self.ofm_ublock.height)

        # Width
        ifm_odd_2x_width_enable = 0
        dilated_kernel_width = ((kernel.width - 1) * kernel.dilation.x) + 1
        ifm_block_width = (
            (ofm_block.width - 1) * kernel.stride.x
            + min(subkernel.width, dilated_kernel_width)
            + ifm_odd_2x_width_enable
        ) // upscaling

        ifm_block_width = round_up(ifm_block_width, self.ofm_ublock.width)

        return Block(ifm_block_width, ifm_block_height, ifm_block_depth)

    def is_spilling_enabled(self):
        """
        Spilling is a feature that allows the Ethos-U to use a dedicated SRAM as a cache for various types of data
        """
        return (
            self._mem_port_mapping(self.cache_mem_area) == MemArea.Sram and self.cache_mem_area != self.arena_mem_area
        )

    def _mem_port_mapping(self, mem_port):
        mem_port_mapping = {MemPort.Axi0: self.axi0_port, MemPort.Axi1: self.axi1_port}
        return mem_port_mapping[mem_port]

    def _set_default_sys_config(self):
        # ArchitectureFeatures.DEFAULT_CONFIG values
        if self.is_ethos_u65_system:
            # Default Ethos-U65 system configuration
            # Ethos-U65 Client-Server: SRAM (16 GB/s) and DRAM (12 GB/s)
            self.core_clock = 1e9
            self.axi0_port = MemArea.Sram
            self.axi1_port = MemArea.Dram
            self.memory_clock_scales[MemArea.Sram] = 1.0
            self.memory_clock_scales[MemArea.Dram] = 0.75  # 3 / 4
            self.memory_burst_length[MemArea.Sram] = 32
            self.memory_burst_length[MemArea.Dram] = 128
            self.memory_latency[MemArea.Sram][BandwidthDirection.Read] = 32
            self.memory_latency[MemArea.Sram][BandwidthDirection.Write] = 32
            self.memory_latency[MemArea.Dram][BandwidthDirection.Read] = 500
            self.memory_latency[MemArea.Dram][BandwidthDirection.Write] = 250
        else:
            # Default Ethos-U55 system configuration
            # Ethos-U55 High-End Embedded: SRAM (4 GB/s) and Flash (0.5 GB/s)
            self.core_clock = 500e6
            self.axi0_port = MemArea.Sram
            self.axi1_port = MemArea.OffChipFlash
            self.memory_clock_scales[MemArea.Sram] = 1.0
            self.memory_clock_scales[MemArea.OffChipFlash] = 0.125  # 1 / 8
            self.memory_burst_length[MemArea.Sram] = 32
            self.memory_burst_length[MemArea.OffChipFlash] = 128
            self.memory_latency[MemArea.Sram][BandwidthDirection.Read] = 32
            self.memory_latency[MemArea.Sram][BandwidthDirection.Write] = 32
            self.memory_latency[MemArea.OffChipFlash][BandwidthDirection.Read] = 64
            self.memory_latency[MemArea.OffChipFlash][BandwidthDirection.Write] = 64

    def _set_default_mem_mode(self):
        # ArchitectureFeatures.DEFAULT_CONFIG values
        if self.is_ethos_u65_system:
            # Default Ethos-U65 memory mode
            # Dedicated SRAM: the SRAM is only for use by the Ethos-U
            # The non-SRAM memory is assumed to be read-writeable
            self.const_mem_area = MemPort.Axi1
            self.arena_mem_area = MemPort.Axi1
            self.cache_mem_area = MemPort.Axi0
            self.cache_sram_size = 384 * 1024
        else:
            # Default Ethos-U55 memory mode
            # Shared SRAM: the SRAM is shared between the Ethos-U and the Cortex-M software
            # The non-SRAM memory is assumed to be read-only
            self.const_mem_area = MemPort.Axi1
            self.arena_mem_area = MemPort.Axi0
            self.cache_mem_area = MemPort.Axi0

    def _get_vela_config(self, vela_config_files, verbose_config):
        """
        Gets the system configuration and memory modes from one or more Vela configuration file(s) or uses some
        defaults.
        """

        # all properties are optional and are initialised to a value of 1 (or the equivalent)
        self.core_clock = 1
        self.axi0_port = MemArea(1)
        self.axi1_port = MemArea(1)
        self.memory_clock_scales = np.ones(MemArea.Size)
        self.memory_burst_length = np.ones(MemArea.Size, np.int)
        self.memory_latency = np.zeros((MemArea.Size, BandwidthDirection.Size), np.int)
        self.const_mem_area = MemPort(1)
        self.arena_mem_area = MemPort(1)
        self.cache_mem_area = MemPort(1)
        self.cache_sram_size = 1

        # read configuration file(s)
        self.vela_config = None

        if vela_config_files is not None:
            self.vela_config = ConfigParser()
            self.vela_config.read(vela_config_files)

        # read system configuration
        sys_cfg_section = "System_Config." + self.system_config

        if self.vela_config is not None and self.vela_config.has_section(sys_cfg_section):
            self.core_clock = float(self._read_config(sys_cfg_section, "core_clock", self.core_clock))
            self.axi0_port = MemArea[self._read_config(sys_cfg_section, "axi0_port", self.axi0_port)]
            self.axi1_port = MemArea[self._read_config(sys_cfg_section, "axi1_port", self.axi1_port)]

            for mem_area in (self.axi0_port, self.axi1_port):
                self.memory_clock_scales[mem_area] = float(
                    self._read_config(
                        sys_cfg_section, mem_area.name + "_clock_scale", self.memory_clock_scales[mem_area]
                    )
                )
                self.memory_burst_length[mem_area] = int(
                    self._read_config(
                        sys_cfg_section, mem_area.name + "_burst_length", self.memory_burst_length[mem_area]
                    )
                )
                self.memory_latency[mem_area][BandwidthDirection.Read] = int(
                    self._read_config(
                        sys_cfg_section,
                        mem_area.name + "_read_latency",
                        self.memory_latency[mem_area][BandwidthDirection.Read],
                    )
                )
                self.memory_latency[mem_area][BandwidthDirection.Write] = int(
                    self._read_config(
                        sys_cfg_section,
                        mem_area.name + "_write_latency",
                        self.memory_latency[mem_area][BandwidthDirection.Write],
                    )
                )
        elif self.system_config == ArchitectureFeatures.DEFAULT_CONFIG:
            self._set_default_sys_config()

        elif vela_config_files is None:
            raise CliOptionError("--config", vela_config_files, "Vela config file not specified")

        else:
            raise CliOptionError(
                "--system-config", self.system_config, f"Section {sys_cfg_section} not found in Vela config file",
            )

        # read the memory mode
        mem_mode_section = "Memory_Mode." + self.memory_mode

        if self.vela_config is not None and self.vela_config.has_section(mem_mode_section):
            self.const_mem_area = MemPort[
                self._read_config(mem_mode_section, "const_mem_area", self.const_mem_area.name)
            ]
            self.arena_mem_area = MemPort[
                self._read_config(mem_mode_section, "arena_mem_area", self.arena_mem_area.name)
            ]
            self.cache_mem_area = MemPort[
                self._read_config(mem_mode_section, "cache_mem_area", self.cache_mem_area.name)
            ]
            self.cache_sram_size = int(self._read_config(mem_mode_section, "cache_sram_size", self.cache_sram_size))

        elif self.memory_mode == ArchitectureFeatures.DEFAULT_CONFIG:
            self._set_default_mem_mode()

        elif vela_config_files is None:
            raise CliOptionError("--config", vela_config_files, "Vela config file not specified")

        else:
            raise CliOptionError(
                "--memory-mode", self.memory_mode, f"Section {mem_mode_section} not found in Vela config file",
            )

        # override sram to onchipflash
        if self._mem_port_mapping(self.const_mem_area) == MemArea.Sram:
            if self.const_mem_area == self.arena_mem_area == self.cache_mem_area:
                print(
                    "Info: Changing const_mem_area from Sram to OnChipFlash. This will use the same characteristics as"
                    " Sram."
                )
                if self.const_mem_area == MemPort.Axi0:
                    self.const_mem_area = MemPort.Axi1
                    self.axi1_port = MemArea.OnChipFlash
                else:
                    self.const_mem_area = MemPort.Axi0
                    self.axi0_port = MemArea.OnChipFlash
                self.memory_clock_scales[MemArea.OnChipFlash] = self.memory_clock_scales[MemArea.Sram]
                self.memory_burst_length[MemArea.OnChipFlash] = self.memory_burst_length[MemArea.Sram]
                self.memory_latency[MemArea.OnChipFlash] = self.memory_latency[MemArea.Sram]

        # check configuration
        if self._mem_port_mapping(self.const_mem_area) not in (
            MemArea.Dram,
            MemArea.OnChipFlash,
            MemArea.OffChipFlash,
        ):
            raise ConfigOptionError(
                "const_mem_area",
                self._mem_port_mapping(self.const_mem_area).name,
                "Dram or OnChipFlash or OffChipFlash",
            )

        if self._mem_port_mapping(self.arena_mem_area) not in (MemArea.Sram, MemArea.Dram):
            raise ConfigOptionError("arena_mem_area", self._mem_port_mapping(self.arena_mem_area).name, "Sram or Dram")

        if self._mem_port_mapping(self.cache_mem_area) != MemArea.Sram:
            raise ConfigOptionError("cache_mem_area", self._mem_port_mapping(self.cache_mem_area).name, "Sram")

        # assign existing memory areas
        self.permanent_storage_mem_area = self._mem_port_mapping(self.const_mem_area)
        self.feature_map_storage_mem_area = self._mem_port_mapping(self.arena_mem_area)
        self.fast_storage_mem_area = self._mem_port_mapping(self.cache_mem_area)

        self.sram_size = self.cache_sram_size if self.is_spilling_enabled() else 9999 * 1024 * 1024

        # display the system configuration and memory mode
        if verbose_config:
            print(f"System Configuration ({self.system_config}):")
            print(f"   core_clock = {self.core_clock}")
            print(f"   axi0_port = {self.axi0_port.name}")
            print(f"   axi1_port = {self.axi1_port.name}")
            for mem in (MemArea.Sram, MemArea.Dram, MemArea.OnChipFlash, MemArea.OffChipFlash):
                print(f"   {mem.name}_clock_scales = {self.memory_clock_scales[mem]}")
                print(f"   {mem.name}_burst_length = {self.memory_burst_length[mem]}")
                print(f"   {mem.name}_read_latency = {self.memory_latency[mem][BandwidthDirection.Read]}")
                print(f"   {mem.name}_write_latency = {self.memory_latency[mem][BandwidthDirection.Write]}")

            print(f"Memory Mode ({self.memory_mode}):")
            print(f"   const_mem_area = {self.const_mem_area.name}")
            print(f"   arena_mem_area = {self.arena_mem_area.name}")
            print(f"   cache_mem_area = {self.cache_mem_area.name}")
            print(f"   cache_sram_size = {self.cache_sram_size}")

            print("Architecture Settings:")
            print(f"   permanent_storage_mem_area = {self.permanent_storage_mem_area.name}")
            print(f"   feature_map_storage_mem_area = {self.feature_map_storage_mem_area.name}")
            print(f"   fast_storage_mem_area = {self.fast_storage_mem_area.name}")
            print(f"   sram_size = {self.sram_size}")

    def _read_config(self, section, key, current_value):
        """
        Reads a given key from a particular section in the Vela config file. If the section contains the 'inherit'
        option then we recurse into the section specified. If inherited sections result in multiple keys for a
        particular option then the key from the parent section is used, regardless of the parsing order
        """
        if not self.vela_config.has_section(section):
            raise ConfigOptionError("section", f"{section}. The section was not found in the Vela config file(s)")

        result = str(current_value)
        if self.vela_config.has_option(section, "inherit"):
            inheritance_section = self.vela_config.get(section, "inherit")
            # check for recursion loop
            if inheritance_section == section:
                raise ConfigOptionError(
                    "inherit", f"{inheritance_section}. This references its own section and recursion is not allowed",
                )
            result = self._read_config(inheritance_section, key, result)

        if self.vela_config.has_option(section, key):
            result = self.vela_config.get(section, key)

        return result


# Cache for default arch instances, as these are expensive to create
default_arch_cache = dict()


def create_default_arch(accelerator: Accelerator) -> ArchitectureFeatures:
    """Creates architecture features object using default settings"""
    if accelerator not in default_arch_cache:
        default_arch_cache[accelerator] = ArchitectureFeatures(
            vela_config_files=None,
            accelerator_config=accelerator.value,
            system_config=ArchitectureFeatures.DEFAULT_CONFIG,
            memory_mode=ArchitectureFeatures.DEFAULT_CONFIG,
            override_block_config=None,
            block_config_limit=None,
            max_blockdep=ArchitectureFeatures.MAX_BLOCKDEP,
            weight_estimation_scaling=1.0,
            verbose_config=False,
        )
    return default_arch_cache[accelerator]
