Six more chapters finishing Part 2. Together with chapters 10–13 they document every SEMI standard this codebase implements. 14 — E40 + E94: process jobs (8-state lifecycle, S16F11/F5/F7/F9 on the wire) and control jobs (CJ wraps PJs with batch policy, S14F9/S16F27 messages). Worked cascade showing how CJSTART propagates through the PJ FSM and triggers S6F11 CEIDs at each transition. 15 — E87 carriers: three orthogonal sub-machines (CarrierID, SlotMap, CarrierAccess) per carrier and three more (Transfer, Reservation, Association) per load port. S3F17 CarrierAction strings + CAACK codes, S3F19 SlotMap verify, the 5-state slot encoding, multi-port concurrency. 16 — E90 + E157: substrate tracking via three orthogonal axes (STS / SPS / SubstrateIDStatus) and module process tracking (NotExecuting / GeneralExecuting / StepExecuting / StepCompleted). End-to-end PVD example showing E40 + E157 + E90 transitions cascading into CEIDs. 17 — E116 + E120 + E39: equipment performance time-buckets across six states, common equipment model object hierarchy, S14F1/F3 GetAttr/SetAttr as the uniform wire access for any object type across multiple standards. 18 — E84 parallel I/O: ten signal lines, the 9-state handshake FSM, the three TA1/TA2/TA3 timing-critical timers, why a physical handshake gets modeled in software (testability, timer enforcement, CEID emission, multi-port concurrency), the pure-FSM + asio-adapter split. 19 — E42 + E148 + S5F9–F18: formatted recipes (S7F23/F25 typed PPBODY), time synchronization with 16-char + 14-char accepted on set, exception recovery as a persistent multi-step host-supervised FSM (Posted → Recovering → Cleared with abort/retry). Revisits the auto-S9 family and contrasts S9 (transport) vs S5F9 (application). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.7 KiB
16 — E90 + E157: Substrate and module tracking
← 15 E87 — Carriers and load ports | Back to index | Next: 17 E116 + E120 + E39 — Performance, CEM, objects →
E87 (chapter 15) tracks the container. E90 and E157 track what's inside the container — every individual wafer (substrate) and every process module the wafer passes through.
This chapter is shorter than the others in Part 2 because the ideas overlap E87 (the same three-orthogonal-axes pattern repeats) and E40 (state events drive S6F11 CEIDs).
E90 — Substrate tracking
What it tracks
One state-bearing record per wafer, identified by a substrate ID (an ASCII string, often the laser-etched serial number).
E90 has three orthogonal axes — the same pattern as E87's carrier (chapter 15 §3):
1. Substrate State (STS) — location
// include/secsgem/gem/substrate_state.hpp:26
enum class SubstrateState : uint8_t {
AtSource = 0, // in its origin carrier slot
AtWork = 1, // in-process at a module
AtDestination = 2, // delivered to final location
NoState = 255,
};
Events: Acquire (Source→Work), Release (Work→Destination),
Return (Work→Source, for unprocessed return).
2. Substrate Processing State (SPS) — lifecycle
enum class SubstrateProcessingState : uint8_t {
NeedsProcessing = 0,
InProcess = 1,
Processed = 2,
Aborted = 3,
Stopped = 4,
Rejected = 5,
Lost = 6,
Skipped = 7,
NoState = 255,
};
Events: StartProcessing, EndProcessing, Abort, Stop,
Reject, ReportLost, Skip.
3. Substrate ID Status — identity confidence
enum class SubstrateIDStatus : uint8_t {
NotConfirmed = 0,
WaitingForHost = 1,
Confirmed = 2,
Mismatched = 3,
NoState = 255,
};
Mirrors the CarrierIDStatus pattern from E87 — same problem
(equipment reads ID, host may need to verify), same shape of
solution.
Why three axes?
The same reason E87 has three: these aspects evolve at different times and for different reasons.
- A wafer can be
AtWork+NeedsProcessing(just arrived, recipe hasn't started). - A wafer can be
AtWork+InProcess(recipe running). - A wafer can be
AtSource+Processed+Confirmed(back in its carrier slot after processing — typical end state).
Putting all three in one enum would multiply to ~30 valid combinations. Three independent FSMs with ~3 events each is much cleaner.
Code
State machines:
include/secsgem/gem/substrate_state.hpp
defines SubstrateStateMachine, which composes the three.
Store:
include/secsgem/gem/store/substrates.hpp
holds one record per substrate ID, with a Location string the
application updates as the wafer moves.
Tests:
tests/test_substrates.cpp (14
cases — every axis, every event); persistence in
tests/test_substrate_persistence.cpp
(7 cases).
CEID-on-wire emission ("Substrate StartProcessing fires the
configured SubstrateInProcess CEID") is verified by
tests/test_wire_ceid_emission.cpp.
Wire interaction
E90 doesn't define its own S/F messages — substrate state changes fire as CEIDs that the host has subscribed to via the standard E30 §6.6 Dynamic Event Report Configuration (chapter 13). So:
- Equipment fires
Acquireevent on substrateW-2026-06-09-A47. SubstrateStateMachinetransitions Source → Work.- The state-change handler looks up the configured CEID for
"SubstrateInProcess" (from
data/equipment.yaml). - That CEID fires →
compose_reports_for(ceid)→S6F11.
Host gets one S6F11 per wafer transition. In a 25-wafer FOUP that's 25–50 events per processing pass. Persistent reports + spool (chapter 13 Additionals) handle the burst.
E157 — Module Process Tracking
What it tracks
One state-bearing record per process module. A cluster tool has multiple modules (Chamber A, Chamber B, Pre-clean, …); each runs its own recipe step in parallel or sequence. E157 lets the host see which module is in which step of which recipe right now.
The states
// include/secsgem/gem/module_state.hpp:20
enum class ModuleState : uint8_t {
NotExecuting = 0,
GeneralExecuting = 1, // setup, pre-process, post-process
StepExecuting = 2, // actively running a recipe step
StepCompleted = 3,
NoState = 255,
};
Events: StartGeneral, StartStep, CompleteStep, Reset,
Abort.
Notice this is a much simpler FSM than E90 — one axis only. That's because modules are more deterministic than substrates: a module is either running a step or it isn't; substrates can be in many overlapping conditions.
Code
include/secsgem/gem/module_state.hpp
defines ModuleStateMachine.
Store:
include/secsgem/gem/store/modules.hpp.
Tests:
tests/test_modules.cpp (5 cases).
How E157 plays with E40 and E90
Concrete example. A PVD tool with three modules (Chamber A, B, C); host submits PJ for wafer W-1, recipe says "process at Chamber B for 90 seconds":
1. PJ-1 transitions Queued → SettingUp → WaitingForStart → Processing.
(E40 FSM, chapter 14)
2. Equipment fires ModuleEvent::StartGeneral on Chamber B.
ModuleState: NotExecuting → GeneralExecuting.
(E157 FSM)
3. Equipment fires SubstrateEvent::Acquire on W-1.
Substrate STS: AtSource → AtWork.
(E90 FSM)
4. Recipe step begins. ModuleEvent::StartStep on Chamber B.
ModuleState: GeneralExecuting → StepExecuting.
Substrate SPS: NeedsProcessing → InProcess.
5. ...90 seconds pass...
6. Recipe step ends. ModuleEvent::CompleteStep on Chamber B.
ModuleState: StepExecuting → StepCompleted.
Substrate SPS: InProcess → Processed.
7. Substrate released. SubstrateEvent::Release on W-1.
Substrate STS: AtWork → AtDestination.
8. PJ-1: ProcessComplete.
Each of the eight transitions fires a CEID, which fires an S6F11 event report. The host sees the complete trace of where every wafer was at every moment.
Where to go next
You now know how every component of in-flight material is tracked. The next chapter covers the three smaller GEM 300 standards that round out the suite: equipment performance time tracking, the common equipment model, and generic object services.