Reference design

two_die_interposer is the worked example of the whole flow: two dies mounted face down on an IntM4TM2 interposer, attached by two different interconnect methods, with wire-bond I/O pads at the interposer edge. It ships in the IHP-GmbH/ADK-Tools repository under examples/two_die_interposer/ and is baked into the ADK-Tools image at /opt/adk-tools/examples/two_die_interposer. On first container start a disposable copy is seeded at /work/example.

It is also the template adk-new-project scaffolds, so its directory layout is the recommended one for your own designs.

Tip

Work on the seeded copy under /work/example, not on /opt/adk-tools/examples. The seeded copy is disposable: delete ~/adk-work/example on the host and the next container start reseeds it from the image.

What the demo assembles

Component

Technology

Description

interposer

intm4tm2

6492.312 x 5602.001 um, 300 um thick. Four routed metals, Cu-pillar landing pads under each die, 35 wire-bond I/O pads of 100 x 100 um on TopMetal2 around the edge.

U1

sg13g2

770 x 2606.339 um, 750 um thick, orientation: flip_chip, attached with cupillar_opt1 (44 um body, 75 um pitch, 40 um spacing).

U2

sg13g2

The same die layout, attached with vendorx_microbump (40 um body, 50 um pitch, 15 um spacing). A demo, non-IHP method.

Both dies are instances of the same Metal_Test layout, an SG13G2 test die whose 58 external I/O pads sit on TopMetal2 (134/0) with their names on the text layer 134/25.

The two connection stacks are what make the demo interesting, because they are what forces every per-method mechanism in the flow to actually do something. The die z values follow from them directly. The interposer’s attachment surface is at 13.83 um; cupillar_opt1 is a 28 um Cu pillar plus a 16 um SnAg cap, so U1 sits at 57.83 um; vendorx_microbump is 18 um plus 6 um, so U2 sits at 37.83 um. That arithmetic is not decoration: the 3Dblox exporter verifies it exactly and refuses assemblies that do not satisfy it.

Directory tree

two_die_interposer/
  README.md
  chiplets/                              gds2kicad prior-step inputs
    README.md
    Metal_Test.gds                       the full die layout, shared by U1 and U2
    Metal_Test_stripped.gds              curated: only the 58 I/O pads, with names
    metal_test_chiplet.pins.json         58-pad pin list with reviewed side/type
    metal_test_chiplet.g2kproj           saved gds-to-kicad GUI session
  kicad/                                 the human-authored source
    two_die_interposer.kicad_pro
    two_die_interposer.kicad_sch
    two_die_interposer.kicad_pcb
    two_die_interposer.kicad_sym         project symbols, produced by gds2kicad
    two_die_interposer.pretty/
      metal_test_chiplet.kicad_mod       die footprint, produced by gds2kicad
      interposer_bondpad.kicad_mod       wire-bond I/O pad footprint, parametric
    sym-lib-table
    fp-lib-table
  outputs/                               everything the export writes
    two_die_interposer.chiplet           open this in Chiplet Studio
    MANIFEST.md                          index of the products
    layout/
      two_die_interposer_interposer.gds
      two_die_interposer_interposer.boundaries.json
      two_die_interposer_interposer.pillars.json
      two_die_interposer_complete.boundaries.json
      two_die_interposer_complete.pillars.json
      two_die_interposer_complete.ixn_methods.json
    reports/
      two_die_interposer_assembly_drc.lyrdb
      two_die_interposer_cupillar_drc.json

Four more paths appear once you regenerate, and are deliberately not tracked: outputs/two_die_interposer.hyp, outputs/layout/two_die_interposer_complete.gds, outputs/reports/assembly_drc/ (the DRC scratch directory) and outputs/logs/. Everything else is committed on purpose, so a fresh clone opens in Chiplet Studio and carries its DRC results without a rebuild.

Note

To open two_die_interposer_complete.gds in KLayout, or run the assembly DRC yourself, regenerate the outputs first. The *_complete.*.json sidecars are shipped, so the boundary and pillar manifests can be read straight from a clone.

What each file is

chiplets/

Metal_Test.gds is the canonical die layout. Both the footprint and the .chiplet reference it board-relative as ../chiplets/Metal_Test.gds, so the export and Chiplet Studio read the die geometry from the example itself and not from any external tool tree.

Metal_Test_stripped.gds is the frozen result of the pad review described in From die GDS to KiCad: 58 external I/O pads out of about 474 shapes on TopMetal2. Shipping the curated version makes the footprint a reproducible conversion rather than the one hand-made artefact in the project.

metal_test_chiplet.pins.json carries each pad’s name and geometry plus the reviewed symbol-layout fields side and type, which cannot be re-extracted from a footprint. That is why the file exists rather than being derived.

metal_test_chiplet.g2kproj is a saved gds-to-kicad session bundling the inputs, the layer selections and the embedded pin list. It stores image-absolute paths, so it is meant for use inside the container.

kicad/

The board and its project libraries. The symbol library and the .pretty footprint library are outputs of the prior steps below, committed so the board opens without running them, and registered with the project through sym-lib-table and fp-lib-table.

outputs/

two_die_interposer.chiplet is the assembly description and the entry point for Chiplet Studio. It declares both technologies, all five connection stacks, the interposer with its 35 I/O pads, and the two dies with their placement, orientation, thickness and connection method.

Under layout/, the interposer GDS is the one the .chiplet references. Each GDS has its own boundary manifest and pillar manifest as siblings, which is how the assembly DRC and the viewer macro find them without being told. two_die_interposer_complete.ixn_methods.json maps each interconnect method to the dies that use it, so the DRC checks U1’s pads at 75/40 and U2’s at 50/15 instead of applying one number to the whole assembly.

Under reports/, the .lyrdb is the assembly DRC result database, openable in the KLayout Marker Browser, and the _cupillar_drc.json is the Cu-pillar DRC summary the producer wrote while generating the pillars.

Walking the flow

Step 0: open what is already there

From the host, using the launcher in the ADK-Tools checkout:

./run.sh chiplet-studio example/outputs/two_die_interposer.chiplet
./run.sh kicad          example/kicad/two_die_interposer.kicad_pro

Or from a shell inside the container, where both tools are on the path. Expect Chiplet Studio to show the interposer slab with two dies standing off it on their pillars, and the wire-bond pads with their fan-out traces around the edge; switch a die to a detailed render mode to see its actual artwork as geometry. See Viewing and inspecting.

Step 1: the gds2kicad prior steps

These run once per die, before any board work, and produce the KiCad library the board is built on. They are reproducible from the shipped inputs, and the image build gates them against the committed library.

The die footprint, read straight out of the curated GDS:

gds_to_kicad.py Metal_Test_stripped.gds \
    --layer TopMetal2.drawing --text-layer-number 134/25 \
    --lyp-file $GDS_TO_KICAD_ROOT/pdks/sg13g2.lyp --flip-chip \
    -o metal_test_chiplet.kicad_mod

The die symbol, from the reviewed pin list, with no GDS involved:

gds_to_kicad_symbol.py --from-pin-list metal_test_chiplet.pins.json \
    -o Metal_Test.kicad_sym

The wire-bond I/O pad, generated parametrically rather than converted:

$GDS_TO_KICAD_ROOT/io_pads/generate_io_pad.py --io-class wire_bond --size 100x100

The same three steps are available from the gds-to-kicad GUI, and metal_test_chiplet.g2kproj reopens the session at exactly the state that produces the footprint and the symbol. See From die GDS to KiCad.

Note

--flip-chip on the footprint conversion is not cosmetic. The die is mounted face down, so its pads are mirrored in the board frame. This is the same mirror the assembly generator applies to the die artwork, and the same one the pad-to-pillar check models. Getting it wrong produces an assembly where every pad is on the wrong side and every individual check still passes.

Step 2: author the board

The board is drawn in the KiCad fork, with the physical stackup naming the copper layers after the process metals and a closed Edge.Cuts outline. That is covered by Designing the interposer; the demo’s .kicad_pcb is the finished result.

Step 3: export and generate the GDS

Normally this is the Chiplet Export plugin inside pcbnew, with its output directory pointed at the sibling outputs/. The demo’s headless equivalent, which is exactly what the image build runs, is:

python3 /opt/adk-tools/chiplet_kicad_plugin/tests/regenerate_wirebond_demo.py \
    --require-drc \
    --board   example/kicad/two_die_interposer.kicad_pcb \
    --output-dir example/outputs

One command drives the whole chain: the HyperLynx writer produces the .hyp, the chiplet writer produces the intermediate .chiplet, hyp_to_gds produces both GDS files with their sidecars and finalises the .chiplet, and the ADK assembly DRC runs on the complete GDS. --require-drc makes a DRC failure a non-zero exit, which is what turns this into a build gate.

The script prints the resolved artefact paths as it goes, and echoes the worker command lines it runs, so it doubles as a way to see the exact hyp_to_gds invocation for a given board.

Step 4: the assembly DRC on its own

The export runs the DRC for you. To run it again by hand against the regenerated complete GDS, with the same adapters and per-method scoping the pipeline derives from the .chiplet:

adk-drc \
    --path      example/outputs/layout/two_die_interposer_complete.gds \
    --interposer-adapter   intm4tm2 \
    --interconnect-adapter vendorx_microbump \
    --interconnect-methods example/outputs/layout/two_die_interposer_complete.ixn_methods.json \
    --report    example/outputs/reports/two_die_interposer_assembly_drc.lyrdb \
    --run_dir   example/outputs/reports/assembly_drc

The boundary manifest is not on the command line because the runner auto-discovers two_die_interposer_complete.boundaries.json next to the GDS. The runner logs a pass or fail banner and the report path; a violation leaves items in the .lyrdb under the rule that flagged them.

Step 5: checks the demo does not run for you

Only stage 3, the KLayout assembly DRC of step 4, is part of the demo pipeline. The other three of the four verification stages are not. Two of them you can run yourself against the shipped artefacts, and they are given below. The third, the KiCad design-time check, cannot be run here at all: the demo kicad/ tree ships no generated .kicad_dru, so there is nothing for pcbnew to enforce. Generate one as KiCad DRU generation describes before using this example as the template for a design of your own.

Pad-to-pillar alignment, which needs the .chiplet, the pillar manifest and a pad source per die:

python3 $ADK_ROOT/checks/pads_vs_pillars.py \
    --chiplet example/outputs/two_die_interposer.chiplet \
    --pillars example/outputs/layout/two_die_interposer_complete.pillars.json \
    --pins U1=example/chiplets/metal_test_chiplet.pins.json \
    --pins U2=example/chiplets/metal_test_chiplet.pins.json \
    --json pads_vs_pillars.json

The 3Dblox export, whose own consistency checks run without OpenROAD installed:

python3 $ADK_ROOT/openroad/chiplet2dbx.py \
    --chiplet example/outputs/two_die_interposer.chiplet \
    --out-dir build/3dblox \
    --pins U1=example/chiplets/metal_test_chiplet.pins.json \
    --pins U2=example/chiplets/metal_test_chiplet.pins.json

Running check_3dblox on the result additionally needs an OpenROAD image carrying the 3Dblox commands. See Verification stages.

Step 6: the one-command self test

adk-smoke

adk-smoke verifies that the intm4tm2 KLayout technology is registered and its layer properties resolve, then exports the demo end to end into a throwaway directory with --require-drc and asserts the DRC passed. It is the fastest way to tell whether a container, or a hand-assembled toolchain, is wired correctly. On success it ends with the line adk-smoke: PASS (export + assembly DRC green); any failure exits non-zero before that.

What the committed reports say

Two result files are tracked, so you can read the demo’s verification outcome without running anything.

reports/two_die_interposer_cupillar_drc.json records the producer-side Cu-pillar checks: version 2 of the report format, the per-die method assignment (U1 to cupillar_opt1, U2 to vendorx_microbump), the parameter set each method was checked with, and a summary of zero errors, zero warnings and ten informational results across ten checks over two devices, with passed true.

reports/two_die_interposer_assembly_drc.lyrdb records the assembly DRC. It carries eleven rule categories and no violation items:

ASM.a  ASM.b  ASM.e  ASM.f
IXN.b.cupillar_opt1        IXN.e.cupillar_opt1
IXN.b.vendorx_microbump    IXN.e.vendorx_microbump
IXN.x.cupillar_opt1.vendorx_microbump
IXN.b.unclaimed            IXN.e.unclaimed

That list is the interesting part. The per-method categories show the two dies being checked at their own numbers; IXN.x is the conservative cross-method spacing between the two bump fields, at the larger of the two spacings; and the unclaimed categories cover any attachment pad that falls under no die’s boundary, checked with the assembly-level adapter’s numbers.

Reproducibility

The demo outputs are not decorative. The image build regenerates them headless from the board and then compares the fresh regeneration against the committed tree, failing the build on any semantic difference: a committed deliverable a fresh run no longer produces, a new sidecar a fresh run emits that is not committed, or a change in the .chiplet, the manifests, the reports or the GDS geometry.

The comparison is not a naive byte diff. GDS files are hashed with the BGNLIB and BGNSTR timestamps zeroed, so a real geometry, layer or cell change is caught while KLayout’s per-run header timestamp is not. Boundary manifests are compared with assembly_gds_sha256 dropped, for the same reason. Per-run artefacts, the logs, the DRC scratch directory, the .lyrdb, the complete GDS and the .hyp, are ignored.

The gate exists because the runtime image bakes the tracked deliverables rather than the regeneration, so a tracked set that had drifted from what the current board and toolchain produce could ship on a green build. A stale .chiplet and a missing pillar manifest reached a release candidate that way.

What the demo demonstrates

  • A die layout becoming a KiCad symbol and footprint, reproducibly, from shipped inputs.

  • An interposer authored in KiCad on process-named copper layers, exported to a .chiplet assembly and a HyperLynx netlist.

  • Routing becoming fabrication geometry: paths on real process layers, vias from the base PDK’s via_stack PCells, the board outline on prBoundary.

  • Cu-pillar generation from per-die pin lists, with two different interconnect methods in one assembly, each checked against its own rules.

  • Flip-chip placement of both dies, mirrored per layer in the assembly GDS.

  • Wire-bond I/O pads placed on the interposer and recorded in the .chiplet.

  • The manifest sidecars, and both consumers of them: the assembly DRC and the boundary viewer.

  • A per-method assembly DRC run that passes, including cross-method spacing.

  • 3D inspection of the finished assembly, with drill-down into the real layouts.

What it does not demonstrate

  • Two different dies. U1 and U2 are two instances of the same layout. Nothing in the flow requires that, but the demo does not exercise a genuinely heterogeneous die set.

  • A stacked or multi-tier assembly. Everything sits on one tier. The assembly rules assume that, and ASM.a would flag legally stacked dies as overlapping.

  • Automated 2.5D place and route. That work is a proof of concept and is not part of this example. See Roadmap.

  • The interposer’s or the dies’ own fabrication rules. The example runs the assembly checks only. The interposer PDK and the die PDK own their decks, and running them is a separate step.

  • Thermal, power-integrity or timing analysis. Those ADK domains are reserved names with no implementation.

  • A fabricated assembly. The interposer process has been fabricated several times at IHP, which is a statement about process maturity. This example is a design flow demonstration, and no complete assembly built from it has been manufactured.

  • A vendor-qualified fine-pitch method. vendorx_microbump is a deliberately synthetic, non-IHP method, present so that the per-method machinery has two methods to distinguish. Its numbers are demonstration values.

Starting your own design

adk-new-project my_design

This scaffolds /work/heterogenic-designs/my_design with the same kicad/ plus chiplets/ plus outputs/ split, and a .gitignore already keeping the heavy and scratch files out of version control while tracking the light deliverables. Author the board under kicad/, run the Chiplet Export plugin with its output directory set to the sibling outputs/, and open the result with chiplet-studio.