si module#

Signal integrity constraints and modeling#

This module provides classes for defining signal integrity constraints, routing structures, and pin models.

class SignalConstraint[source]#

Bases: Structural, Generic

SignalConstraint is the primary way to apply signal integrity constraints in a design. They are meant to encapsulate a set of conditions that generate the constraints for a given signal or set of signals. While it is possible to apply constraints directly to a signal topology, it is recommended to define a reusable SignalConstraint from specifications instead.

Various examples of SignalConstraint implementations can be found in JITX Standard Library protocols.

This is a base class, create a subclass and override constrain() to implement your own signal constraint.

add(*constrain)[source]#
Return type:

None

Parameters:

constrain (BaseConstrain)

abstractmethod constrain(src, dst)[source]#

Called to apply implementation specific constraints. Note that all constraints should be added to the container by calling add() on self. It is valid to just set member attributes as well, as with everything in JITX, but be aware that your constraint may be used multiple times with different topologies, and thus be careful with overwriting values (e.g. some constraints may use a single DiffPairConstraint to constrain all its diff pairs).

Parameters:
  • src (T)

  • dst (T)

constrain_topology(src, dst)[source]#

Construct topology and apply the constraint end-to-end.

>>> class MyCircuit(Circuit):
...     a = ComponentCircuit()
...     b = ComponentCircuit()
...     cst = MyDiffPairConstraint()
...     def __init__(self):
...         with self.cst.constrain_topology(self.a.require(DiffPair), self.b.require(DiffPair)) as (src, dst):
...             # insert circuitry between src and dst here.
...             self += src >> dst
Parameters:
  • src (T)

  • dst (T)

class DiffPairConstraint(skew, loss, structure=None)[source]#

Bases: SignalConstraint[DiffPair]

Basic signal constraint for a differential pair signal topology. Provides a simple declration of skew and insertion loss requirements for a diff pair signal. Often used inside a more complex protocol signal constraint.

Parameters:
constrain(src, dst)[source]#

Called to apply implementation specific constraints. Note that all constraints should be added to the container by calling add() on self. It is valid to just set member attributes as well, as with everything in JITX, but be aware that your constraint may be used multiple times with different topologies, and thus be careful with overwriting values (e.g. some constraints may use a single DiffPairConstraint to constrain all its diff pairs).

Parameters:
class PinModel(delay, loss)[source]#

Bases: Critical

Simple model base class to describe signal propagation behavior as fixed delay and loss.

Parameters:
delay: Toleranced#
loss: Toleranced#
class BridgingPinModel(portA, portB=None, /, *, delay, loss)[source]#

Bases: PinModel, Structural, Generic

A pin model the describes the signal propagation through a component from one port to another at the frequency of interest. Ideally this is included in the component definition, but can also be added to the circuit when used, if it doesn’t already have one.

Parameters:
  • portA (T | tuple[T, T]) – The first port of the pin model.

  • portB (T | None) – The second port of the pin model.

  • delay (float | Toleranced) – The propagation delay through the component in seconds.

  • loss (float | Toleranced) – The insertion loss through the component in dB.

>>> class MyComponent(Component):
...     a = Port()
...     b = Port()
...     pin_model = BridgingPinModel(a, b, delay=6e-12, loss=3)
>>> class MyCircuit(Circuit):
...     r = Resistor()
...     def __init__(self):
...         self.aux_pin_model = BridgingPinModel(self.r.a, self.r.b, delay=6e-12, loss=3)
ports: tuple[T, T]#
class TerminatingPinModel(port, *, delay, loss)[source]#

Bases: PinModel, Structural, Generic

A pin model the describes the signal propagation from a component port into the relevant part of the component at frequency of interest. Ideally this is included in the component definition, but can also be added to the circuit when used, if it doesn’t already have one.

Parameters:
  • port (T) – The port of the pin model.

  • delay (float) – The propagation delay into the component in seconds.

  • loss (float) – The insertion loss into the component in dB.

>>> class MyComponent(Component):
...     a = Port()
...     pin_model = TerminatingPinModel(a, delay=6e-12, loss=3)
>>> class MyCircuit(Circuit):
...     ic = MyComponent()
...     def __init__(self):
...         self.aux_pin_model = TerminatingPinModel(self.ic.a, delay=6e-12, loss=3)
port: T#
class Constraint[source]#

Bases: Critical

Base class for all signal integrity constraints.

class BaseConstrain[source]#

Bases: Structural

Base class for applying constraints to signal topologies.

insertion_loss(high, low=0)[source]#

Apply an insertion loss constraint to the signal topology.

Parameters:
  • high (float | Toleranced) – Maximum insertion loss allowed.

  • low (float) – Minimum insertion loss allowed. Default is 0.

timing(high, low=0)[source]#

Apply a timing constraint to the signal topology.

Parameters:
  • high (Toleranced | float) – Maximum delay allowed.

  • low (float) – Minimum delay allowed. Default is 0.

class Constrain(topologies)[source]#

Bases: BaseConstrain

Constrain a single signal topology. This is most commonly used inside a SignalConstraint (which encapsulates more complex constraint configurations), and not to constrain a signal topology directly.

Parameters:

topologies (Sequence[Topology])

topologies: Sequence[Topology]#

Signal topologies to constrain.

structure(structure, *, ref_layers=None)[source]#

Apply a routing structure constraint to the signal topology.

Parameters:
  • structure (RoutingStructure) – The routing structure to apply.

  • ref_layers (Mapping[int, TypeAliasType] | None) – A mapping of layers to reference plane nets.

class BaseConstrainPairwise[source]#

Bases: BaseConstrain

Constrain signal topologies pairwise. This is a base class that declares the _pairwise() method.

timing_difference(high, low=None)[source]#

Apply a timing difference constraint between two signal topologies.

Parameters:
  • high (Toleranced | float) – Maximum timing difference allowed.

  • low (float | None) – Minimum timing difference allowed. If not provided, it is set to -high.

Return type:

Self

class ConstrainReferenceDifference(guide, topologies)[source]#

Bases: BaseConstrainPairwise

Constrain multiple signals to a single reference signal. Timing difference constraints will be applied to all signals, using the guide as reference. Timing and loss constraints apply to all, including the guide.

Parameters:
guide: Topology[Port]#
topologies: Sequence[Topology]#
class ConstrainDiffPair(topologies)[source]#

Bases: BaseConstrainPairwise

Apply constraints within diff-pair signals. Timing difference constraints will effectively be skew constraints. Timing and loss apply to all P and N individually.

Parameters:

topologies (Sequence[Topology[DiffPair]])

topologies: Sequence[Topology[DiffPair]]#
structure(structure, *, ref_layers=None)[source]#

Apply a differential routing structure constraint to the signal topology.

Parameters:
class TimingConstraint(min_delay, max_delay)[source]#

Bases: Constraint

A timing constraint that can be applied to a signal topology. The min_delay and max_delay are relative delays limits in units of seconds.

Parameters:
min_delay: float#

Minimum delay in seconds.

max_delay: float#

Maximum delay in seconds.

class InsertionLossConstraint(min_loss, max_loss)[source]#

Bases: Constraint

An insertion loss constraint that can be applied to a signal topology. The min_loss and max_loss are relative attenuation limits in units of dB.

Parameters:
min_loss: float#

Minimum insertion loss in decibels.

max_loss: float#

Maximum insertion loss in decibels.

class TimingDifferenceConstraint(min_delta, max_delta)[source]#

Bases: Constraint

A timing difference constraint that can be applied between two signal topologies. The min_delta and max_delta are relative skew limits in units of seconds between the two signal routes to be constrained. It is typical in most applications for min-delta to be negative and max-delta to be positive.

Parameters:
min_delta: float#

Minimum timing difference in seconds.

max_delta: float#

Maximum timing difference in seconds.

class RoutingStructure(layers=None, *, impedance, name=None)[source]#

Routing structure definition.

A symmetric_routing_layers() function is available to create a symmetric routing structure by specifying just half of the layers, assuming that it’s valid to use symmetric values.

>>> class MySubstrate(Substrate):
...     RS_50 = RoutingStructure(
...         impedance=50,
...         layers={
...             0: RoutingStructure.Layer(trace_width=0.2, velocity=150e6, insertion_loss=0.01),
...             1: RoutingStructure.Layer(trace_width=0.2, velocity=150e6, insertion_loss=0.01),
...             -2: RoutingStructure.Layer(trace_width=0.2, velocity=150e6, insertion_loss=0.01),
...             -1: RoutingStructure.Layer(trace_width=0.2, velocity=150e6, insertion_loss=0.01),
...         }
...     )
>>> class MySubstrate(Substrate):
...     RS_50 = RoutingStructure(
...         impedance=50,
...         layers=symmetric_routing_layers({
...             0: RoutingStructure.Layer(trace_width=0.2, velocity=150e6, insertion_loss=0.01),
...             1: RoutingStructure.Layer(trace_width=0.2, velocity=150e6, insertion_loss=0.01),
...         })
...     )
Parameters:
  • layers (Mapping[int, Layer] | None)

  • impedance (PlainQuantity | float)

  • name (str | None)

class NeckDown(*, trace_width=None, clearance=None, insertion_loss=None, velocity=None)[source]#

Neck down parameters for routing layer.

Parameters:
  • trace_width (float | None)

  • clearance (float | None)

  • insertion_loss (float | None)

  • velocity (float | None)

trace_width: float | None = None#
clearance: float | None = None#
insertion_loss: float | None = None#
velocity: float | None = None#
class Layer(*, trace_width, velocity, insertion_loss, clearance=None, neck_down=None)[source]#

Bases: Critical

Routing layer definition.

Parameters:
trace_width: float#

Width of traces on this layer.

velocity: float#

Velocity of signal for purposes of timing constraints, in millimeters per second.

insertion_loss: float#

Insertion loss of traces on this layer, in decibels per millimeter.

clearance: float | None = None#

Minimum clearance to other objects on this layer, in millimeters.

neck_down: NeckDown | None = None#

Routing parameters to apply in neckdown regions.

geometry(feature, width, **kwargs)[source]#

Add routing structure geometry for this routing layer. The generated feature will follow the shape if the created route, with the desired width, and can be on layers other than the current one. This is particularly useful if generating KeepOut voids in between this layer and a reference layer.

Note

It’s currently not supported to generate route KeepOuts.

Parameters:
  • feature (type[Feature]) – The feature type to add.

  • desired_width – The desired width of the feature that will follow the generated route.

  • width (float)

Return type:

Self

reference(layer, desired_width=None)[source]#

Specify that there should be a reference plane on the given layer, with the desired width surrounding the route. An attempt will be made to ensure there is a contiguous reference plane on that layer, but it is not guaranteed.

Parameters:
  • layer (int | Mapping[int, float]) – The layer number of the reference plane.

  • desired_width (float | None) – The desired width of the reference plane surrounding the route.

  • layers – Alternatively, a mapping of layer numbers to desired widths can be used to declare multiple reference planes at once.

Return type:

Self

fence(via, pattern=None, *, reference_layer=None)[source]#

Specify that there should be a via fence around the perimeter of the route. Unless otherwise specified, the vias will be given the same net as the first reference plane specified in the routing structure.

Parameters:
  • via (type[Via] | FenceVia) – The Via class to use for fencing.

  • pattern (ViaFencePattern | None) – The geometric pattern for fence placement.

  • fence – Alternatively, a prepared FenceVia can be used to specify the via and pattern in one go.

  • reference_layer (int | None) – An optional layer index to use as reference for the via fence. The generated vias will be given the same net as the reference plane on that layer. Note that this does not imply that a this layer is a reference plane for the signal. Note that the via fence will be generated regardless whether there actually is a reference plane on this layer. This can parameter can also be used, for example, to generate a via fence using planes far away from the signal (e.g. using through-hole vias), but are not actually reference planes, should that ever be necessary.

Return type:

Self

layers: Mapping[int, Layer]#
impedance: PlainQuantity#
property name: str#
class DifferentialRoutingStructure(layers=None, uncoupled_region=None, *, impedance, name=None)[source]#

Differential routing structure definition.

Parameters:
class NeckDown(*, trace_width=None, clearance=None, insertion_loss=None, velocity=None, pair_spacing=None)[source]#

Bases: NeckDown

Neck down parameters for differential routing layer.

Parameters:
  • trace_width (float | None)

  • clearance (float | None)

  • insertion_loss (float | None)

  • velocity (float | None)

  • pair_spacing (float | None)

pair_spacing: float | None = None#
class Layer(*, trace_width, velocity, insertion_loss, clearance=None, neck_down=None, pair_spacing)[source]#

Bases: Layer

Differential routing layer definition.

Parameters:
pair_spacing: float#

Internal spacing within the differential pair, in millimeters.

layers: Mapping[int, Layer]#
uncoupled_region: RoutingStructure | None = None#
impedance: PlainQuantity#
property name: str#
class ReferencePlanes(layers, /)[source]#

Bases: Context, Structurable

A context for specifying net assignments for reference layers used by routing structures. Nets of reference layers can also be specified directly when applying the routing structure, but this context allows a simple mechanism for declaring reference planes higher up in the design hierarchy.

>>> class MyCircuit(Circuit):
...     GND = Net()
...     planes = ReferencePlanes({0: GND, 1: GND})
...     c = MyComponent()
...     def __init__(self):
...         self += self.c.p[0] >> self.c.p[1]

Or if different reference planes are required for different parts of the design, the context can be activated separately. Note that this form can only be used inside the constructor function and will have no effect if used in the class variable context due to how JITX structural elements are instantiated.

>>> class MyCircuit(Circuit):
...     GND1 = Net()
...     GND2 = Net()
...     c = MyComponent()
...     protocol = MyProtocolConstraint()
...     def __init__(self):
...         with ReferencePlanes(self.GND1):
...             with self.protocol.constrain_topology(selc.c.p[0].to(self.c.p[1])) as src, dst:
...                 self += src >> dst
...         with ReferencePlanes(self.GND2):
...             with self.protocol.constrain_topology(selc.c.p[0].to(self.c.p[1])) as src, dst:
...                 self += src >> dst
Parameters:
  • layers (Mapping[int, TypeAliasType] | TypeAliasType) – A mapping of layer indices to nets. The nets will be assigned to the reference layers of the routing structure.

  • all – Optionally a single net can be specified which will used for all reference layers.

all: RefLayerType | None = None#
layers: Mapping[int, RefLayerType]#
class RoutingStructureConstraint(structure, *, ref_layers=None)[source]#

Bases: Structurable

A constraint to apply a routing structure to a signal topology.

Parameters:
structure: RoutingStructure#
ref_layers: Mapping[int, RefLayerType]#
class DifferentialRoutingStructureConstraint(structure, *, ref_layers=None)[source]#

Bases: Structurable

A constraint to apply a differential routing structure to a signal topology.

Parameters:
structure: DifferentialRoutingStructure#
ref_layers: Mapping[int, RefLayerType]#
symmetric_routing_layers(layers, invert_geometry=True)[source]#

Create a symmetric routing structure from a dictionary of routing layers.

Parameters:
  • layers (Mapping[int, TypeVar(T, bound= Layer)]) – Half of a routing structure layer set.

  • invert_geometry – If True, the geometry of the inverted layers will be flipped appropriayle. If not, the geometry will be left as is. Note that via fences cannot currently be inverted unless they’re using a via that’s symmetric around the center of the board, since there’s no practical way to specify a via for fencing on the other side of the board.

Return type:

dict[int, TypeVar(T, bound= Layer)]