Files
secs-gem/docs/02_the_cast.md
T
raphael 0355c73211
tests / build-and-test (push) Successful in 2m9s
tests / thread-sanitizer (push) Successful in 2m35s
tests / tshark-dissector (push) Successful in 2m17s
tests / secs4j-interop (push) Successful in 1m6s
tests / libfuzzer (push) Successful in 3m7s
docs: refresh stale file paths after store/ reorg + gen_messages rename
generate_messages.py → gen_messages.py and several gem/ headers moved
under gem/store/ (carrier_store.hpp → store/carriers.hpp, etc.);
e84.hpp split into e84_state.hpp.  The guided-tour chapters still
pointed at the old paths — relink them so the deep-link footnotes
resolve.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 23:23:42 +02:00

417 lines
20 KiB
Markdown

# 02 — The cast of characters
← [01 What is SECS/GEM?](01_what_is_secs_gem.md) | [Back to index](00_index.md) | Next: [03 Vocabulary + a wafer's journey](03_vocabulary_and_a_wafers_journey.md) →
Chapter [01](01_what_is_secs_gem.md) explained that SECS/GEM is the
protocol a fab uses to make ~100 tools talk to a central MES. That
description hid a lot of structure. In reality, there are at least
**six distinct actors** in a typical fab automation stack — six
roles, each implemented by different software (often by different
vendors), each with its own concerns.
This chapter introduces them all, draws who-talks-to-whom, and
locates each one in this codebase. After this you'll be able to read
any SECS conversation and know which actor is initiating, which is
responding, and why.
---
## The six actors
```
┌──────────────────┐
│ Fab planner │ "make 100 wafers
│ (MES upper) │ of recipe R by
└────────┬─────────┘ Friday"
recipes, lot │ yields, KPIs,
assignments, │ alarms, status
process programs │
┌──────────────────┐
│ MES (the host) │ per-step orchestration
└────────┬─────────┘
SECS/GEM │ SECS/GEM
S2F41 RCMD, │ S6F11 events,
S7F3 PP send, │ S5F1 alarms,
S2F33 reports, │ S1F4 status
… │ …
┌──────────────────┐
│ EAP / equipment automation program │
│ (vendor application layer) │
├──────────────────────────────────────────┤
│ THIS CODEBASE — the SECS/GEM runtime │
│ secsgem::gem / secsgem::hsms / … │
└────────┬─────────────────────────────────┘
PLC / sensor / recipe-engine APIs (tool-specific)
┌──────────────────┐
│ Equipment │ the physical tool:
│ (the tool) │ chambers, robots,
└────────┬─────────┘ sensors, recipes
E84 8-line │ (carrier moves, no SECS bytes)
parallel I/O │
┌──────────────────┐
│ AMHS │ robot rails / OHT
│ (the carriers) │ that move FOUPs
└──────────────────┘
←───── Operator ──────→ panel buttons,
recipe overrides,
Online/Offline/Local/Remote
```
Read the diagram top-down: a fab planner schedules work, the MES
dispatches it tool by tool, each tool's EAP receives commands over
SECS/GEM, the EAP drives the actual hardware, the AMHS robots feed
carriers in and out. An operator can intervene at any layer.
Each actor has a section below.
---
## 1. Equipment — the tool itself
**What it is.** A physical processing tool — a chemical-vapor
deposition (CVD) chamber, a plasma etcher, a wafer prober, a
photolithography stepper, an ion implanter, an inspection
microscope. Anywhere from one chamber the size of a microwave to a
full lithography cluster the size of a small bus.
**What it does in SECS/GEM terms.**
- **Reports state** — its current control state (Equipment Offline,
Online Remote, …), its processing state (IDLE, EXECUTING, …), its
carrier slots, its current recipe.
- **Emits events** — when something happens worth recording
(processing started, wafer processed, alarm raised, recipe
completed), it fires an `S6F11` to the host.
- **Accepts commands** — START, STOP, ABORT, PAUSE, CHANGE-RECIPE,
CARRIER-PROCEED, etc., delivered as `S2F41` Host Commands.
- **Stores its data dictionary** — every Status Variable (SVID),
Equipment Constant (ECID), Data Variable (DVID), Collection Event
(CEID), Alarm (ALID), and Process Program (PPID) it supports.
- **Manages its own physical safety** — it can refuse a host command
if the requested action would damage hardware, and it can raise
alarms autonomously.
**In SECS/GEM, the equipment is almost always the "passive" side of
the connection** — it binds a TCP port and waits for the host to
connect, rather than the other way around. This codebase reflects
that: `apps/secs_server.cpp` is the equipment, and it listens.
**Where it lives in this codebase.**
- The equipment role's main binary: [`apps/secs_server.cpp`](../apps/secs_server.cpp).
- The data dictionary: [`include/secsgem/gem/data_model.hpp`](../include/secsgem/gem/data_model.hpp)
defines `EquipmentDataModel`, which composes every per-domain
store (SVIDs, ECIDs, CEIDs, alarms, carriers, substrates, recipes,
spool, …).
- A worked example with sensor simulation, recipe runner, and alarm
monitoring: [`examples/pvd_tool/main.cpp`](../examples/pvd_tool/main.cpp).
- Tests covering equipment behaviour: [`tests/test_data_model.cpp`](../tests/test_data_model.cpp),
[`tests/test_control_state.cpp`](../tests/test_control_state.cpp),
[`tests/test_host_handler.cpp`](../tests/test_host_handler.cpp).
---
## 2. EAP — the equipment automation program
**What it is.** The vendor-written software layer that sits on top
of the SECS/GEM runtime and *makes the tool actually do things*.
The EAP is the glue between:
- The SECS/GEM library (this codebase),
- The tool's PLCs / sensors / recipe engine / robot controllers,
- The tool vendor's domain logic.
Every tool vendor ships their own EAP. Two CVD tools from different
vendors both speak GEM, but their EAPs are entirely different
codebases doing entirely different things internally.
**Why it's a separate role.** The SECS/GEM standards spell out
*what* messages mean — "S2F41 with RCMD=START must initiate
processing on the currently loaded recipe." They don't spell out
*how* a specific CVD tool initiates processing on its specific
hardware. The EAP is the layer that resolves that.
In particular:
- When `S2F41 RCMD=START` arrives, the EAP decides whether the tool
is in a state to start (chamber pressure low enough? robot at
home position? recipe loaded?), and if so, calls the tool's
proprietary recipe engine to begin the cycle.
- When a sensor reads a temperature change, the EAP decides whether
to update an SVID, fire a CEID, or raise an alarm — and the
per-tool rules for that aren't in any SEMI standard.
- When a `S7F3` arrives with a new recipe payload, the EAP decides
how to validate the recipe against the tool's actual hardware
capabilities.
**Where it lives in this codebase.**
This codebase provides the SECS/GEM runtime; the EAP is what a
customer writes on top of it. We ship two reference EAPs:
- [`apps/secs_server.cpp`](../apps/secs_server.cpp) — the demo
server. Wires every Router handler the demo flow needs; uses
static YAML data and doesn't simulate any sensors. Useful as a
starting fork.
- [`examples/pvd_tool/main.cpp`](../examples/pvd_tool/main.cpp) — a
fictional PVD tool that adds a sensor simulator, a recipe runner,
an alarm threshold monitor, EPT state cycling, and Prometheus
metrics. This is the closest thing to "what a real EAP looks
like" that we ship. See [`examples/pvd_tool/README.md`](../examples/pvd_tool/README.md)
for the section-by-section walk.
The integration tutorial — how to *write* an EAP for a real tool —
is [`INTEGRATION.md`](INTEGRATION.md). Chapter
[41](41_integration_hardware_mes_production.md) in this series covers
the same material with cross-references back to the standards.
---
## 3. MES — the host
**What it is.** The **Manufacturing Execution System**. A
fab-wide server (or cluster) that orchestrates production across
every tool, manages lots and recipes, collects yield and statistical
process control (SPC) data, and provides the operator UI for the
production floor.
Commercial MES vendors you'll meet: Applied Materials **E3**, Camstar
**InSite**, Wonderware **MES**, Aegis **FactoryWorks**, Inficon
**FabGuard**, Critical Manufacturing **MES**, and many in-house
custom builds especially at the largest fabs.
**What it does in SECS/GEM terms.**
- **Connects** to each tool's equipment process. In SECS/GEM
language, the MES is the **active** side of the HSMS connection
(it initiates the TCP connect and sends `Select.req`).
- **Establishes communications** — sends `S1F13` to which the
equipment replies `S1F14(COMMACK=Accept)`.
- **Identifies the tool** — sends `S1F1` (Are You There), reads
back the `MDLN` (model name) and `SOFTREV` (software revision)
in `S1F2`.
- **Reads the data dictionary** — `S1F11` for the SVID namelist,
`S2F29` for the ECID namelist, `S1F23` for the CEID namelist,
`S5F5` for the alarm directory, `S7F19` for the recipe list.
- **Configures event reports** — `S2F33` defines a report,
`S2F35` links it to a Collection Event, `S2F37` enables it. This
is how the MES tells the tool "when CEID 300 fires, send me the
values of SVIDs 1 and 2 along with it."
- **Issues remote commands** — `S2F41 RCMD=START`, `S2F41
RCMD=PAUSE`, `S2F41 RCMD=ABORT`, etc.
- **Manages recipes** — `S7F3` to send a recipe, `S7F19` to list,
`S7F17` to delete, `S7F5` to read one back.
- **Orchestrates process and control jobs** — `S16F11` to create
a Process Job, `S14F9` to wrap it in a Control Job, `S16F27`
CJSTART to begin execution.
- **Receives alarms and events** — `S5F1` for alarm set/clear,
`S6F11` for collection events. Acknowledges with `S5F2` and
`S6F12` respectively.
- **Sets and reads the equipment's clock** — `S2F17`/`S2F18` to
read, `S2F31`/`S2F32` to set.
**Where it lives in this codebase.**
We don't *implement* an MES — that's a separate, much larger product
category. We implement the host *side* of SECS/GEM so the codebase
can drive equipment too, mainly for testing.
- [`apps/secs_client.cpp`](../apps/secs_client.cpp) — the active
host that drives the demo server through ~24 transactions.
- [`apps/secs_conformance.cpp`](../apps/secs_conformance.cpp) — the
host-driven conformance harness that runs the 47 wire-level checks.
- [`include/secsgem/gem/host_handler.hpp`](../include/secsgem/gem/host_handler.hpp)
+ [`src/gem/host_handler.cpp`](../src/gem/host_handler.cpp) —
symmetric handler module so the host side can decode equipment
replies and act on equipment-initiated S5F1 / S6F11.
- [`interop/host_vs_cpp_server.py`](../interop/host_vs_cpp_server.py)
— the secsgem-py active host driving our C++ passive server.
For integrating against a **commercial** MES,
[`MES_INTEROP.md`](MES_INTEROP.md) is the day-1 punch list.
---
## 4. Fab planner / MES upper layer
**What it is.** The layer *above* the MES. Goes by many names:
**Advanced Planning and Scheduling (APS)**, **Fab scheduler**,
**Dispatcher**, **MES upper**. Big fabs separate this from the
operational MES; smaller ones bundle it in.
**What it does.** Decides which lot runs on which tool, in what
order, against what recipe, by what deadline. This is fab-wide
optimisation across hundreds of in-flight lots and dozens of routes.
**SECS/GEM contact:** none directly. The planner talks to the MES
via REST / SQL / a message queue / a proprietary API. The MES
translates planner decisions into SECS commands.
**Where it lives in this codebase.** Not implemented; out of scope.
Mentioned here so the reader knows where the recipes and lot
assignments ultimately come from, but no codebase artifact
corresponds to this layer.
---
## 5. AMHS — Automated Material Handling System
**What it is.** The robot-rail network and overhead hoist transport
(**OHT**) system that physically moves carriers (FOUPs holding ~25
wafers each) between tools. In a modern 300 mm fab the AMHS is
*always* moving carriers between tools 24/7; humans never touch a
substrate.
**What it does in SECS/GEM terms.**
- The AMHS itself **doesn't speak SECS/GEM** — it has its own
control plane talking to a Material Control System (MCS) which is
conceptually peer to the MES.
- But every time a carrier *arrives at* or *departs from* an
equipment's load port, the AMHS-side robot and the equipment-side
load port **handshake over 8 parallel I/O lines** defined by
**E84**. This is a physical-layer handshake (CMOS-level voltages
on real wires) with strict timing — TA1, TA2, TA3 timers — to
make sure a $20 000 FOUP doesn't get dropped because both sides
thought the other one was holding it.
- Once the carrier is physically docked, the equipment fires a
`S6F11(CarrierArrived)` event to the MES and the MES sends back a
`S3F17(CarrierAction=ProceedWithCarrier)` to authorise processing.
**Where it lives in this codebase.**
- The E84 handshake state machine: [`include/secsgem/gem/e84_state.hpp`](../include/secsgem/gem/e84_state.hpp)
+ [`src/gem/e84_state.cpp`](../src/gem/e84_state.cpp).
- The TA1/TA2/TA3 timer wiring (asio): [`include/secsgem/gem/e84_asio_timers.hpp`](../include/secsgem/gem/e84_asio_timers.hpp).
- The per-port store: [`include/secsgem/gem/store/e84_ports.hpp`](../include/secsgem/gem/store/e84_ports.hpp).
- Tests covering the timing rules: [`tests/test_e84.cpp`](../tests/test_e84.cpp),
[`tests/test_e84_timers.cpp`](../tests/test_e84_timers.cpp),
[`tests/test_e84_asio_timers.cpp`](../tests/test_e84_asio_timers.cpp),
[`tests/test_e84_ports.cpp`](../tests/test_e84_ports.cpp).
Chapter [18](18_e84_parallel_io.md) covers E84 in full.
---
## 6. Operator — the human
**What it is.** The fab technician at the tool's local panel. Their
job is to handle anything the automation can't: load a non-AMHS
carrier, clear a jammed wafer, run a maintenance recipe, respond to
an alarm the MES can't auto-clear.
**What they do in SECS/GEM terms.**
- **Mode switch.** The operator can push the equipment between
control states: `EquipmentOffline`, `OnlineLocal` (commands
accepted only from the local panel), `OnlineRemote` (commands
accepted from the MES). This is E30 §6.2.
- **Override.** An operator can override an MES command (refuse to
start, force-clear an alarm, manually unload a carrier). In
SECS/GEM terms this is reflected by control-state transitions:
`OnlineRemote` → `OnlineLocal` means "operator has taken control."
- **Local alarm acknowledgement.** Some alarms can be cleared at
the panel without the MES being involved; the equipment then
emits an `S5F1` with the cleared bit so the MES catches up.
**Where it lives in this codebase.**
- The control state machine: [`include/secsgem/gem/control_state.hpp`](../include/secsgem/gem/control_state.hpp)
+ [`src/gem/control_state.cpp`](../src/gem/control_state.cpp).
- The transition table loaded from YAML: [`data/control_state.yaml`](../data/control_state.yaml).
- The operator-initiated transition handlers:
`ControlStateMachine::operator_online`, `::operator_offline`,
`::operator_local`, `::operator_remote` in the same header.
- Tests: [`tests/test_control_state.cpp`](../tests/test_control_state.cpp).
Chapter [13](13_e30_gem.md) walks through control state in detail.
---
## Who talks to whom
A short reference table. "Init." marks who initiates the
conversation; "Channel" marks the protocol layer.
| Pair | Init. | Channel | Examples |
|----------------------------|------------|---------------------------------------------|-----------------------------------------------------------|
| Planner ↔ MES | Planner | REST / SQL / queue (out of scope) | "run lot L on tool T with recipe R" |
| MES ↔ EAP | MES | HSMS-SS (one TCP socket, equipment passive) | `S1F1`, `S2F41`, `S6F11`, `S5F1`, … |
| MES ↔ EAP (multi-MES) | MES | HSMS-GS (one TCP socket, multiple sessions) | Same messages, demuxed by session_id |
| EAP ↔ Equipment | Either | PLC / sensor APIs / recipe engine (tool-specific) | Out of scope of SECS/GEM |
| AMHS ↔ Load port | AMHS | E84 8-line parallel I/O | VALID/CS_0/CS_1/TR_REQ/READY/BUSY/COMPT/CONT/L_REQ/U_REQ/ES |
| MES ↔ EAP (carrier flow) | Equipment | HSMS | `S6F11(CarrierArrived)`, `S3F17(ProceedWithCarrier)` |
| Operator ↔ Equipment | Operator | Local panel | Online/Offline buttons, alarm acks |
The four interesting things in this table:
1. **The MES is the active side, the equipment is the passive side.**
Always. Equipment binds the port; MES connects to it. Some MES
want this reversed and will negotiate, but the GEM default is
equipment-passive.
2. **One TCP socket per (MES, equipment) pair.** HSMS-SS doesn't
multiplex; one connection serves one conversation. HSMS-GS adds
session multiplexing on top.
3. **Equipment-initiated traffic exists.** `S6F11` events and
`S5F1` alarms fire from equipment to MES *autonomously*, not
in reply to a host command. An EAP that never emits unsolicited
traffic is broken.
4. **The AMHS handshake is out-of-band relative to SECS/GEM.**
E84's 8 parallel I/O lines are real wires with real voltages;
the SECS messages that follow (`S6F11`, `S3F17`) are just the
*bookkeeping* around a handoff that already happened in
hardware.
---
## A small mental check
If you've internalised the chapter, you should be able to answer:
1. When the MES sends `S1F13`, who initiates the TCP connection?
2. When a chamber pressure sensor reads out of range, who decides
whether to fire `S5F1`?
3. What language does the AMHS speak to the equipment to coordinate
a FOUP handoff?
4. Is the operator at the local panel a SECS/GEM actor?
5. Is the fab planner a SECS/GEM actor?
Answers, in order:
1. The MES. The equipment is passive; it binds and waits. TCP
connect is the MES's first move.
2. The EAP (the vendor's application code on top of this library).
The SECS/GEM library doesn't know what's a "normal" pressure;
the EAP does. Once the EAP decides "this is alarm-worthy," it
calls into the alarm store and the library emits `S5F1`.
3. E84 8-line parallel I/O — physical wires, not SECS. After the
handoff, the *bookkeeping* SECS messages (`S6F11`, `S3F17`) flow
between equipment and MES.
4. Yes — through E30 §6.2 control-state transitions. Not a SECS
message *sender*, but a state-transition source the equipment
has to report on.
5. No. The planner talks to the MES; the MES talks to the EAP.
The planner is invisible from the SECS wire.
---
## What's next
You now know who's in the room and who's talking to whom. The next
chapter introduces the **vocabulary** — every SEMI acronym you'll
read in a debug log (SVID, CEID, ALID, PPID, ALCD, HCACK, T-timers,
…) — by tracing **one wafer's journey** end-to-end through a fab and
labelling every SECS message that fires along the way.
Next: [→ 03 Vocabulary + a wafer's journey](03_vocabulary_and_a_wafers_journey.md)