Skip to content

Component Registry

Register components using decorators for hardware kernels, backend implementations (HLS/RTL), and pipeline transformation steps. Components are discovered automatically from brainsmith, FINN, your project, and custom plugins.


kernel

kernel(obj=None, **kwargs)

Register a kernel class.

Decorator for hardware kernel implementations. Supports both @kernel and @kernel(name='CustomName') syntax.

Parameters:

Name Type Description Default
obj

Class being decorated (automatic when using @kernel without parens)

None
**kwargs

Optional configuration: name: Kernel name (default: cls.op_type or cls.name) infer_transform: Transform class for ONNX → kernel inference is_infrastructure: Mark as topology kernel like FIFO (default: False)

{}

Returns:

Type Description

The decorated class, unchanged but registered in component index

Examples:

>>> from brainsmith.registry import kernel
>>> from brainsmith.dataflow import KernelOp
>>>
>>> @kernel
... class MyKernel(KernelOp):
...     op_type = "MyKernel"
...
>>> @kernel(name="CustomName", is_infrastructure=True)
... class FIFO(HWCustomOp):
...     pass
Source code in brainsmith/registry/_decorators.py
def kernel(obj=None, **kwargs):
    """Register a kernel class.

    Decorator for hardware kernel implementations. Supports both `@kernel` and
    `@kernel(name='CustomName')` syntax.

    Args:
        obj: Class being decorated (automatic when using @kernel without parens)
        **kwargs: Optional configuration:
            name: Kernel name (default: cls.op_type or cls.__name__)
            infer_transform: Transform class for ONNX → kernel inference
            is_infrastructure: Mark as topology kernel like FIFO (default: False)

    Returns:
        The decorated class, unchanged but registered in component index

    Examples:
        >>> from brainsmith.registry import kernel
        >>> from brainsmith.dataflow import KernelOp
        >>>
        >>> @kernel
        ... class MyKernel(KernelOp):
        ...     op_type = "MyKernel"
        ...
        >>> @kernel(name="CustomName", is_infrastructure=True)
        ... class FIFO(HWCustomOp):
        ...     pass
    """

    def register(cls):
        kwargs.setdefault("name", getattr(cls, "op_type", cls.__name__))
        _register_kernel(cls, **kwargs)
        return cls

    return register(obj) if obj is not None else register

Example:

from brainsmith.dataflow import KernelOp
from brainsmith.registry import kernel

@kernel
class ElementwiseBinaryOp(KernelOp):
    """Polymorphic kernel for Add, Mul, Sub, Div operations."""

    def get_nodeattr_types(self):
        return {"func": ("s", True, "")}

backend

backend(obj=None, **kwargs)

Register a backend implementation.

Decorator for HLS or RTL backend implementations. Backends must specify their target kernel and implementation language.

Parameters:

Name Type Description Default
obj

Class being decorated (automatic when using @backend without parens)

None
**kwargs

Backend configuration: target_kernel (required): Kernel name this backend implements language (required): Implementation language ('hls' or 'rtl') name: Backend class name (default: cls.name) variant: Optional variant identifier

{}

Returns:

Type Description

The decorated class, unchanged but registered in component index

Raises:

Type Description
ValueError

If target_kernel or language missing

Examples:

>>> from brainsmith.registry import backend
>>>
>>> @backend(target_kernel='MVAU', language='hls')
... class MVAU_hls:
...     @staticmethod
...     def get_nodeattr_types():
...         return {...}
...
>>> @backend(target_kernel='MVAU', language='rtl', variant='fast')
... class MVAU_rtl_fast:
...     pass
Source code in brainsmith/registry/_decorators.py
def backend(obj=None, **kwargs):
    """Register a backend implementation.

    Decorator for HLS or RTL backend implementations. Backends must specify their
    target kernel and implementation language.

    Args:
        obj: Class being decorated (automatic when using @backend without parens)
        **kwargs: Backend configuration:
            target_kernel (required): Kernel name this backend implements
            language (required): Implementation language ('hls' or 'rtl')
            name: Backend class name (default: cls.__name__)
            variant: Optional variant identifier

    Returns:
        The decorated class, unchanged but registered in component index

    Raises:
        ValueError: If target_kernel or language missing

    Examples:
        >>> from brainsmith.registry import backend
        >>>
        >>> @backend(target_kernel='MVAU', language='hls')
        ... class MVAU_hls:
        ...     @staticmethod
        ...     def get_nodeattr_types():
        ...         return {...}
        ...
        >>> @backend(target_kernel='MVAU', language='rtl', variant='fast')
        ... class MVAU_rtl_fast:
        ...     pass
    """

    def register(cls):
        kwargs.setdefault("name", cls.__name__)
        _register_backend(cls, **kwargs)
        return cls

    return register(obj) if obj is not None else register

Example:

from finn.custom_op.fpgadataflow.hlsbackend import HLSBackend
from brainsmith.registry import backend, get_kernel

# Get the kernel class
ElementwiseBinaryOp = get_kernel('ElementwiseBinaryOp')

@backend(target_kernel='ElementwiseBinaryOp', language='hls')
class ElementwiseBinary_hls(ElementwiseBinaryOp, HLSBackend):
    """HLS backend for ElementwiseBinaryOp."""

    def get_nodeattr_types(self):
        # Combine attributes from kernel and backend
        my_attrs = ElementwiseBinaryOp.get_nodeattr_types(self)
        my_attrs.update(HLSBackend.get_nodeattr_types(self))
        return my_attrs

step

step(obj=None, **kwargs)

Register a pipeline transformation step.

Decorator for model transformation functions. Steps are discovered automatically and can be used in pipeline workflows.

Parameters:

Name Type Description Default
obj

Function or class being decorated (automatic when using @step without parens)

None
**kwargs

Optional configuration: name: Step name (default: function/class name)

{}

Returns:

Type Description

The decorated callable, unchanged but registered in component index

Examples:

>>> from brainsmith.registry import step
>>>
>>> @step
... def my_optimization(model, config):
...     # Transform model
...     return model
...
>>> @step(name="CustomStepName")
... def complex_transform(model, config):
...     return model
Source code in brainsmith/registry/_decorators.py
def step(obj=None, **kwargs):
    """Register a pipeline transformation step.

    Decorator for model transformation functions. Steps are discovered automatically
    and can be used in pipeline workflows.

    Args:
        obj: Function or class being decorated (automatic when using @step without parens)
        **kwargs: Optional configuration:
            name: Step name (default: function/class __name__)

    Returns:
        The decorated callable, unchanged but registered in component index

    Examples:
        >>> from brainsmith.registry import step
        >>>
        >>> @step
        ... def my_optimization(model, config):
        ...     # Transform model
        ...     return model
        ...
        >>> @step(name="CustomStepName")
        ... def complex_transform(model, config):
        ...     return model
    """

    def register(func_or_class):
        kwargs.setdefault("name", func_or_class.__name__)
        _register_step(func_or_class, **kwargs)
        return func_or_class

    return register(obj) if obj is not None else register

Example:

from brainsmith.registry import step
from qonnx.transformation.infer_shapes import InferShapes

@step(name='qonnx_to_finn')
def qonnx_to_finn_step(model, cfg):
    """Convert QONNX to FINN opset."""
    model = model.transform(ConvertQONNXtoFINN())
    model = model.transform(InferShapes())
    return model

source_context

source_context(source_name: str)

Context manager for setting component source during discovery.

Parameters:

Name Type Description Default
source_name str

Source identifier for components loaded in this context

required

Examples:

>>> with source_context('project'):
...     import project_kernels  # Registered with source='project'
Source code in brainsmith/registry/_decorators.py
def __init__(self, source_name: str):
    self.source_name = source_name
    self.token = None

__enter__

__enter__()

Enter context, set current source.

Source code in brainsmith/registry/_decorators.py
def __enter__(self):
    """Enter context, set current source."""
    self.token = _current_source.set(self.source_name)
    return self

__exit__

__exit__(exc_type, exc_val, exc_tb)

Exit context, restore previous source.

Source code in brainsmith/registry/_decorators.py
def __exit__(self, exc_type, exc_val, exc_tb):
    """Exit context, restore previous source."""
    _current_source.reset(self.token)
    return False

discover_components

discover_components(use_cache: bool = True, force_refresh: bool = False)

Discover components from all configured sources.

Discovers kernels, backends, and steps from: - Core brainsmith components - Project components (if configured) - Entry points from installed packages (e.g., FINN) - Custom component sources

Called automatically on first component lookup.

Parameters:

Name Type Description Default
use_cache bool

Use cached manifest if available

True
force_refresh bool

Ignore cache and regenerate manifest

False
Source code in brainsmith/registry/_discovery.py
def discover_components(use_cache: bool = True, force_refresh: bool = False):
    """Discover components from all configured sources.

    Discovers kernels, backends, and steps from:
    - Core brainsmith components
    - Project components (if configured)
    - Entry points from installed packages (e.g., FINN)
    - Custom component sources

    Called automatically on first component lookup.

    Args:
        use_cache: Use cached manifest if available
        force_refresh: Ignore cache and regenerate manifest
    """
    global _components_discovered

    # Handle force refresh - reset discovery state to allow re-discovery
    if force_refresh and _components_discovered:
        logger.debug("Force refresh requested - resetting discovery state")
        _components_discovered = False
        _component_index.clear()
        _discovered_sources.clear()

    # Skip if already discovered (and not forcing refresh)
    if _components_discovered:
        return

    with _measure_load("discover_components"):
        # Check cache_components setting and get project_dir
        from brainsmith.settings import get_config

        config = get_config()
        cache_enabled = config.cache_components

        # Use project_dir for manifest location (not CWD)
        manifest_path = config.project_dir / ".brainsmith" / "component_manifest.json"

        if not cache_enabled:
            logger.debug("Component caching disabled via cache_components setting")
            use_cache = False

        # Try cached manifest
        if use_cache and not force_refresh and manifest_path.exists():
            try:
                logger.debug(f"Loading component manifest from {manifest_path}")
                manifest = _load_manifest(manifest_path)

                # Check if cache is stale
                if _is_manifest_stale(manifest):
                    logger.debug("Manifest is stale - performing full discovery")
                    # Don't return, fall through to full discovery
                else:
                    _populate_index_from_manifest(manifest)
                    _components_discovered = True

                    logger.debug(f"Loaded {len(_component_index)} components from cache")
                    return
            except Exception as e:
                logger.warning(f"Failed to load manifest cache: {e}")
                logger.debug("Falling back to full discovery...")

        # Full discovery
        logger.debug("Discovering components from all sources...")

        # Get config for component sources
        config = get_config()

        # 1. Core brainsmith components (eager imports with source_context)
        # Decorators fire during import and auto-populate registry + index
        _discovered_sources.add(SOURCE_BRAINSMITH)
        with source_context(SOURCE_BRAINSMITH):
            pass  # noqa: E402

        logger.debug("Loaded core brainsmith components")

        # 2. Entry point components (FINN, etc.)
        _load_entry_point_components()

        # 3. Active project components (SOURCE_PROJECT at project root)
        _load_project_components(config)

        # 4. Other filesystem-based component sources (custom sources)
        _load_other_component_sources(config)

        _components_discovered = True

        # Link backends to their target kernels after all components indexed
        _link_backends_to_kernels()

        # Count components by type
        counts = {"step": 0, "kernel": 0, "backend": 0}
        for meta in _component_index.values():
            counts[str(meta.component_type)] += 1

        logger.info(
            f"Component discovery complete: "
            f"{counts['step']} steps, "
            f"{counts['kernel']} kernels, "
            f"{counts['backend']} backends"
        )

        # Save manifest for next time (only if caching is enabled)
        if cache_enabled:
            try:
                manifest = _build_manifest_from_index()
                _save_manifest(manifest, manifest_path)
                logger.debug(f"Regenerated and saved manifest cache to {manifest_path}")
            except Exception as e:
                logger.warning(f"Failed to save manifest cache: {e}")
        else:
            logger.debug("Skipping manifest save (caching disabled)")

reset_registry

reset_registry() -> None

Reset registry to uninitialized state.

Clears all discovered components and resets discovery flag. Primarily used for testing.

Example

from brainsmith.registry import reset_registry reset_registry()

... change configuration ...

from brainsmith.registry import discover_components discover_components() # Re-discover with new config

Source code in brainsmith/registry/__init__.py
def reset_registry() -> None:
    """Reset registry to uninitialized state.

    Clears all discovered components and resets discovery flag.
    Primarily used for testing.

    Example:
        >>> from brainsmith.registry import reset_registry
        >>> reset_registry()
        >>> # ... change configuration ...
        >>> from brainsmith.registry import discover_components
        >>> discover_components()  # Re-discover with new config
    """
    import brainsmith.registry._discovery as discovery_module
    import brainsmith.registry._state as registry_state

    registry_state._component_index.clear()
    registry_state._components_discovered = False
    discovery_module._components_discovered = False

is_initialized

is_initialized() -> bool

Check if registry has been initialized.

Returns:

Type Description
bool

True if component discovery has completed

Example

from brainsmith.registry import is_initialized is_initialized() False discover_components() is_initialized() True

Source code in brainsmith/registry/__init__.py
def is_initialized() -> bool:
    """Check if registry has been initialized.

    Returns:
        True if component discovery has completed

    Example:
        >>> from brainsmith.registry import is_initialized
        >>> is_initialized()
        False
        >>> discover_components()
        >>> is_initialized()
        True
    """
    from ._state import _components_discovered

    return _components_discovered

get_kernel

get_kernel(name: str) -> type

Get kernel class.

Accepts both short names ('LayerNorm') and qualified names ('user:LayerNorm'). Short names are resolved using source priority from settings.

Parameters:

Name Type Description Default
name str

Kernel name - either short ('LayerNorm') or qualified ('user:LayerNorm')

required

Returns:

Type Description
type

Kernel class

Raises:

Type Description
KeyError

If kernel not found in any source

Examples:

>>> LayerNorm = get_kernel('LayerNorm')  # Short name, uses source priority
>>> kernel = LayerNorm(onnx_node)
>>> CustomKernel = get_kernel('user:CustomKernel')  # Qualified name, explicit source
Source code in brainsmith/registry/_lookup.py
def get_kernel(name: str) -> type:
    """Get kernel class.

    Accepts both short names ('LayerNorm') and qualified names ('user:LayerNorm').
    Short names are resolved using source priority from settings.

    Args:
        name: Kernel name - either short ('LayerNorm') or qualified ('user:LayerNorm')

    Returns:
        Kernel class

    Raises:
        KeyError: If kernel not found in any source

    Examples:
        >>> LayerNorm = get_kernel('LayerNorm')  # Short name, uses source priority
        >>> kernel = LayerNorm(onnx_node)
        >>> CustomKernel = get_kernel('user:CustomKernel')  # Qualified name, explicit source
    """
    return _get_component(name, "kernel")

Example:

from brainsmith.registry import get_kernel

# Get kernel class by name
kernel_class = get_kernel('ElementwiseBinaryOp')

get_kernel_infer

get_kernel_infer(name: str) -> type

Get kernel's inference transform class.

Parameters:

Name Type Description Default
name str

Kernel name (short or qualified)

required

Returns:

Type Description
type

InferTransform class for ONNX → kernel conversion

Raises:

Type Description
KeyError

If kernel not found or has no InferTransform

Examples:

>>> InferLayerNorm = get_kernel_infer('LayerNorm')
>>> model = model.transform(InferLayerNorm())
Source code in brainsmith/registry/_lookup.py
def get_kernel_infer(name: str) -> type:
    """Get kernel's inference transform class.

    Args:
        name: Kernel name (short or qualified)

    Returns:
        InferTransform class for ONNX → kernel conversion

    Raises:
        KeyError: If kernel not found or has no InferTransform

    Examples:
        >>> InferLayerNorm = get_kernel_infer('LayerNorm')
        >>> model = model.transform(InferLayerNorm())
    """
    if not _components_discovered:
        discover_components()

    full_name = _resolve_component_name(name, "kernel")

    # Lookup in unified component index
    meta = _component_index.get(full_name)
    if not meta:
        available = list_kernels()
        raise KeyError(_format_not_found_error("kernel", full_name, available))

    # Load component to ensure metadata is populated
    _load_component(meta)

    # Check metadata for infer transform
    if meta.kernel_infer is None:
        raise KeyError(
            f"Kernel '{full_name}' has no InferTransform.\n"
            f"\nThis kernel does not have an associated shape inference transform.\n"
            f"Check that the kernel class defines 'infer_transform' attribute."
        )

    # Resolve lazy import specs and cache
    infer = resolve_lazy_class(meta.kernel_infer)
    if infer != meta.kernel_infer:
        # Cache the resolved class
        meta.kernel_infer = infer

    return infer

has_kernel

has_kernel(name: str) -> bool

Check if kernel exists.

Parameters:

Name Type Description Default
name str

Kernel name (with or without source prefix)

required

Returns:

Type Description
bool

True if kernel exists

Source code in brainsmith/registry/_lookup.py
def has_kernel(name: str) -> bool:
    """Check if kernel exists.

    Args:
        name: Kernel name (with or without source prefix)

    Returns:
        True if kernel exists
    """
    return _has_component(name, "kernel")

list_kernels

list_kernels(source: str | None = None) -> list[str]

List all available kernels.

Parameters:

Name Type Description Default
source str | None

Optional source filter (e.g., 'user', 'brainsmith')

None

Returns:

Type Description
list[str]

Sorted list of kernel names (with source prefixes)

Examples:

>>> kernels = list_kernels()  # All kernels
>>> user_kernels = list_kernels(source='user')  # Only user kernels
Source code in brainsmith/registry/_lookup.py
def list_kernels(source: str | None = None) -> list[str]:
    """List all available kernels.

    Args:
        source: Optional source filter (e.g., 'user', 'brainsmith')

    Returns:
        Sorted list of kernel names (with source prefixes)

    Examples:
        >>> kernels = list_kernels()  # All kernels
        >>> user_kernels = list_kernels(source='user')  # Only user kernels
    """
    return _list_components("kernel", source)

Example:

from brainsmith.registry import list_kernels

# List all available kernels
kernels = list_kernels()
for name in kernels:
    print(name)

get_backend

get_backend(name: str) -> type

Get backend class by name.

Accepts both short names ('LayerNorm_HLS') and qualified names ('user:LayerNorm_HLS_Fast'). Short names are resolved using source priority from settings.

Parameters:

Name Type Description Default
name str

Backend name - either short ('LayerNorm_HLS') or qualified ('user:LayerNorm_HLS_Fast')

required

Returns:

Type Description
type

Backend class

Raises:

Type Description
KeyError

If backend not found in any source

Examples:

>>> backend = get_backend('LayerNorm_HLS')  # Short name, uses source priority
>>> custom = get_backend('user:LayerNorm_HLS_Fast')  # Qualified name, explicit source
Source code in brainsmith/registry/_lookup.py
def get_backend(name: str) -> type:
    """Get backend class by name.

    Accepts both short names ('LayerNorm_HLS') and qualified names ('user:LayerNorm_HLS_Fast').
    Short names are resolved using source priority from settings.

    Args:
        name: Backend name - either short ('LayerNorm_HLS') or qualified ('user:LayerNorm_HLS_Fast')

    Returns:
        Backend class

    Raises:
        KeyError: If backend not found in any source

    Examples:
        >>> backend = get_backend('LayerNorm_HLS')  # Short name, uses source priority
        >>> custom = get_backend('user:LayerNorm_HLS_Fast')  # Qualified name, explicit source
    """
    return _get_component(name, "backend")

Example:

from brainsmith.registry import list_backends_for_kernel, get_backend

# Find backends for a kernel
backend_names = list_backends_for_kernel('ElementwiseBinaryOp', language='hls')

# Get backend classes
backends = [get_backend(name) for name in backend_names]

get_backend_metadata

get_backend_metadata(name: str) -> dict[str, Any]

Get backend metadata.

Parameters:

Name Type Description Default
name str

Backend name (with or without source prefix)

required

Returns:

Type Description
dict[str, Any]

Backend metadata dict with 'class', 'target_kernel', 'language' keys

Raises:

Type Description
KeyError

If backend not found

Source code in brainsmith/registry/_lookup.py
def get_backend_metadata(name: str) -> dict[str, Any]:
    """Get backend metadata.

    Args:
        name: Backend name (with or without source prefix)

    Returns:
        Backend metadata dict with 'class', 'target_kernel', 'language' keys

    Raises:
        KeyError: If backend not found
    """
    if not _components_discovered:
        discover_components()

    full_name = _resolve_component_name(name, "backend")
    logger.debug(f"Looking up backend metadata: {name}{full_name}")

    # Lookup in unified component index
    meta = _component_index.get(full_name)
    if not meta:
        available = list_backends()
        raise KeyError(_format_not_found_error("backend", full_name, available))

    # Load component to ensure metadata is populated
    _load_component(meta)

    # Build metadata dict from ComponentMetadata fields
    return {
        "class": meta.loaded_obj,
        "target_kernel": meta.backend_target,
        "language": meta.backend_language,
    }

list_backends

list_backends(source: str | None = None) -> list[str]

List all available backends.

Parameters:

Name Type Description Default
source str | None

Optional source filter (e.g., 'user', 'brainsmith')

None

Returns:

Type Description
list[str]

Sorted list of backend names (with source prefixes)

Examples:

>>> backends = list_backends()  # All backends
>>> user_backends = list_backends(source='user')  # Only user backends
Source code in brainsmith/registry/_lookup.py
def list_backends(source: str | None = None) -> list[str]:
    """List all available backends.

    Args:
        source: Optional source filter (e.g., 'user', 'brainsmith')

    Returns:
        Sorted list of backend names (with source prefixes)

    Examples:
        >>> backends = list_backends()  # All backends
        >>> user_backends = list_backends(source='user')  # Only user backends
    """
    return _list_components("backend", source)

list_backends_for_kernel

list_backends_for_kernel(kernel: str, language: str | None = None, sources: list[str] | None = None) -> list[str]

List backends that target a specific kernel.

Backends are stored directly on kernel metadata during discovery, so this is a simple field access followed by optional filtering.

Parameters:

Name Type Description Default
kernel str

Kernel name (with or without source prefix)

required
language str | None

Optional language filter ('hls' or 'rtl')

None
sources list[str] | None

Optional list of sources to search (default: all sources)

None

Returns:

Type Description
list[str]

Sorted list of backend names (with source prefixes)

Examples:

>>> # All backends for LayerNorm
>>> backends = list_backends_for_kernel('LayerNorm')
>>> print(backends)  # ['brainsmith:LayerNorm_hls', 'user:LayerNorm_rtl', ...]
>>> # Only HLS backends for LayerNorm
>>> hls_backends = list_backends_for_kernel('LayerNorm', language='hls')
>>> # Only user-provided backends
>>> user_backends = list_backends_for_kernel('LayerNorm', sources=['user'])
Source code in brainsmith/registry/_lookup.py
def list_backends_for_kernel(
    kernel: str, language: str | None = None, sources: list[str] | None = None
) -> list[str]:
    """List backends that target a specific kernel.

    Backends are stored directly on kernel metadata during discovery, so this
    is a simple field access followed by optional filtering.

    Args:
        kernel: Kernel name (with or without source prefix)
        language: Optional language filter ('hls' or 'rtl')
        sources: Optional list of sources to search (default: all sources)

    Returns:
        Sorted list of backend names (with source prefixes)

    Examples:
        >>> # All backends for LayerNorm
        >>> backends = list_backends_for_kernel('LayerNorm')
        >>> print(backends)  # ['brainsmith:LayerNorm_hls', 'user:LayerNorm_rtl', ...]

        >>> # Only HLS backends for LayerNorm
        >>> hls_backends = list_backends_for_kernel('LayerNorm', language='hls')

        >>> # Only user-provided backends
        >>> user_backends = list_backends_for_kernel('LayerNorm', sources=['user'])
    """
    if not _components_discovered:
        discover_components()

    # Resolve kernel name to full source:name format
    kernel_full = _resolve_component_name(kernel, "kernel")

    # Get kernel metadata
    kernel_meta = _component_index.get(kernel_full)
    if not kernel_meta:
        available = list_kernels()
        raise KeyError(_format_not_found_error("kernel", kernel_full, available))

    # Get backends list from kernel metadata (populated during discovery)
    candidate_backends = kernel_meta.kernel_backends or []

    matching = []

    # Filter candidates by language and sources (typically small set: 1-5 backends)
    for backend_name in candidate_backends:
        meta = _component_index[backend_name]

        # Filter by sources if specified
        if sources and meta.source not in sources:
            continue

        # Filter by language if specified
        # Metadata already populated during discovery - no loading needed!
        if language and meta.backend_language != language:
            continue

        matching.append(backend_name)

    return sorted(matching)

get_step

get_step(name: str)

Get step callable by name.

Accepts both short names ('streamline') and qualified names ('user:custom_step'). Short names are resolved using source priority from settings.

Parameters:

Name Type Description Default
name str

Step name - either short ('streamline') or qualified ('user:custom_step')

required

Returns:

Type Description

Callable step function or Step instance

Raises:

Type Description
KeyError

If step not found

Examples:

>>> streamline = get_step('streamline')  # Short name, uses source priority
>>> custom = get_step('user:custom_step')  # Qualified name, explicit source
Source code in brainsmith/registry/_lookup.py
def get_step(name: str):
    """Get step callable by name.

    Accepts both short names ('streamline') and qualified names ('user:custom_step').
    Short names are resolved using source priority from settings.

    Args:
        name: Step name - either short ('streamline') or qualified ('user:custom_step')

    Returns:
        Callable step function or Step instance

    Raises:
        KeyError: If step not found

    Examples:
        >>> streamline = get_step('streamline')  # Short name, uses source priority
        >>> custom = get_step('user:custom_step')  # Qualified name, explicit source
    """
    return _get_component(name, "step")

has_step

has_step(name: str) -> bool

Check if step exists without importing it.

Parameters:

Name Type Description Default
name str

Step name (with or without source prefix)

required

Returns:

Type Description
bool

True if step exists

Source code in brainsmith/registry/_lookup.py
def has_step(name: str) -> bool:
    """Check if step exists without importing it.

    Args:
        name: Step name (with or without source prefix)

    Returns:
        True if step exists
    """
    return _has_component(name, "step")

list_steps

list_steps(source: str | None = None) -> list[str]

List all available steps.

Parameters:

Name Type Description Default
source str | None

Optional source filter (e.g., 'user', 'brainsmith')

None

Returns:

Type Description
list[str]

Sorted list of step names (with source prefixes)

Examples:

>>> steps = list_steps()  # All steps
>>> user_steps = list_steps(source='user')  # Only user steps
Source code in brainsmith/registry/_lookup.py
def list_steps(source: str | None = None) -> list[str]:
    """List all available steps.

    Args:
        source: Optional source filter (e.g., 'user', 'brainsmith')

    Returns:
        Sorted list of step names (with source prefixes)

    Examples:
        >>> steps = list_steps()  # All steps
        >>> user_steps = list_steps(source='user')  # Only user steps
    """
    return _list_components("step", source)

get_component_metadata

get_component_metadata(name: str, component_type: str)

Get component metadata without loading.

Parameters:

Name Type Description Default
name str

Component name (short or qualified)

required
component_type str

Component type ('step', 'kernel', 'backend')

required

Returns:

Type Description

ComponentMetadata with source, import spec, and type-specific fields

Raises:

Type Description
KeyError

If component not found

Examples:

>>> meta = get_component_metadata('LayerNorm', 'kernel')
>>> print(meta.source, meta.import_spec.module)
brainsmith brainsmith.kernels.layernorm
Source code in brainsmith/registry/_lookup.py
def get_component_metadata(name: str, component_type: str):
    """Get component metadata without loading.

    Args:
        name: Component name (short or qualified)
        component_type: Component type ('step', 'kernel', 'backend')

    Returns:
        ComponentMetadata with source, import spec, and type-specific fields

    Raises:
        KeyError: If component not found

    Examples:
        >>> meta = get_component_metadata('LayerNorm', 'kernel')
        >>> print(meta.source, meta.import_spec.module)
        brainsmith brainsmith.kernels.layernorm
    """
    if not _components_discovered:
        discover_components()

    full_name = _resolve_component_name(name, component_type)

    if full_name not in _component_index:
        available = _list_components(component_type)
        raise KeyError(_format_not_found_error(component_type, full_name, available))

    return _component_index[full_name]

get_all_component_metadata

get_all_component_metadata() -> dict[str, Any]

Get all component metadata.

Returns:

Type Description
dict[str, Any]

Dict mapping full_name (source:name) to ComponentMetadata

Examples:

>>> all_components = get_all_component_metadata()
>>> for name, meta in all_components.items():
...     print(f"{name}: {meta.component_type}")
Source code in brainsmith/registry/_lookup.py
def get_all_component_metadata() -> dict[str, Any]:
    """Get all component metadata.

    Returns:
        Dict mapping full_name (source:name) to ComponentMetadata

    Examples:
        >>> all_components = get_all_component_metadata()
        >>> for name, meta in all_components.items():
        ...     print(f"{name}: {meta.component_type}")
    """
    if not _components_discovered:
        discover_components()

    return dict(_component_index)

get_domain_for_backend

get_domain_for_backend(backend_name: str) -> str

Get ONNX domain for backend by deriving from module path.

Derives domain directly from the backend class's module attribute, eliminating the need for reverse lookup through source_module_prefixes.

Parameters:

Name Type Description Default
backend_name str

Backend name (short or qualified)

required

Returns:

Type Description
str

ONNX domain string

Examples:

>>> get_domain_for_backend('brainsmith:LayerNorm_hls')
'brainsmith.kernels'
>>> get_domain_for_backend('finn:MVAU_hls')
'finn.custom_op.fpgadataflow.hls'
Source code in brainsmith/registry/_lookup.py
def get_domain_for_backend(backend_name: str) -> str:
    """Get ONNX domain for backend by deriving from module path.

    Derives domain directly from the backend class's __module__ attribute,
    eliminating the need for reverse lookup through source_module_prefixes.

    Args:
        backend_name: Backend name (short or qualified)

    Returns:
        ONNX domain string

    Examples:
        >>> get_domain_for_backend('brainsmith:LayerNorm_hls')
        'brainsmith.kernels'
        >>> get_domain_for_backend('finn:MVAU_hls')
        'finn.custom_op.fpgadataflow.hls'
    """
    from brainsmith.registry._domain_utils import derive_domain_from_module

    # Get backend metadata and load the class
    meta = get_component_metadata(backend_name, "backend")

    # Load the backend class to access its __module__ attribute
    backend_class = _load_component(meta)

    # Derive domain directly from the backend class's module path
    domain = derive_domain_from_module(backend_class.__module__)

    logger.debug(
        f"Derived domain '{domain}' for backend '{backend_name}' from module '{backend_class.__module__}'"
    )
    return domain

ComponentMetadata dataclass

ComponentMetadata(name: str, source: str, component_type: ComponentType, import_spec: ImportSpec, loaded_obj: Any | None = None, kernel_infer: Any | None = None, kernel_backends: list[str] | None = None, is_infrastructure: bool = False, backend_target: str | None = None, backend_language: str | None = None)

Metadata for registered component.

Contains all information needed to identify, load, and inspect a component.

Attributes:

Name Type Description
name str

Component name (without source prefix)

source str

Source identifier (e.g., 'brainsmith', 'finn', 'project')

component_type ComponentType

Component type (kernel, backend, or step)

import_spec ImportSpec

Import specification for lazy loading

loaded_obj Any | None

Loaded component instance (None if not yet loaded)

kernel_infer Any | None

InferTransform class (kernels only)

kernel_backends list[str] | None

List of backend names targeting this kernel (kernels only)

is_infrastructure bool

True for topology kernels like FIFO (kernels only)

backend_target str | None

Target kernel name (backends only)

backend_language str | None

Implementation language 'hls' or 'rtl' (backends only)

full_name property

full_name: str

Get source-prefixed name (e.g., 'brainsmith:LayerNorm').


ComponentType

Bases: Enum

Component type enumeration.

Attributes:

Name Type Description
KERNEL

Hardware kernel operation

BACKEND

HLS or RTL backend implementation

STEP

Pipeline transformation step

__str__

__str__() -> str

String representation for display and serialization.

Source code in brainsmith/registry/_metadata.py
def __str__(self) -> str:
    """String representation for display and serialization."""
    return self.name.lower()

from_string classmethod

from_string(s: str) -> ComponentType

Parse component type from string.

Parameters:

Name Type Description Default
s str

Component type string ('kernel', 'backend', or 'step')

required

Returns:

Type Description
ComponentType

Corresponding ComponentType enum value

Raises:

Type Description
ValueError

If string doesn't match any component type

Example

ComponentType.from_string('kernel') ComponentType.from_string('backend')

Source code in brainsmith/registry/_metadata.py
@classmethod
def from_string(cls, s: str) -> "ComponentType":
    """Parse component type from string.

    Args:
        s: Component type string ('kernel', 'backend', or 'step')

    Returns:
        Corresponding ComponentType enum value

    Raises:
        ValueError: If string doesn't match any component type

    Example:
        >>> ComponentType.from_string('kernel')
        <ComponentType.KERNEL: 1>
        >>> ComponentType.from_string('backend')
        <ComponentType.BACKEND: 2>
    """
    try:
        return cls[s.upper()]
    except KeyError:
        valid = ", ".join([t.name.lower() for t in cls])
        raise ValueError(f"Invalid component type: '{s}'. " f"Must be one of: {valid}")

ImportSpec dataclass

ImportSpec(module: str, attr: str)

Import specification for lazy component loading.

Attributes:

Name Type Description
module str

Python module path (e.g., 'brainsmith.kernels.layernorm')

attr str

Attribute name in module (e.g., 'LayerNorm')

See Also