Registries and schemas¶
Every number the ADK’s own rule decks check, and every layer number the ADK core
still knows, lives in a small JSON registry under config/ in the ADK
repository. PDK-specific layer numbers and per-method numbers live in adapters,
which is the point of the adapter axes. Nothing
normative is hardcoded in a rule deck or in a generator. This page describes each
registry, who reads it, and what its values are worth.
Alongside the registries, config/schema/ holds the JSON Schemas: three that
describe the registries themselves, and three that describe the per-assembly
sidecar files the toolchain exchanges.
Version discipline¶
All four registries carry a version key, and all four read
0.2.0 today. That is not a coincidence maintained by hand: a test
in the ADK reads the first released heading in CHANGELOG.md and asserts that
the VERSION file and every config/*.json version key equal it. A skew
between them fails CI.
The sidecar schemas version independently, because they describe a data contract
between separate tools rather than the ADK release. All three currently stand at
1.0.0, and their readers pin them exactly: a boundary manifest, a
per-method interconnect file or a pillar manifest whose version is anything
other than the pinned string is rejected rather than best-effort parsed. See
The ADK-Tools image for the full version matrix.
Note
The registries are also baked into the ADK-Tools container image, which is why the schema files are committed rather than generated. A container built from a given ADK commit validates against exactly that commit’s schemas.
config/rule_params.json¶
The assembly-placement parameter registry: the numbers the ASM rules use.
Consumers. klayout/drc/adk_assembly.drc loads it into the drc_rules
dictionary, which the interposer adapter may then override and which
8_1_assembly.drc reads. kicad/dru/generate_assembly_dru.py loads the same
file as its defaults. Both consumers apply adapter overrides, which is what makes
the KLayout and KiCad checks agree. See Adapter contract.
Key |
Meaning |
Default |
Unit |
|---|---|---|---|
ASM_b |
Minimum spacing between chiplets, in micrometres. Edge-to-edge between adjacent chiplet boundary polygons. |
50 |
um |
ASM_e |
Minimum chiplet area, in square micrometres. Chiplet boundary polygons below this threshold are flagged. |
10000 |
um2 |
Warning
ASM_b and ASM_e are engineering defaults with no recorded
provenance in the registry. The registry’s own description calls them
parameter defaults, and no foundry document, assembly-house specification or
qualification report is cited for either value anywhere in the source. Treat
50 um of chiplet-to-chiplet spacing and 10000 um2 of minimum chiplet area as
sane starting points that make the rules do something useful on a plausible
assembly, not as manufacturing constraints. Override them from your
interposer adapter when you have numbers that are actually justified.
ASM_e in particular is a sanity check rather than a constraint: it exists to
catch degenerate boundary polygons, a chiplet outline that collapsed to a sliver
during a transform, not to express a real minimum die size.
config/interconnect.json¶
The interconnect-axis parameter registry: the numbers the IXN rules use when
no adapter overrides them.
Consumers. klayout/drc/adk_assembly.drc loads it into
interconnect_rules when the file exists, and tolerates its absence so that a
partial checkout still runs the interposer-only path.
rule_decks/8_2_interconnect.drc reads the dictionary, but only when the
interconnect axis is active at all. generate_assembly_dru.py also loads it,
for the documented render signature, but the KiCad template emits no IXN
constraint: the interconnect checks are post-layout geometry checks with no
KiCad equivalent, so only the adapter name reaches the generated file, as a
provenance comment.
Key |
Meaning |
Default |
Unit |
|---|---|---|---|
IXN_spacing |
Minimum edge-to-edge spacing between chiplet attachment points, in micrometres. |
40 |
um |
IXN_pitch |
Minimum centre-to-centre pitch between attachment points, in micrometres. Checked as a spacing of (pitch - pad_size) since KLayout has no native pitch check. |
75 |
um |
IXN_pad_size |
Representative attachment-pad size in micrometres, used for the pitch-to-spacing conversion. |
35 |
um |
Unlike the ASM defaults, these numbers have recorded provenance, stated in
the registry’s own description: they mirror the IHP Cu-pillar default option in
the bumping vendor’s table, a 35 um passivation opening, 40 um edge-to-edge space
and 75 um pitch. The interposer PDK’s Padc_a, Padc_b and Padc_e carry
the same three numbers, so the interposer stage and the assembly stage of the
two-stage DRC check the same values.
Designs using the larger Cu-pillar options are checked against this conservative floor, exactly as they are at the interposer stage. Option-specific adapters are trivial copies with that option’s values from the same table, and can be added when a design needs option-specific checking. Interconnect rules (IXN) describes how the pitch value becomes a spacing check.
config/layers.json¶
A layer registry that exists for backward compatibility and nothing else.
It contains one entry, exchange0 at GDS 190/0, the historical fabrication
location of the chiplet boundary. The default path never touches it: the boundary
travels in the per-assembly manifest, outside any fabrication-layer namespace.
Consumers. adk_assembly.drc loads the file unconditionally and raises if
it is missing, but only layers_def.drc consults the exchange0 entry, and
only when the deck runs with legacy_exchange0 set, which the runner flag
--legacy-exchange0 does:
if defined?(legacy_exchange0) && legacy_exchange0
exchange0_layer = adk_layers['exchange0']
chiplet_boundary = polygons(exchange0_layer['gds_layer'],
exchange0_layer['gds_datatype'])
else
chiplet_boundary = polygon_layer
# ... polygons inserted from the injected boundary manifest
end
The KiCad DRU generator does not read the file at all. Bumping its version
key has no effect on the contract; only its layers key is ever read, and only
on that one path. Boundary manifest describes what replaced
it.
config/chiplet_pads.json¶
The canonical chiplet-internal pad vocabulary.
Name |
GDS |
Purpose |
|---|---|---|
|
205/0 |
Bond-pad metal geometry on a black-box or pads-only chiplet, one polygon per pad. |
|
205/25 |
Pad-name text labels, associated to pads by proximity. Datatype 25
mirrors the PDK |
|
206/0 |
Die mechanical outline, one polygon. |
Note
This registry is producer-side vocabulary, not an assembly check. No ADK rule reads it, and no assembly verdict depends on it. It says what the black-box generator writes and what a downstream reader may assume when it is told the geometry came from that generator. Do not read it as “the layers a chiplet must use”.
Two things follow from that framing, and both are in the registry’s own description:
The input side never consults this file. Reading an arbitrary commercial pads-only GDS, whose layer numbers are unknown, is handled by an explicit
--pad-layer-numberor by densest-layer auto-detection, not by assuming 205/0.The numbers 205 and 206 were chosen deliberately in a band the reference interposer PDK leaves free. IHP SG13G2 uses the Exchange family at 190 to 194 and layer 257, so 195 to 256 is unassigned, and a black-box chiplet’s synthetic pad and outline geometry cannot alias a real interposer fabrication layer in an assembled GDS. A guard test in
gds2kicadpins this against the IHP layer set, and a test in the ADK pins the registry’s own shape.
The one reader on the checking side is checks/pads_vs_pillars.py, which uses
the vocabulary to extract pad positions from a die layout when no pin list is
available. That is still consumption of producer-side geometry, not an assembly
rule: layer numbers are never hardcoded in the check, they come from here. See
Pad to pillar alignment.
Finally, note what the registry says about the outline: the black-box generator
records the die outline as the chiplet boundary in the .boundaries.json
manifest, and it is no longer mirrored onto exchange0. The 206/0 outline
is a drawing convenience for the chiplet’s own GDS; the manifest is what the
assembly DRC reads.
Registry schemas¶
The three registry schemas are validated against their data in CI, so the committed schema files cannot drift from the registries they describe.
Rule parameter registry¶
config/schema/rule_params.schema.json. Note the closed additionalProperties
on rules: a key that does not match the uppercase-initial pattern is a schema
error, not an ignored extra.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://heterogenic-chip-design-project/adk/config/schema/rule_params.schema.json",
"title": "ADK rule parameter registry",
"type": "object",
"required": ["version", "rules"],
"properties": {
"description": { "type": "string" },
"version": { "type": "string" },
"rules": {
"type": "object",
"patternProperties": {
"^[A-Z][A-Za-z0-9_]*$": { "type": "number" }
},
"additionalProperties": false
},
"rule_descriptions": {
"type": "object",
"patternProperties": {
"^[A-Z][A-Za-z0-9_]*$": { "type": "string" }
},
"additionalProperties": false
}
}
}
Interconnect registry¶
config/schema/interconnect.schema.json. Structurally identical to the rule
parameter schema, kept separate so the two registries can diverge without a
coupled edit.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://heterogenic-chip-design-project/adk/config/schema/interconnect.schema.json",
"title": "ADK interconnect-axis rule parameter registry",
"type": "object",
"required": ["version", "rules"],
"properties": {
"description": { "type": "string" },
"version": { "type": "string" },
"rules": {
"type": "object",
"patternProperties": {
"^[A-Z][A-Za-z0-9_]*$": { "type": "number" }
},
"additionalProperties": false
},
"rule_descriptions": {
"type": "object",
"patternProperties": {
"^[A-Z][A-Za-z0-9_]*$": { "type": "string" }
},
"additionalProperties": false
}
}
}
Layer registry¶
config/schema/layers.schema.json. It constrains both config/layers.json
and, by convention, config/chiplet_pads.json, which the ADK test suite checks
against the same constraints without requiring a jsonschema dependency.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://heterogenic-chip-design-project/adk/config/schema/layers.schema.json",
"title": "ADK layer registry",
"type": "object",
"required": ["version", "layers"],
"properties": {
"description": { "type": "string" },
"version": { "type": "string" },
"layers": {
"type": "object",
"patternProperties": {
"^[a-z][a-z0-9_]*$": {
"type": "object",
"required": ["gds_layer", "gds_datatype"],
"properties": {
"gds_layer": { "type": "integer", "minimum": 0, "maximum": 255 },
"gds_datatype": { "type": "integer", "minimum": 0, "maximum": 255 },
"purpose": { "type": "string" }
},
"additionalProperties": false
}
},
"additionalProperties": false
}
}
}
Sidecar schemas¶
Three further schemas describe per-assembly files that travel next to an
assembly GDS rather than living in config/. They are data contracts between
separate tools, so their readers pin the schema string and the version exactly.
Each is listed on the page that owns it:
Schema file |
Schema string |
Normative page |
|---|---|---|
|
|
|
|
|
|
|
|
Changing a registry¶
Changing a value. Edit the registry, and expect the generated rule and parameter tables in this documentation to change with it. The documentation generators read the pinned submodule, and CI fails if the committed tables no longer match.
Adding a rule parameter. Add the key and a matching entry in
rule_descriptions. The description is not decoration: the table generators fail the documentation build when a parameter has no description.Adding a layer entry. Only
config/layers.jsonandconfig/chiplet_pads.jsonhave a layers shape, and neither is the right home for a new assembly-level concept. If a new piece of per-assembly data is needed, it belongs in a sidecar with its own schema and its own version pin, for the reasons theexchange0migration records above.Bumping a version. The four registry
versionkeys move together withVERSIONand theCHANGELOG.mdheading, and the consistency test enforces it. Sidecar schema versions move on their own, and a bump there means every reader’s exact-match pin must be updated in the same change.