main
John Lauer README: component table per the wiki format, open-source section, no duplicate hero; generators at gen/ 39a59ef 7d ago
#!/usr/bin/env python3
"""Delay of each differential pair: trace length per layer times sqrt(eeff_odd)/c, plus via barrels."""
import json, math, os
HERE = os.path.dirname(__file__)
Z = json.load(open(os.path.join(HERE, "..", "design", "zfinal.json")))
C_MM_PS = 0.299792458   # mm per ps
EEFF = {"L1": Z["L1"]["eeff_odd"], "L6": Z["L1"]["eeff_odd"], "L3": Z["L3"]["eeff_odd"], "L5": Z["L5"]["eeff_odd"]}
# JLC06161H-3313 z of each signal layer (mm from the top surface)
ZL = {"L1": 0.0, "L3": 0.035 + 0.0994 + 0.0152 + 0.55 + 0.0152, "L5": None, "L6": 1.6}
ZL["L5"] = ZL["L3"] + 0.1088 + 0.0152 + 0.55 + 0.0152
ER_VIA = 4.4   # barrel delay approximated through the laminate


def pair_delay(p):
    """ps for the n trace (equal to p: intra-pair skew is zero by construction)."""
    t = 0.0
    for (lay, net, x1, y1, x2, y2, w) in p.tracks:
        if net == p.nnet:
            t += math.hypot(x2 - x1, y2 - y1) * math.sqrt(EEFF[lay]) / C_MM_PS
    # via barrels along the signal path
    layers = []
    for nd in p.nodes:
        if not layers or layers[-1] != nd[2]:
            layers.append(nd[2])
    for a, b in zip(layers, layers[1:]):
        t += abs(ZL[a] - ZL[b]) * math.sqrt(ER_VIA) / C_MM_PS
    if p.end is not None and p.end[3]:    # via-in-pad up to the L1 pad
        t += ZL[p.end[2]] * math.sqrt(ER_VIA) / C_MM_PS
    return t


def per_mm(layer):
    return math.sqrt(EEFF[layer]) / C_MM_PS