Source code for jitxexamples.demos.si_bga_optimization.constraints

"""Design-rule ``Tag`` subclasses and antipad fence-via rules for the
BGA escape design.

``StriplineDiffPairTag`` keys the 85 ohm differential routing structure
rule (built in ``bga_escape.BGALink``, which owns the GND reference
net); the antipad fence tags key the per-layer fence-via rules defined
at the bottom of this file.

JITX discovers ``DesignConstraint`` rules by walking the design object
tree, so a module-level rule takes effect only once it is reachable
from the design — the rules here are anchored as attributes of
``substrate.BGAEscapeSubstrate``.
"""

from jitx.constraints import Tag, ViaFencePattern, design_constraint
from jitxexamples.substrates.generic_20layer import Generic_Substrate


[docs] class StriplineDiffPairTag(Tag): """85 ohm differential stripline trunk net. Carries the differential routing structure via a tag rule (see ``BGALink``), so the diff pairs get their impedance-controlled cross-section without an explicit ``>>`` topology or a far-end terminal. """
# Per-layer antipad GND-pour fences. These are *mutually exclusive* — # each cavity is closed by exactly one fence via class — so each is its # own top-level Tag. (Tag inheritance would only help an additive # parent-rule-plus-child-override pattern; here a shared base rule would # double-fence every pour, and a parent-only base tag isn't registered in # the backend tag table. See PR #4 discussion.)
[docs] class AntipadFenceTag(Tag): """Signal-via antipad GND pour on L7 (Ground4), fenced by uGnd_L1_L7. Upper-reference-plane antipad fence around the BGA wave-port launch of any Signal4-deskew row pair. """
[docs] class Ground3AntipadFenceTag(Tag): """Signal-via antipad GND pour on L5 (Ground3), fenced by uGnd_L1_L5."""
[docs] class Ground2AntipadFenceTag(Tag): """Signal-via antipad GND pour on L3 (Ground2), fenced by uGnd_L1_L3."""
[docs] class DeskewAntipadFenceTag(Tag): """Deskew antipad GND pour on L9 (Ground5), fenced by uFence_L7_L9 (the Signal4 stripline-reference fence via)."""
[docs] class Ground4DeskewAntipadFenceTag(Tag): """Deskew antipad GND pour on L7 (Ground4), fenced by uFence_L5_L7."""
[docs] class Ground3DeskewAntipadFenceTag(Tag): """Deskew antipad GND pour on L5 (Ground3), fenced by uFence_L3_L5."""
[docs] class Ground2DeskewAntipadFenceTag(Tag): """Deskew antipad GND pour on L3 (Ground2), fenced by uFence_L1_L3."""
# ----------------------------------------------------------------------------- # Antipad fence-via pattern. # ----------------------------------------------------------------------------- BGA_ANTIPAD_FENCE_PITCH = 0.35 BGA_ANTIPAD_FENCE_OFFSET = 0.15 BGA_ANTIPAD_FENCE_MIN_EDGE_CLEARANCE = -0.02 def _antipad_fence_pattern(via_diameter: float) -> ViaFencePattern: edge_clearance = BGA_ANTIPAD_FENCE_OFFSET - (via_diameter / 2) if edge_clearance < BGA_ANTIPAD_FENCE_MIN_EDGE_CLEARANCE: raise ValueError( "BGA_ANTIPAD_FENCE_OFFSET places the fence via pad too far into " "the antipad region; minimum allowed edge clearance is " f"{BGA_ANTIPAD_FENCE_MIN_EDGE_CLEARANCE} mm; " f"got {edge_clearance:.3f} mm." ) return ViaFencePattern( pitch=BGA_ANTIPAD_FENCE_PITCH, offset=BGA_ANTIPAD_FENCE_OFFSET, initial_offset=BGA_ANTIPAD_FENCE_OFFSET, num_rows=1, input_shape_only=True, ) # Fence pattern around the signal-via antipad cavity. Sized off the # uGnd_L1_L7 via diameter so the fence-via pad sits just outside the # antipad opening. _ANTIPAD_FENCE_PATTERN = _antipad_fence_pattern( float(Generic_Substrate.uGnd_L1_L7.diameter) + 0.075 ) # ----------------------------------------------------------------------------- # Antipad fence-via rules. # ----------------------------------------------------------------------------- # Constraint ``priority`` breaks ties when generated fence vias from # competing rules want to land at the same X/Y; higher wins. The # antipad fence and deskew fence intentionally use DIFFERENT via # classes: the antipad fence closes only the upper cavity # (uGnd_L1_L<upper-ref>); the deskew fence closes only the lower # cavity (uFence_L<upper-ref>_L<lower-ref>). Unifying them to # uGnd_L1_L<lower-ref> catastrophically regressed Scd21 (gen7_nyquist # -32.62 -> -24.10 dB) by routing longer fence vias through the # signal layer adjacent to the launch. signal_via_antipad_fence = design_constraint(AntipadFenceTag(), priority=20).fence_via( Generic_Substrate.uGnd_L1_L7, _ANTIPAD_FENCE_PATTERN ) signal_via_antipad_fence_g3 = design_constraint( Ground3AntipadFenceTag(), priority=20 ).fence_via(Generic_Substrate.uGnd_L1_L5, _ANTIPAD_FENCE_PATTERN) signal_via_antipad_fence_g2 = design_constraint( Ground2AntipadFenceTag(), priority=9 ).fence_via(Generic_Substrate.uGnd_L1_L3, _ANTIPAD_FENCE_PATTERN) deskew_antipad_fence = design_constraint( DeskewAntipadFenceTag(), priority=10 ).fence_via(Generic_Substrate.uFence_L7_L9, _ANTIPAD_FENCE_PATTERN) deskew_antipad_fence_g4 = design_constraint( Ground4DeskewAntipadFenceTag(), priority=10 ).fence_via(Generic_Substrate.uFence_L5_L7, _ANTIPAD_FENCE_PATTERN) deskew_antipad_fence_g3 = design_constraint( Ground3DeskewAntipadFenceTag(), priority=10 ).fence_via(Generic_Substrate.uGnd_L1_L5, _ANTIPAD_FENCE_PATTERN) deskew_antipad_fence_g2 = design_constraint( Ground2DeskewAntipadFenceTag(), priority=10 ).fence_via(Generic_Substrate.uFence_L1_L3, _ANTIPAD_FENCE_PATTERN)