embedl_deploy.lattice.patterns package#

Module contents:

Public re-exports of Lattice pattern classes.

Users import from here:

from embedl_deploy.lattice.patterns import LatticeConv2dPattern
class embedl_deploy.lattice.patterns.FlattenToReshapePattern[source]#

Bases: Pattern

Replace flatten with an equivalent static reshape.

Lattice does not support flatten as a stand-alone op but does support reshape to a fully-static target shape. When the input shape of the flatten node is known (via ShapeProp) the dimensions outside [start_dim, end_dim] are kept verbatim and the flattened span is collapsed to a single -1 axis, producing a statically-shaped reshape call equivalent to the original flatten.

Matches all three flatten spellings: the Flatten module, the torch.flatten function, and the Tensor.flatten method.

Note

The replacement reshape bakes in the batch dimension from the traced shape (typically 1). This is intentional: Lattice hardware targets a fixed batch size of 1, so the resulting model is not expected to handle variable batch sizes.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _flatten_to_reshape>,)#

The factories to make replacements for each matched tree, if used.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_convertible_flatten>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeC2fChunkPattern[source]#

Bases: Pattern

Replace a C2f chunk with two parallel branches.

The C2f (CSP Bottleneck with 2 convolutions - Fast) module in YOLOv8 uses chunk to divide the output of a Conv2d BatchNorm2d Activation chain into two channel halves. Lattice hardware does not support the ONNX Split operator that chunk decomposes to, so the convolution chain followed by a channel split is replaced with two independent parallel branches, each producing half the output channels.

The replacement handles the full chain between the Conv2d and the chunk:

  • Conv2d — weights and bias are sliced at the channel midpoint; each branch gets half the output filters.

  • BatchNorm2dweight, bias, running_mean, and running_var are split; num_batches_tracked is copied.

  • Activation (SiLU, ReLU, etc.) — deep-copied for each branch.

All downstream getitem consumers of the chunk output are rewired to use the appropriate branch’s output directly.

This pattern requires that the convolution has an even number of output channels, that exactly two getitem consumers (indices 0 and 1) exist on the chunk node, and that every node in the chain from Conv2d to chunk has exactly one user.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_c2f_branches>,)#

The factories to make replacements for each matched tree, if used.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

classmethod replace(pattern_match: PatternMatch) list[Node][source]#

Rewire the chunk’s getitem consumers onto the branches.

graft builds the two parallel branches (recording their outputs in tree_match.meta) and replace_tree erases the matched Conv chunk chain, pointing every getitem at the second-half branch output. This override then redirects getitem(0) to the first-half branch and getitem(1) to the second-half branch and drops the now-redundant getitem nodes — the two-output fan-out that the linear replace_tree contract cannot express on its own.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_c2f_conv>, Wildcard(check=<function _is_single_user_bn_or_act>, quantifier='*', nodes=()), <function _is_c2f_chunk>)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeCBSRAdvancedPattern[source]#

Bases: Pattern

Match Conv2d -> [BatchNorm2d] -> Activation and fuse into CBSR.

The BatchNorm2d is optional — both Conv -> BN -> Act and Conv -> Act chains are matched. The activation must be ReLU or LatticeLeakyReLU. The convolution must have Lattice-supported parameters (kernel in {1, 3, 5, 7}, stride in {1, 2}, dilation == 1); convolutions outside the supported set are silently skipped.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function make_fused.<locals>._make>,)#

The factories to make replacements for each matched tree, if used.

phase: Phase = 'fusion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_cbsr_conv_advanced>, Wildcard(check=<class 'torch.nn.modules.batchnorm.BatchNorm2d'>, quantifier='?', nodes=()), torch.nn.modules.activation.ReLU | embedl_deploy._internal.lattice.modules.activation.LatticeLeakyReLU)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeCBSRPattern[source]#

Bases: Pattern

Match Conv2d -> [BatchNorm2d] -> Activation and fuse into CBSR.

The BatchNorm2d is optional — both Conv -> BN -> Act and Conv -> Act chains are matched. The activation must be ReLU or LatticeLeakyReLU. The convolution must have Lattice-supported parameters (kernel in {1, 3}, stride in {1, 2}, dilation == 1); convolutions outside the supported set are silently skipped.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function make_fused.<locals>._make>,)#

The factories to make replacements for each matched tree, if used.

phase: Phase = 'fusion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_cbsr_conv>, Wildcard(check=<class 'torch.nn.modules.batchnorm.BatchNorm2d'>, quantifier='?', nodes=()), torch.nn.modules.activation.ReLU | embedl_deploy._internal.lattice.modules.activation.LatticeLeakyReLU)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeConv2dAdvancedPattern[source]#

Bases: Pattern

Snap a Conv2d to Lattice’s advanced-kernel set.

Lattice advanced hardware supports 1×1, 3×3, 5×5, and 7×7 convolutions. 3×3 allows stride 1 or 2; all other kernel sizes require stride 1. Non-conforming convolutions are replaced by a LatticeConv2dAdvanced, whose constructor snaps the kernel to the nearest of {1, 3, 5, 7} and the stride according to the snapped kernel size. Padding is set to kernel_size // 2.

Weights and bias are preserved when only stride and/or padding needed snapping. When the kernel size itself is snapped the replacement has freshly initialized weights.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_lattice_advanced_conv>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_nonconforming_advanced_conv2d>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeConv2dPattern[source]#

Bases: Pattern

Snap an out-of-spec Conv2d to Lattice’s supported set.

Lattice hardware accepts only 1×1 and 3×3 convolutions with stride 1 or 2 (and stride 1 is mandatory for the 1×1 kernel). Convolutions outside this set are replaced by a LatticeConv2d, whose constructor performs the snapping.

Weights and bias are preserved when only stride and/or padding needed snapping (the weight tensor shape is unchanged). When the kernel size itself is snapped the replacement has freshly initialized weights, since the source kernel cannot be meaningfully reused at the new shape.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_lattice_conv>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_nonconforming_conv2d>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeGELUToReLUPattern[source]#

Bases: Pattern

Replace GELU with ReLU.

Lattice hardware does not support GELU activations. Any GELU instance is replaced by a ReLU and a warning is logged advising retraining.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_relu_from_activation>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function LatticeGELUToReLUPattern.<lambda>>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeGlobalAvgPoolPattern[source]#

Bases: Pattern

Normalize any global average pool to AdaptiveAvgPool2d((1, 1)).

Lattice hardware represents the classification-tail pool as an AdaptiveAvgPool2d with output_size == (1, 1). Any other module that effectively performs a global average pool over a 4-D input (an AdaptiveAvgPool2d with the scalar shorthand 1 or with a None axis equal to the input spatial size, or an AvgPool2d whose kernel covers the full spatial extent) is rewritten to this canonical form.

The pattern is a no-op for inputs already in canonical form, so it converges in a single conversion pass without infinite looping.

Requires shape metadata on the input node, propagated by ShapeProp (the transform driver runs this automatically between conversion iterations).

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_lattice_global_pool>,)#

The factories to make replacements for each matched tree, if used.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_nonconforming_global_avg_pool>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeLeakyReLUPattern[source]#

Bases: Pattern

Snap a LeakyReLU negative slope to Lattice’s supported value.

Lattice hardware implements leaky ReLU with a fixed negative slope of 1/16 (0.0625). Any other slope is replaced by that value and a warning is logged advising retraining.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_lattice_leaky_relu>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_nonconforming_leaky_relu>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeMaxPool2dPattern[source]#

Bases: Pattern

Snap an out-of-spec MaxPool2d to Lattice’s supported set.

Lattice hardware supports only a 2×2 max-pool with stride 2 and zero padding. Any other configuration is replaced by that single canonical form, matching the stem rewrite performed by the Lattice export reference script.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_lattice_maxpool>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_nonconforming_maxpool2d>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeReLU6ToReLUPattern[source]#

Bases: Pattern

Replace ReLU6 with ReLU.

Lattice hardware does not support ReLU6 (Clip) activations. Any ReLU6 instance is replaced by a ReLU and a warning is logged advising retraining.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_relu_from_activation>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function LatticeReLU6ToReLUPattern.<lambda>>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeSPPFMaxPoolAdvancedPattern[source]#

Bases: Pattern

Replace three cascaded stride-1 MaxPool2d with kernel-matched convs.

Like LatticeSPPFMaxPoolPattern, this matches the full three-pool SPPF cascade and replaces it with Conv2d + BatchNorm2d + ReLU chains. The difference is the convolution kernel size: instead of always using 3×3, this pattern snaps to the nearest kernel from {3, 5, 7} to match the original pool’s receptive field whenever the advanced hardware supports it.

For example, a MaxPool2d(kernel_size=5, stride=1, padding=2) is replaced with Conv2d(c, c, 5, stride=1, padding=2) — preserving the 5×5 receptive field. The replacement is not mathematically equivalent — retraining is required.

Requires shape metadata on the input node, propagated by ShapeProp.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (functools.partial(<function _sppf_replacement>, build_fn=<function _build_sppf_conv_modules_advanced>),)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_sppf_maxpool2d>, <function _is_sppf_maxpool2d>, <function _is_sppf_maxpool2d>)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeSPPFMaxPoolPattern[source]#

Bases: Pattern

Replace three cascaded stride-1 MaxPool2d with Conv+BN+ReLU.

SPPF (Spatial Pyramid Pooling - Fast) modules use three cascaded MaxPool2d operations with stride 1 to expand the receptive field without reducing spatial resolution. Lattice hardware only supports MaxPool2d with kernel 2, stride 2, and zero padding — snapping a stride-1 pool to that canonical form would halve spatial dimensions and destroy the SPPF structure.

This pattern matches the full three-pool cascade at once and replaces all three with Conv2d(c, c, 3, stride=1, padding=1) + BatchNorm2d + ReLU chains. The cascaded 3×3 convolutions provide receptive field expansion (3→5→7) analogous to the original cascaded max pools (5→9→13), but the replacement is not mathematically equivalent — retraining is required.

Standalone stride-1 pools that do not feed torch.cat are left for LatticeMaxPool2dPattern to handle.

Requires shape metadata on the input node, propagated by ShapeProp.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (functools.partial(<function _sppf_replacement>, build_fn=<function _build_sppf_conv_modules>),)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_sppf_maxpool2d>, <function _is_sppf_maxpool2d>, <function _is_sppf_maxpool2d>)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeSiLUToReLUPattern[source]#

Bases: Pattern

Replace SiLU with ReLU.

Lattice hardware does not support SiLU activations. Any SiLU instance is replaced by a ReLU and a warning is logged advising retraining.

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_relu_from_activation>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function LatticeSiLUToReLUPattern.<lambda>>,)#

The pattern topology to match, if using tree-based matching.

class embedl_deploy.lattice.patterns.LatticeStride2ConvBnReLUPattern[source]#

Bases: Pattern

Rewrite Conv(stride=2)->BN->ReLU as Conv(stride=1)+MaxPool2d.

This pattern preserves convolution weights by moving the downsampling step into a following MaxPool2d(kernel_size=2, stride=2).

graft: tuple[Callable[[TreeMatch], tuple[Module | Node | Callable[[GraphModule, tuple[Node, ...]], list[Node]], ...]], ...] = (<function _make_stride2_conv_bn_relu_with_pool>,)#

The factories to make replacements for each matched tree, if used.

is_numerically_equivalent: bool = False#

Whether applying this pattern preserves numeric outputs.

phase: Phase = 'conversion'#

Pipeline phase this pattern belongs to.

tree: tuple[type[Module] | UnionType | Callable[[Node], bool] | Wildcard, ...] | Fork = (<function _is_stride2_conv_bn_relu_conv>, <class 'torch.nn.modules.batchnorm.BatchNorm2d'>, <class 'torch.nn.modules.activation.ReLU'>)#

The pattern topology to match, if using tree-based matching.