Skip to main content

Semiconductor — yield & defect tracing

The problem. In a fab, yield is everything — and a yield drop is a detective story. A wafer lot passes through hundreds of process steps on dozens of tools; when lots start failing final test, the cause could be any one tool drifting out of spec. The killer question is: what do the failing lots have in common? Find the one tool or chamber that every bad lot passed through and you've found the culprit; miss it and you scrap wafers for weeks.

What we solve here is tracing a yield excursion back to its root tool before it costs a fortune in scrapped silicon.

Set up demo data​

New workspace? Run this once (Python) to create two failing lots that both ran on tool_etch_07 (plus other tools) — so the intersection in step 2 finds the shared culprit. Safe to re-run.

import intellistream_datahub_sdk

client = intellistream_datahub_sdk.DataHubClient.from_env()

client.resources.create(
[intellistream_datahub_sdk.Resource(external_id=x, name=x, labels=[lbl]) for x, lbl in
[("lot_22841", "Lot"), ("lot_22863", "Lot"), ("tool_etch_07", "Tool"),
("tool_litho_03", "Tool"), ("tool_cmp_05", "Tool")]],
[intellistream_datahub_sdk.RelForm.by_external_ids("lot_22841", "tool_etch_07", "processed_on"),
intellistream_datahub_sdk.RelForm.by_external_ids("lot_22841", "tool_litho_03", "processed_on"),
intellistream_datahub_sdk.RelForm.by_external_ids("lot_22863", "tool_etch_07", "processed_on"),
intellistream_datahub_sdk.RelForm.by_external_ids("lot_22863", "tool_cmp_05", "processed_on")])

1. Record process data exactly​

Chamber pressure, temperature and gas flow are the process record, and they must be exact — use the NUMERIC value type so values store without floating-point drift.

var pressure = Timeseries.of("tool_etch_07_chamber_pressure_mtorr")
.name("Etch-07 chamber pressure")
.setValueType("numeric");
pressure.setUnit("mtorr");
client.timeseries().create(pressure);

client.timeseries().ingest(Map.of(
"tool_etch_07_chamber_pressure_mtorr",
List.of(Datapoint.of(Instant.now(), "12.0436"))));

2. Find the tool every failing lot shares​

Each lot is connected to the tools it ran on (processed_on). Walk the graph from each failing lot and intersect: the tool common to all of them is the prime suspect — the same shared-node reasoning as alarm correlation, applied to process genealogy.

ResourceNetwork lotA = client.resources().fetchRelated("lot_22841", 6);
ResourceNetwork lotB = client.resources().fetchRelated("lot_22863", 6);

Set<String> toolsA = lotA.nodes().stream()
.map(Resource::getExternalId).filter(id -> id.startsWith("tool_")).collect(Collectors.toSet());
Set<String> suspect = lotB.nodes().stream()
.map(Resource::getExternalId).filter(toolsA::contains).collect(Collectors.toSet());

// suspect contains "tool_etch_07" → the chamber to pull and check

3. Confirm against the tool's process record​

With the suspect tool identified, pull its exact process series around the failing lots' run times and compare to a known-good window — the drift that explains the excursion should be right there. See Query & aggregate.

See the result​

The tools common to both failing lots:

suspect contains 'tool_etch_07' ← the chamber to pull and check

See also​