VSIKnowledge

Building a Twin

Building a twin from a Teamcenter interface definition

The pipeline turns what Teamcenter records about a system's interfaces into a vsiBuild command file, with every assumption it had to make written down beside the output. Three scripts, in order; each one's output is a file you can read.

1. Extract the interface data (a Teamcenter read)

python extract_icd.py --profile vm2606 --item-range 005095 005142 --out wildfire-icd.json

Reads, strictly read-only and disconnecting when done, the interface objects (Seg0Interface), the ports assigned to them (Seg0InterfaceAssignment, read per interface with expandGRMRelationsForSecondary), the exchange allocations that give each interface its signals (Seg0ExchangeAllocation to Seg0ItemFlow) and each port's direction (fnd0Direction). Ports bind to interfaces through Seg0InterfaceAssignment, not through Seg0Implements. The output JSON is the ICD the rest of the pipeline works from; the run that produced Wildfire's saw 103 interfaces on the tier, selected 48, and found 464 of 476 ports carrying an assignment.

2. Find which logical block owns each port

python port_owners.py --icd wildfire-icd.json --out owners.json

Port ownership is BOM structure: each port is a line under the owning block revision's structure. The script opens a BOM window per block, expands all levels, and records the immediate owner of every port plus the block tree. Without this, a 152-port model becomes 152 components and vsiBuild refuses it (the cap is 64 including a slot the fabric keeps).

3. Generate the command file

python icd_to_vsi.py -i wildfire-icd.json -m gateway_map.json -o wildfire_grouped.vsi.cmd --twin WildfireDT --owners owners.json

Options that matter:

  • --owners groups ports under their owning block so one block is one component; ports of the same protocol on one block merge (Ethernet always, others when vsiBuild's one port per protocol per component rule requires it), and the merges are reported.
  • --group-cap (default 63) is the component budget; the generator folds child blocks into parents to fit and lists what it folded.
  • --python-blocks REGEX emits matching blocks as Python components (see python-components). A matched block that carries an Ethernet port is kept C++ and the demotion is reported, because vsiBuild generates invalid Python for a component whose socket carries no connected signals.
  • --exclude-ports and --exclude-blocks drop by regex and list what they dropped; used for probe and duplicate objects on the MSP-2 tier.
  • --workspace sets where vsiBuild will write the twin. Use a short root such as D:\wfpy when any block is Python.

Every run writes OUT.assumptions.md next to the output. Read it before building. It lists, per bus, what was derived rather than read: which port is the Ethernet hub and the socket numbers chosen; that signals are typed int because Teamcenter records no type; which signal directions were declared to satisfy connect signals although the recorded direction said otherwise; frame layouts at 8 bits per signal; spokes omitted because both ends landed on one merged port; and the blocks demoted from Python.

How protocols are decided

Teamcenter records no interface protocol. gateway_map.json maps interface class names to VSI protocols and is deliberately a reviewable file rather than logic in code. The generator prefers Seg0Implements on the port when it exists, falls back to the name rules with a warning, and lists anything unresolved rather than dropping it. The grammar the generator emits per protocol is in reference/command-grammar; the six places the vendor PDF disagreed with the binary are marked there.

What comes out

For Wildfire: 63 components, 78 ports, 63 signal-definition lines, 118 TCP sockets in hub-and-spoke form across 20 Ethernet buses, 22 CAN nodes on one frame id, and 30 connect signals lines across eight signal-wired buses. The file is the input to running-and-controlling/build-and-run.

What the ICD does not carry, and how that shows up

  • No signals cross Ethernet sockets, so 25 components are trace-only and the checker lists them as "nothing to check".
  • No CAN bit layout, so frames are laid out 8 bits per signal in declaration order.
  • No socket roles or port numbers, so the first port on a bus is the hub and numbers are handed out from 8800.
  • No signal timing, so the glue's per-bus periods are a stimulus schedule, not the real rates.

Each of these is an open item against the Teamcenter model (roadmap rm-xq7x89ob), not against the generator, which reports them rather than inventing values.

Source: innexis-vsi/extract_icd.py, port_owners.py, icd_to_vsi.py, gateway_map.json, README.md (EXERCISED 2026-08-20 to 2026-09-08) · retrieved Tue Sep 08 2026 00:00:00 GMT+0000 (Coordinated Universal Time)