Source code for jitxexamples.patterns.si_point_to_point

"""Point-to-point timing and loss on a single-ended line.

A driver pad joins a receiver pad on one ordinary net. The constraint names
the two pads with ``Topology(begin, end)``; it connects nothing, and no ``>>``
is needed. ``Constrain(...).timing(1e-9).insertion_loss(1.0)`` sets the
limits, and ``.structure(SampleSubstrate.RS_50)`` puts the timed path on a
single-ended routing structure. Without a structure the constraint still
measures, but with a delay and loss that are not the structure's, and the
report adds ``Missing routing structure on Path: ...`` per segment.

The receiver, :py:class:`~jitxexamples.patterns.si_parts.ExampleTerminatedChip`,
carries a ``TerminatingPinModel`` on its pin, so the measurement runs into the
die: the package model's 10 ps and 0.2 dB are added. This line measures
114.529 ps and 0.556 dB; the same 20 mm span with no package model measures
104.529 ps and 0.356 dB (the lanes in
:py:mod:`~jitxexamples.patterns.si_diff_pair`). The limits and the model's
values are illustrative, not from a standard or a datasheet.

The runtime infers the path from routed copper, so one code ``Route`` closes
it. Before routing there is nothing to measure: a copy of this line with no
route (and no package model) reported only
``Unconnected Topology on Path: drv.io, rcv.io``.

Every object the design needs is stored on ``self``: the net, the route and
the constraint. One that is built and not stored logs ``lost during
instantiation`` and never reaches the report.

Checked with the design-issues query, run as a script from a project
root with that project's runtime running
(jitx 4.6.0rc10, runtime 4.6.0-rc.16)::

    import jitx

    from jitxexamples.patterns.si_point_to_point import PointToPointDesign


    def main() -> None:
        with jitx.runtime as rt:
            report = rt.submit(PointToPointDesign).issues(satisfied=True, wait=30)
            if not report.complete:
                print("report incomplete: raise wait and run again")
            for group in report.groups():
                print("met" if group.satisfied else "NOT MET", group.text)
                if len(group.issues) > 1:
                    for issue in group:
                        print("   ", issue.text)


    if __name__ == "__main__":
        main()

It printed::

    met Time: 114.529ps - Target: 500ps ± 500ps from drv.io to rcv.io
    met Loss: 0.556db - Target: 0.5db ± 0.5db from drv.io to rcv.io
    met Satisfied

Each limit gives one line per path: ``timing`` a ``Time``, ``insertion_loss``
a ``Loss``. A limit is printed as a window: ``timing(1e-9)`` reads
``500ps ± 500ps``, anything from 0 to 1 ns. ``met`` comes from
``group.satisfied``, the only verdict; the text reads the same met or unmet.

The last line is the Routing category's group: every code route was made.
It is not a constraint verdict.
"""

from __future__ import annotations

from jitx.circuit import Circuit, Route
from jitx.net import Topology
from jitx.sample import SampleDesign, SampleSubstrate
from jitx.si import Constrain

from jitxexamples.patterns.si_parts import ExampleChip, ExampleTerminatedChip


[docs] class PointToPoint(Circuit): """One single-ended line from a driver pad to a packaged receiver, constrained for delay and loss, and closed by one code route.""" def __init__(self) -> None: self.drv = ExampleChip().at(-10, 0) self.rcv = ExampleTerminatedChip().at(10, 0) self.line = self.drv.io + self.rcv.io self.route = Route(self.drv.io, self.rcv.io, layer=0) self.line_cst = ( Constrain(Topology(self.drv.io, self.rcv.io)) .timing(1e-9) .insertion_loss(1.0) .structure(SampleSubstrate.RS_50) )
[docs] class PointToPointDesign(SampleDesign): """The point-to-point line on the sample board.""" circuit = PointToPoint()