Source code for jitxexamples.patterns.si_daisy_chain
"""A daisy chain whose order is part of the design, declared with ``>>``.
A clock driver feeds ``load0`` and then ``load1``, as on a flyby clock or
address bus. ``self.drv.io >> self.load0.io >> self.load1.io`` builds a
``TopologyNet``, which records that order before anything is routed. Store
it like any net. ``>>`` is for this case only; a point-to-point constraint
needs ordinary nets.
The code routes run in chain order, driver to ``load0`` to ``load1``, so the
second path runs through the first load. One ``Constrain`` over both
topologies limits the delay to each load, and the routing structure is
applied once, by a structure-only constraint over the longest path
(``drv.io`` to ``load1.io``). That one structure covers the shorter path
too: no ``Missing routing structure`` line appears for it.
Putting a second structure on the shared ``drv.io`` to ``load0.io`` segment
broke the report: with an extra
``Constrain(Topology(drv.io, load0.io)).structure(RS_50)`` the same design
printed::
NOT MET Ambiguous routing structures meet at load0.io (2 alternatives)
met Time: 62.717ps - Target: 500ps ± 500ps from drv.io to load0.io
met Time: 125.434ps - Target: 500ps ± 500ps from drv.io to load1.io
NOT MET Overlapping routing structures along path from drv.io to load0.io (1 overlapped)
met Satisfied
The limits are illustrative.
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_daisy_chain import DaisyChainDesign
def main() -> None:
with jitx.runtime as rt:
report = rt.submit(DaisyChainDesign).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: 62.717ps - Target: 500ps ± 500ps from drv.io to load0.io
met Time: 125.434ps - Target: 500ps ± 500ps from drv.io to load1.io
met Satisfied
The structure-only constraint prints nothing, satisfied or not; its code is
the evidence that it applied. A copy of this design with the chain as a plain
``Net([drv.io, load0.io, load1.io])``, the same routes and the same
constraints, printed the same two ``Time`` lines (62.717 ps and 125.434 ps)
and met: on code routes, the routes fix the order. How the autorouter treats a chain with or
without ``>>`` has not been checked; this pattern routes from code only.
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
[docs]
class DaisyChain(Circuit):
"""A clock driver feeding two loads in a fixed order."""
def __init__(self) -> None:
self.drv = ExampleChip().at(-12, 0)
self.load0 = ExampleChip().at(0, 0)
self.load1 = ExampleChip().at(12, 0)
self.clk = self.drv.io >> self.load0.io >> self.load1.io
self.routes = [
Route(self.drv.io, self.load0.io, layer=0),
Route(self.load0.io, self.load1.io, layer=0),
]
self.clk_timing = Constrain(
[Topology(self.drv.io, self.load0.io), Topology(self.drv.io, self.load1.io)]
).timing(1e-9)
self.clk_structure = Constrain(Topology(self.drv.io, self.load1.io)).structure(
SampleSubstrate.RS_50
)
[docs]
class DaisyChainDesign(SampleDesign):
"""The daisy chain on the sample board."""
circuit = DaisyChain()