net.connector_signal
a connector-facing signal net (not a rail, ground, no-connect, or power path), the scope the ESD rules share
What it is ¶
net.connector_signal(net) yields one row per net that leaves the board through a connector and is a
SIGNAL, not power. Both ESD rules share this scope, and the relation projects it so a
datalog-authored check can select the same nets the Go rules do.
A net qualifies when a connector sits on it and none of the exclusions apply: it is not a rail or ground (by name or by fact), not marked global or power-driven, not a deliberately unconnected pad, and no power pin is reachable from it through the series walk.
For hardware engineers ¶
An ESD review is actually about this set of lines. A signal that leaves the board is a path for a discharge to travel into whatever drives it, and a person touches the parts on the far end of a connector.
Each exclusion removes a kind of net, and an ESD verdict would otherwise misjudge it. A power rail arriving on the same connector is a different review with different rules (input protection: fuses, reverse blocking, inrush), so it is subtracted here rather than lumped in. A ground pin needs no clamp. A pad wired to nothing on purpose is not an exposure. Querying this relation on a real board is a quick way to check that the engine agrees with you about which lines are exposed, before trusting any ESD verdict built on top of it.
For software engineers ¶
It is a filtered projection over Nets(), 1:1 with in-scope nets. It is empty on a design with no
connectors. That empty answer is genuine rather than permissive, because a board that exposes nothing
has no ESD question to fail.
Every other part of the ESD guard stack could be composed from other relations, and this one could
not. The
protection predicates are reachability questions, and they became plain datalog once net.reaches carried
distance (WS3-112):
net.reaches(?n, ?rn, ?h), ?h <= 2, component.net(?t, ?rn), component.class(?t, "tvs")
The scope could not, because its guards read net ATTRIBUTES (global, power_driven) and the
no-connect channel. net.attr now exposes the attributes (agni 691). Reassembling the scope clause
by clause in datalog would still eventually drop a guard, and a dropped guard here is a false FAIL on
a rail or an unconnected pad rather than a missed defect.
Go projector ¶
externalSignalNetFacts in stdlib/relations/facts.go walks Model.Nets() and emits a row where
check.ExternalSignalNet holds. That function lives in core/check/guards.go beside the guards it
calls. esd-protection and esd-clamp-not-tvs evaluate that SAME predicate, so a datalog check
and the Go rules cannot disagree about scope. One row per in-scope net; zero rows when the
design has no connector-facing signals.
Datalog ¶
Every net an ESD review is about:
net.connector_signal(?n) => ?n
The unprotected ones have nothing clamping within two series crossings. The esd profile
requirement compiles to the same shape:
net.connector_signal(?n),
not_clamped(?n)
=> ?n
written out, since not_clamped is not built in:
clamped(?n) :- net.reaches(?n, ?rn, ?h), ?h <= 2, component.net(?t, ?rn), component.class(?t, "tvs");
exposed(?n) :- net.connector_signal(?n), not clamped(?n);
exposed(?n) => ?n
Which parts sit on the exposed lines, for a quick read of what is at risk:
net.connector_signal(?n), component.net(?r, ?n) => ?n, ?r