board
OCuLink Riser for the Supermicro AIOM Slot
Public Unreviewedby John Lauer
Passive OCP NIC 3.0 SFF card that breaks a Supermicro AIOM slot's PCIe x16 into four OCuLink 4i ports (4 x4, Gen4): 6-layer, 85 ohm, length-matched, DRC-clean KiCad project with Gerbers, BOM and CPL.
← Commit history
design/gen/check.pydeleted−76@@ -1,76 +0,0 @@-#!/usr/bin/env python3-"""Render and clearance-check the routing plan (container side, before KiCad)."""-import sys, os, json, math-sys.path.insert(0, os.path.dirname(__file__))-import matplotlib-matplotlib.use("Agg")-import matplotlib.pyplot as plt-from shapely.geometry import LineString, Point-from shapely.strtree import STRtree--COL = {"L1": "#d62728", "L3": "#2ca02c", "L5": "#1f77b4", "L6": "#9467bd"}---def shapes(tracks, vias):- """list of (layerset, net, geom)"""- out = []- for (lay, net, x1, y1, x2, y2, w) in tracks:- out.append(({lay}, net, LineString([(x1, y1), (x2, y2)]).buffer(w / 2, cap_style=1), ("t", lay, x1, y1, x2, y2)))- for (x, y, net, d, h) in vias:- out.append(({"L1", "L3", "L5", "L6"}, net, Point(x, y).buffer(d / 2), ("v", x, y)))- return out---def clearance(items, clr=0.15, extra=()):- geoms = [g for (_, _, g, _) in items]- tree = STRtree(geoms)- bad = []- for i, (ls, net, g, tag) in enumerate(items):- for j in tree.query(g.buffer(clr)):- if j <= i:- continue- ls2, net2, g2, tag2 = items[j]- if net2 == net or not (ls & ls2):- continue- dd = g.distance(g2)- if dd < clr - 1e-6:- bad.append((round(dd, 3), net, net2, sorted(ls & ls2)[0], tag[:4], tag2[:4]))- return bad---def render(tracks, vias, path, outline=None, extra_polys=(), xlim=(0, 76), ylim=(115, 0), layers=("L1", "L3", "L5", "L6"), dpi=110):- fig, ax = plt.subplots(figsize=(8, 12))- if outline:- xs, ys = zip(*outline)- ax.plot(xs, ys, "k-", lw=0.6)- for (lay, net, x1, y1, x2, y2, w) in tracks:- if lay in layers:- ax.plot([x1, x2], [y1, y2], "-", color=COL[lay], lw=max(0.3, w * 3), solid_capstyle="round", alpha=0.85)- for (x, y, net, d, h) in vias:- ax.add_patch(plt.Circle((x, y), d / 2, color="#444", lw=0, alpha=0.8))- for poly, c in extra_polys:- xs, ys = zip(*poly)- ax.fill(xs, ys, color=c, alpha=0.35, lw=0)- ax.set_xlim(*xlim); ax.set_ylim(*ylim); ax.set_aspect("equal")- ax.grid(True, lw=0.2)- fig.savefig(path, dpi=dpi, bbox_inches="tight")- plt.close(fig)---if __name__ == "__main__":- import hs- pairs, lines = hs.all_routes()- T = [t for p in pairs + lines for t in p.tracks]- V = [v for p in pairs + lines for v in p.vias]- bad = clearance(shapes(T, V), 0.15)- print(len(bad), "clearance violations")- for b in bad[:40]:- print(b)- os.makedirs("../design/plots", exist_ok=True)- render(T, V, "../design/plots/hs_all.png")- for k in range(4):- cx = hs.CX[k]- render(T, V, f"../design/plots/hs_port{k}_top.png", xlim=(cx - 9, cx + 9), ylim=(22, 2), dpi=160)- render(T, V, "../design/plots/hs_fan.png", xlim=(15, 75), ylim=(113, 86), dpi=150)- render(T, V, "../design/plots/hs_tune.png", xlim=(10, 76), ylim=(80, 34), dpi=150)- render(T, V, "../design/plots/hs_bus.png", xlim=(5, 76), ylim=(110, 76), dpi=150)