# This file was generated by stubgen-pyx v0.2.6 from cuda_core/cuda/core/_module.pyx

from __future__ import annotations

from collections import namedtuple
from os import PathLike

import cython
from cuda.core._device import Device
from cuda.core._launch_config import LaunchConfig
from cuda.core._stream import Stream
from cuda.core._utils.cuda_utils import driver


class KernelAttributes:
    """Read-only view of a kernel's per-device attributes.

    The default view returned by :attr:`Kernel.attributes` is bound to
    the current device, resolved at attribute-access time. Use
    ``kernel.attributes[device]`` to obtain a view bound to a specific
    device (an :class:`int` device ordinal or :class:`Device`). Per-device
    views share the underlying cache so a value queried through one view
    is visible through the others.
    """

    def __init__(self, *args, **kwargs) -> None:
        ...

    def __getitem__(self, device: Device | int) -> KernelAttributes:
        """Return a view of these attributes bound to a specific device.

        Parameters
        ----------
        device : Device or int
            The device whose attributes to query. Accepts a :class:`Device`
            or a device ordinal (:class:`int`).

        Returns
        -------
        KernelAttributes
            A view bound to ``device`` that shares the underlying cache
            with this view.
        """

    @property
    def max_threads_per_block(self) -> int:
        """int : The maximum number of threads per block.
        This attribute is read-only."""

    @property
    def shared_size_bytes(self) -> int:
        """int : The size in bytes of statically-allocated shared memory required by this function.
        This attribute is read-only."""

    @property
    def const_size_bytes(self) -> int:
        """int : The size in bytes of user-allocated constant memory required by this function.
        This attribute is read-only."""

    @property
    def local_size_bytes(self) -> int:
        """int : The size in bytes of local memory used by each thread of this function.
        This attribute is read-only."""

    @property
    def num_regs(self) -> int:
        """int : The number of registers used by each thread of this function.
        This attribute is read-only."""

    @property
    def ptx_version(self) -> int:
        """int : The PTX virtual architecture version for which the function was compiled.
        This attribute is read-only."""

    @property
    def binary_version(self) -> int:
        """int : The binary architecture version for which the function was compiled.
        This attribute is read-only."""

    @property
    def cache_mode_ca(self) -> bool:
        """bool : Whether the function has been compiled with user specified option "-Xptxas --dlcm=ca" set.
        This attribute is read-only."""

    @property
    def max_dynamic_shared_size_bytes(self) -> int:
        """int : The maximum size in bytes of dynamically-allocated shared memory that can be used
        by this function."""

    @property
    def preferred_shared_memory_carveout(self) -> int:
        """int : The shared memory carveout preference, in percent of the total shared memory."""

    @property
    def cluster_size_must_be_set(self) -> bool:
        """bool : The kernel must launch with a valid cluster size specified.
        This attribute is read-only."""

    @property
    def required_cluster_width(self) -> int:
        """int : The required cluster width in blocks."""

    @property
    def required_cluster_height(self) -> int:
        """int : The required cluster height in blocks."""

    @property
    def required_cluster_depth(self) -> int:
        """int : The required cluster depth in blocks."""

    @property
    def non_portable_cluster_size_allowed(self) -> bool:
        """bool : Whether the function can be launched with non-portable cluster size."""

    @property
    def cluster_scheduling_policy_preference(self) -> int:
        """int : The block scheduling policy of a function."""

class KernelOccupancy:
    """This class offers methods to query occupancy metrics that help determine optimal
    launch parameters such as block size, grid size, and shared memory usage.
    """

    def __init__(self, *args, **kwargs) -> None:
        ...

    def max_active_blocks_per_multiprocessor(self, block_size: int, dynamic_shared_memory_size: int) -> int:
        """Occupancy of the kernel.

        Returns the maximum number of active blocks per multiprocessor for this kernel.

        Parameters
        ----------
            block_size: int
                Block size parameter used to launch this kernel.
            dynamic_shared_memory_size: int
                The amount of dynamic shared memory in bytes needed by block.
                Use `0` if block does not need shared memory.

        Returns
        -------
        int
            The maximum number of active blocks per multiprocessor.

        Note
        ----
            The fraction of the product of maximum number of active blocks per multiprocessor
            and the block size to the maximum number of threads per multiprocessor is known as
            theoretical multiprocessor utilization (occupancy).

        """

    def max_potential_block_size(self, dynamic_shared_memory_needed: int | driver.CUoccupancyB2DSize, block_size_limit: int) -> MaxPotentialBlockSizeOccupancyResult:
        """MaxPotentialBlockSizeOccupancyResult: Suggested launch configuration for reasonable occupancy.

        Returns the minimum grid size needed to achieve the maximum occupancy and
        the maximum block size that can achieve the maximum occupancy.

        Parameters
        ----------
            dynamic_shared_memory_needed: Union[int, driver.CUoccupancyB2DSize]
                The amount of dynamic shared memory in bytes needed by block.
                Use `0` if block does not need shared memory. Use C-callable
                represented by :obj:`~driver.CUoccupancyB2DSize` to encode
                amount of needed dynamic shared memory which varies depending
                on tne block size.
            block_size_limit: int
                Known upper limit on the kernel block size. Use `0` to indicate
                the maximum block size permitted by the device / kernel instead

        Returns
        -------
        :obj:`~MaxPotentialBlockSizeOccupancyResult`
            An object with `min_grid_size` and `max_block_size` attributes encoding
            the suggested launch configuration.

        Note
        ----
            Please be advised that use of C-callable that requires Python Global
            Interpreter Lock may lead to deadlocks.

        """

    def available_dynamic_shared_memory_per_block(self, num_blocks_per_multiprocessor: int, block_size: int) -> int:
        """Dynamic shared memory available per block for given launch configuration.

        The amount of dynamic shared memory per block, in bytes, for given kernel launch configuration.

        Parameters
        ----------
            num_blocks_per_multiprocessor: int
                Number of blocks to be concurrently executing on a multiprocessor.
            block_size: int
                Block size parameter used to launch this kernel.

        Returns
        -------
        int
            Dynamic shared memory available per block for given launch configuration.
        """

    def max_potential_cluster_size(self, config: LaunchConfig, *, stream: Stream) -> int:
        """Maximum potential cluster size.

        The maximum potential cluster size for this kernel and given launch configuration.

        Parameters
        ----------
            config: :obj:`~_launch_config.LaunchConfig`
                Kernel launch configuration. Cluster dimensions in the configuration are ignored.
            stream: :obj:`~Stream`
                Keyword-only. The stream on which this kernel is to be launched.
                Must be passed explicitly; pass ``device.default_stream`` to
                use the default stream.

        Returns
        -------
        int
            The maximum cluster size that can be launched for this kernel and launch configuration.
        """

    def max_active_clusters(self, config: LaunchConfig, *, stream: Stream) -> int:
        """Maximum number of active clusters on the target device.

        The maximum number of clusters that could concurrently execute on the target device.

        Parameters
        ----------
            config: :obj:`~_launch_config.LaunchConfig`
                Kernel launch configuration.
            stream: :obj:`~Stream`
                Keyword-only. The stream on which this kernel is to be launched.
                Must be passed explicitly; pass ``device.default_stream`` to
                use the default stream.

        Returns
        -------
        int
            The maximum number of clusters that could co-exist on the target device.
        """

class Kernel:
    """Represent a compiled kernel that had been loaded onto the device.

    Kernel instances can execution when passed directly into the
    :func:`~launch` function.

    Directly creating a :obj:`~_module.Kernel` is not supported, and they
    should instead be created through a :obj:`~_module.ObjectCode` object.

    """

    def __init__(self, *args, **kwargs) -> None:
        ...

    @property
    @cython.critical_section
    def attributes(self) -> KernelAttributes:
        """Get the read-only attributes of this kernel."""

    @property
    def num_arguments(self) -> int:
        """int : The number of arguments of this function"""

    @property
    def arguments_info(self) -> list[ParamInfo]:
        """list[ParamInfo]: (offset, size) for each argument of this function"""

    @property
    @cython.critical_section
    def occupancy(self) -> KernelOccupancy:
        """Get the occupancy information for launching this kernel."""

    @property
    def handle(self) -> object:
        """Return the underlying kernel handle object.

        .. caution::

            This handle is a Python object. To get the memory address of the underlying C
            handle, call ``int(Kernel.handle)``.
        """

    @property
    def _handle(self) -> object:
        ...

    @staticmethod
    def from_handle(handle, mod: ObjectCode | None=None) -> Kernel:
        """Creates a new :obj:`Kernel` object from a kernel handle.

        Parameters
        ----------
        handle : int
            Kernel handle representing the address of a foreign
            kernel object (CUkernel).
        mod : :obj:`ObjectCode`, optional
            The ObjectCode object associated with this kernel. Provides
            library lifetime for foreign kernels not created by
            cuda.core.
        """

    def __eq__(self, other: object) -> bool:
        ...

    def __hash__(self) -> int:
        ...

    def __repr__(self) -> str:
        ...

class ObjectCode:
    """Represent a compiled program to be loaded onto the device.

    This object provides a unified interface for different types of
    compiled programs that will be loaded onto the device.

    Note
    ----
    This class has no default constructor. If you already have a cubin that you would
    like to load, use the :meth:`from_cubin` alternative constructor. Constructing directly
    from all other possible code types should be avoided in favor of compilation through
    :class:`~cuda.core.Program`
    """

    def __init__(self, *args, **kwargs) -> None:
        ...

    @classmethod
    def _init(cls, module, code_type, *, name: str='', symbol_mapping: dict[str, str] | None=None) -> ObjectCode:
        ...

    @staticmethod
    def _reduce_helper(module, code_type, name, symbol_mapping):
        ...

    def __reduce__(self) -> tuple[object, ...]:
        ...

    @staticmethod
    def from_cubin(module: bytes | str | PathLike[str], *, name: str='', symbol_mapping: dict[str, str] | None=None) -> ObjectCode:
        """Create an :class:`ObjectCode` instance from an existing cubin.

        Parameters
        ----------
        module : Union[bytes, str, os.PathLike]
            Either a bytes object containing the in-memory cubin to load, or
            a file path object (or its string representation) pointing to the
            on-disk cubin to load.
        name : Optional[str]
            A human-readable identifier representing this code object.
        symbol_mapping : Optional[dict]
            A dictionary specifying how the unmangled symbol names (as keys)
            should be mapped to the mangled names before trying to retrieve
            them (default to no mappings).
        """

    @staticmethod
    def from_ptx(module: bytes | str | PathLike[str], *, name: str='', symbol_mapping: dict[str, str] | None=None) -> ObjectCode:
        """Create an :class:`ObjectCode` instance from an existing PTX.

        Parameters
        ----------
        module : Union[bytes, str, os.PathLike]
            Either a bytes object containing the in-memory ptx code to load, or
            a file path object (or its string representation) pointing to the
            on-disk ptx file to load.
        name : Optional[str]
            A human-readable identifier representing this code object.
        symbol_mapping : Optional[dict]
            A dictionary specifying how the unmangled symbol names (as keys)
            should be mapped to the mangled names before trying to retrieve
            them (default to no mappings).
        """

    @staticmethod
    def from_ltoir(module: bytes | str | PathLike[str], *, name: str='', symbol_mapping: dict[str, str] | None=None) -> ObjectCode:
        """Create an :class:`ObjectCode` instance from an existing LTOIR.

        Parameters
        ----------
        module : Union[bytes, str, os.PathLike]
            Either a bytes object containing the in-memory ltoir code to load,
            or a file path object (or its string representation) pointing to the
            on-disk ltoir file to load.
        name : Optional[str]
            A human-readable identifier representing this code object.
        symbol_mapping : Optional[dict]
            A dictionary specifying how the unmangled symbol names (as keys)
            should be mapped to the mangled names before trying to retrieve
            them (default to no mappings).
        """

    @staticmethod
    def from_fatbin(module: bytes | str | PathLike[str], *, name: str='', symbol_mapping: dict[str, str] | None=None) -> ObjectCode:
        """Create an :class:`ObjectCode` instance from an existing fatbin.

        Parameters
        ----------
        module : Union[bytes, str, os.PathLike]
            Either a bytes object containing the in-memory fatbin to load, or
            or a file path object (or its string representation) pointing to the
            on-disk fatbin to load.
        name : Optional[str]
            A human-readable identifier representing this code object.
        symbol_mapping : Optional[dict]
            A dictionary specifying how the unmangled symbol names (as keys)
            should be mapped to the mangled names before trying to retrieve
            them (default to no mappings).
        """

    @staticmethod
    def from_object(module: bytes | str, *, name: str='', symbol_mapping: dict[str, str] | None=None) -> ObjectCode:
        """Create an :class:`ObjectCode` instance from an existing object code.

        Parameters
        ----------
        module : Union[bytes, str]
            Either a bytes object containing the in-memory object code to load, or
            a file path string pointing to the on-disk object code to load.
        name : Optional[str]
            A human-readable identifier representing this code object.
        symbol_mapping : Optional[dict]
            A dictionary specifying how the unmangled symbol names (as keys)
            should be mapped to the mangled names before trying to retrieve
            them (default to no mappings).
        """

    @staticmethod
    def from_library(module: bytes | str, *, name: str='', symbol_mapping: dict[str, str] | None=None) -> ObjectCode:
        """Create an :class:`ObjectCode` instance from an existing library.

        Parameters
        ----------
        module : Union[bytes, str]
            Either a bytes object containing the in-memory library to load, or
            a file path string pointing to the on-disk library to load.
        name : Optional[str]
            A human-readable identifier representing this code object.
        symbol_mapping : Optional[dict]
            A dictionary specifying how the unmangled symbol names (as keys)
            should be mapped to the mangled names before trying to retrieve
            them (default to no mappings).
        """

    def get_kernel(self, name: str | bytes) -> Kernel:
        """Return the :obj:`~_module.Kernel` of a specified name from this object code.

        Parameters
        ----------
        name : str | bytes
            Name of the kernel to retrieve.

        Returns
        -------
        :obj:`~_module.Kernel`
            Newly created kernel object.

        """

    def get_module(self) -> driver.CUmodule:
        """Return a context-dependent :obj:`~driver.CUmodule` for legacy interop.

        Bridges the native :obj:`~driver.CUlibrary` (see :attr:`handle`) to a
        ``CUmodule`` via ``cuLibraryGetModule``, for use with legacy driver APIs
        that only accept ``CUmodule``.

        Returns
        -------
        :obj:`~driver.CUmodule`
            Module handle for the current CUDA context, suitable for legacy
            driver APIs that accept ``CUmodule``.
        """

    @property
    def code(self) -> CodeTypeT:
        """Return the underlying code object."""

    @property
    def name(self) -> str:
        """Return a human-readable name of this code object."""

    @property
    def code_type(self) -> str:
        """Return the type of the underlying code object."""

    @property
    def symbol_mapping(self) -> dict[str, str]:
        """Return a copy of the symbol mapping dictionary."""

    @property
    def handle(self) -> object:
        """Return the native, context-independent :obj:`~driver.CUlibrary` handle.

        Used by ``cuda.core`` and newer driver library APIs. For legacy APIs
        that only accept a ``CUmodule``, use :meth:`get_module` instead.

        .. caution::

            This handle is a Python object. To get the memory address of the underlying C
            handle, call ``int(ObjectCode.handle)``.
        """

    def __eq__(self, other: object) -> bool:
        ...

    def __hash__(self) -> int:
        ...

    def __repr__(self) -> str:
        ...
__all__ = ['Kernel', 'ObjectCode']
MaxPotentialBlockSizeOccupancyResult = namedtuple('MaxPotentialBlockSizeOccupancyResult', ('min_grid_size', 'max_block_size'))
ParamInfo = namedtuple('ParamInfo', ['offset', 'size'])
CodeTypeT = bytes | bytearray | str