net.role

a role the net carries, derived from its name by the lexicon (rail, ground, feedback, switching, control, gate_drive); one row per role, the net-side twin of component.class

What it is

net.role(net, role) yields one row per ROLE a net carries: rail, ground, feedback, switching, control or gate_drive. A net can hold several at once, so a net that is both a rail by name and a switch node by suffix produces two rows.

It is the net-side twin of component.class. The engine derives roles from the naming lexicon at ingestion, and does not read them from the design file. net.attr holds the attributes a file declares.

For hardware engineers

A role is the engine’s reading of what a net IS, worked out from its name. 12V_OUT reads as a rail. 12V_SW reads as a rail by its prefix and a switch node by its suffix, and the second reading decides how rules treat it, because a switch node is not a 12V supply.

Four of the six roles exist to say “this is named after a rail and is not one”:

role typical names why it is not a rail
feedback 12V_FB the divider tap, at the regulator’s internal reference
switching 12V_SW, 12V_BOOT the power-stage node, swinging to the input rail
control 20V_EN, 12V_MODE1 a logic input, at the sequencer’s level
gate_drive 12V_VDRV the driver’s own supply, not the converter’s output

The first two must never be probed. The last two are ordinary signals, and a test point is welcome on them. They are excluded from rail rules only because they are not rails.

The patterns behind each role are lexicon config. A project extends them in the conventions: section of its project.yaml.

For software engineers

A tag set on a node, computed once at load. net.role is the whole set flattened to rows, so net.role(?n, ?r) enumerates and net.role(?n, "switching") filters. An empty result means no net name matched that vocabulary.

Go projector

netRoleFacts in stdlib/relations/facts.go walks Model.Nets() and, for each token in classify.AllNetRoles(), emits a row where Model.HasAnyRole holds. It goes through HasAnyRole rather than reading ir.Net.roles directly. So a net that skipped the ingestion stamp still answers, via the same name fallback every other role relation uses.

Datalog

Every role on every net:

net.role(?n, ?r) => ?n, ?r

The nets that are named after a rail without being one:

net.role(?n, ?r), ?r != "rail", ?r != "ground" => ?n, ?r

Not the same as net.rail

net.rail(?n) is Model.IsPowerRail, which holds for a net that is asserted-driven OR global OR a ground OR carries the rail role. So net.rail(?n) is a CONCLUSION, and net.role(?n, "rail") records what the lexicon STAMPED. The two are different sets on any real board. net.feedback(?n) and net.switching(?n) are exact shorthands for their net.role rows and may be used interchangeably with them.