symbols module#

Symbol partitioning and pad-mapping helpers for the VP1002 component.

The generated component (xcvp1002) stays declarative: it yields SymbolPartition records and (port, (row, col)) ball assignments; the two builders here turn those into jitxlib BoxSymbol instances and a PadMapping. Keeping the builders handwritten (and tiny) means the generated file contains data-shaped code only.

Ports are never stored in extra containers on the component — a Port may have only one home in the design tree (JITX raises “encountered multiple times” otherwise). Partitions are therefore exposed as a method that yields fresh records; tests assert symbol coverage by re-calling it.

Partitioning rules

At 1369 balls there is no single readable symbol: the partition is the part’s schematic, so it is stated as rules and held by checks. The policy lives in tools.generate_pinout.partition_symbols.

  • One box per structural group the source document defines. The AMD package pinout file (xcvp1002nfvi1369pkg.txt) has a Bank column, so every banked ball (I/O pins, the transceiver quad pins of the GTM and GTY banks, and the bank’s own supplies) goes to its bank’s box. On another part, take the grouping from the axis its pin table is organized by (I/O bank, transceiver quad, power domain, peripheral block). A grouping whose defining document cannot be named is invented.

  • A stated per-box ceiling for groups with no natural size. The bankless rails would otherwise be single boxes of hundreds of pins (689 GND balls, 84 VCCINT); they are chunked at MAX_PINS_PER_BOX, and the smaller bankless rails are packed together up to the same ceiling. SymbolPartition rejects a box over the cap at instantiation, and the test suite checks every box against it and checks that the generator’s copy of the constant matches. Pick the number by looking at the rendered sheet at the schematic’s page size, then keep the test that enforces it.

  • Every port in exactly one partition, asserted by a test (test_symbol_coverage in tests/test_js1_versal_fpga.py): no port seen twice, whether across boxes or inside one, and the union of all boxes equals every port of the component. The duplicate inside one box needs the test because nothing else reports it: BoxSymbol maps each port to one pin, so a port listed twice in a box keeps only its last pin and leaves the first unmapped.

  • Pins that belong to no group get their own box. Bankless dedicated and analog pins share one “Dedicated / analog singletons” box rather than being spread across other boxes for convenience.

  • Regular fixed-size slices only for parts with no functional structure: generic connectors, board-to-board headers, pin arrays. An FPGA, MCU or memory is partitioned by the structure its datasheet gives first.

Schematic groups

circuit.XCVP1002Circuit puts each box in its own SchematicGroup (one per Symbol from extract(self.fpga, Symbol)) so banks and rail chunks can be placed on separate sheets. A rail spread over several boxes stays one named net, and named nets are labeled in the schematic, so the boxes connect through net labels rather than drawn wires.

MAX_PINS_PER_BOX = 64#

Readability cap — no symbol box gets more pins than this.

class SymbolPartition(left=(), right=(), down=())[source]#

Bases: object

Ports of one schematic box: left/right rows, optional bottom column.

Parameters:
left: tuple[Port, ...] = ()#
right: tuple[Port, ...] = ()#
down: tuple[Port, ...] = ()#
ports()[source]#
Return type:

tuple[Port, ...]

build_symbols(partitions)[source]#

Turn partitions into one BoxSymbol each (empty sides skipped).

Return type:

list[BoxSymbol]

Parameters:

partitions (Iterable[SymbolPartition])

build_pad_mapping(lp, assignments, expected_total)[source]#

Map every port to its BGA pad, reconciling the ball count.

assignments carries zero-indexed (row, col) grid coordinates as emitted by the pinout generator; VersalBGA.get_pad takes the 1-indexed ball column, so the + 1 lives here and nowhere else.

Return type:

PadMapping

Parameters: