AA: catalog growth — S7F1/F17, S6F5-F22, S2F21, S12F9-F18

Adds the SECS-II messages secsgem-py 0.3.0 ships but our C++ catalog
didn't have, plus the alternative wafer-map formats from E5 §13.
None of these were strictly required for GEM core compliance, but
they're the messages a host might send to a conformant equipment.

  * S7F1/F2 — Process Program Load Inquire / Grant.  Equipment-side
    space-and-policy check before a host commits to S7F3.
  * S7F17/F18 — Delete Process Program.  Empty list = delete-all.
  * S6F5/F6 — Multi-block Data Send Inquire / Grant (with MultiBlockGrant
    enum: Ok/Busy/NoSpace/DuplicateMsg/BadMsg).
  * S6F7/F8 — Data Transfer Request / Send.  Host pulls a DATAID;
    equipment replies with the nested DS/DV structure.
  * S6F15/F16 — Event Report Request (host-initiated).  Reply mirrors
    the unsolicited S6F11.
  * S6F19/F20 — Individual Report Request (RPTID -> values).
  * S6F21/F22 — Annotated Individual Report Request (RPTID -> (VID, value)).
  * S2F21/F22 — Legacy Remote Command (no parameter list).  Delegates
    to the same HostCommandRegistry as S2F41.
  * S12F9/F10 — Map Data Send (array format, MAPFT=1).
  * S12F11/F12 — Map Data Send (coordinate format, MAPFT=2).
  * S12F13/F14, F15/F16, F17/F18 — Map Data Request variants for the
    row, array, and coordinate formats.

11 new round-trip tests; suite at 289 cases / 1495 assertions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 23:30:51 +02:00
parent 2d60571a9c
commit 4197cdfb25
4 changed files with 666 additions and 1 deletions
+403
View File
@@ -520,6 +520,26 @@ messages:
# values; every REPGSZ samples it emits an S6F1 batch; after TOTSMP
# total samples it stops. Periodic execution is the application's
# responsibility; this codebase only stores the request.
# S2F21 / S2F22 — Remote Command (legacy form, E5). No parameter
# list — just the command name. Modern usage prefers S2F41/F42 which
# carry CP name/value pairs, but some older hosts still send the F21
# form so we accept it. CMDA is a U1 ack code: 0=Accept,
# 1=CannotPerformNow, 2=CommandDoesNotExist, etc. (same enum as
# HostCmdAck which we use throughout the codebase).
- id: S2F21
stream: 2
function: 21
w: true
builder: s2f21_remote_command
parser: parse_s2f21
body: {kind: scalar, item_type: ASCII, param: rcmd}
- id: S2F22
stream: 2
function: 22
builder: s2f22_remote_command_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: HostCmdAck, param: cmda}
- id: S2F23
stream: 2
function: 23
@@ -905,6 +925,151 @@ messages:
builder: s6f12_event_report_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: EventReportAck, param: ack}
# S6F5 / S6F6 — Multi-block Data Send Inquire / Grant. Equipment
# asks permission before pushing a large S6F11 (or other primary) of
# DATALENGTH bytes; host replies with GRANT6 (0=OK, 1=Busy, 2=NoSpace,
# 3=DuplicateMsg, 4=BadMsg). HSMS doesn't need this for sizing
# reasons (no 244-byte block ceiling), but the spec contract is kept.
- id: S6F5
stream: 6
function: 5
w: true
builder: s6f5_multi_block_inquire
parser: parse_s6f5
body:
kind: list
struct_name: MultiBlockInquire
fields:
- {name: dataid, shape: {kind: scalar, item_type: U4}}
- {name: datalength, shape: {kind: scalar, item_type: U4}}
- id: S6F6
stream: 6
function: 6
builder: s6f6_multi_block_grant
body: {kind: scalar, item_type: BINARY_BYTE, enum: MultiBlockGrant, param: grant6}
# S6F7 / S6F8 — Data Transfer Request / Send. Host pulls a previously
# announced data set by DATAID; equipment responds with the full
# `[CEID, [[DSID, [[DVNAME, DVVAL], ...]], ...]]` structure.
- id: S6F7
stream: 6
function: 7
w: true
builder: s6f7_data_transfer_request
parser: parse_s6f7
body: {kind: scalar, item_type: U4, param: dataid}
- id: S6F8
stream: 6
function: 8
builder: s6f8_data_transfer_send
parser: parse_s6f8
body:
kind: list
struct_name: DataTransferSend
fields:
- {name: dataid, shape: {kind: scalar, item_type: U4}}
- {name: ceid, shape: {kind: scalar, item_type: U4}}
- name: data_sets
shape:
kind: list_of
element:
kind: list
struct_name: DataSet
fields:
- {name: dsid, shape: {kind: scalar, item_type: U4}}
- name: values
shape:
kind: list_of
element:
kind: list
struct_name: NamedValue
fields:
- {name: dvname, shape: {kind: scalar, item_type: ASCII}}
- {name: dvval, shape: {kind: scalar, item_type: ITEM}}
# S6F15 / S6F16 — Event Report Request / Send (host-initiated).
# Host asks for the latest report payload bound to CEID; equipment
# replies with the same body shape as the unsolicited S6F11.
- id: S6F15
stream: 6
function: 15
w: true
builder: s6f15_event_report_request
parser: parse_s6f15
body: {kind: scalar, item_type: U4, param: ceid}
- id: S6F16
stream: 6
function: 16
builder: s6f16_event_report_data
parser: parse_s6f16
body:
kind: list
struct_name: EventReportMessage
fields:
- {name: dataid, shape: {kind: scalar, item_type: U4}}
- {name: ceid, shape: {kind: scalar, item_type: U4}}
- name: reports
shape:
kind: list_of
element:
kind: list
struct_name: ReportData
external_struct: true
fields:
- {name: rptid, shape: {kind: scalar, item_type: U4}}
- name: values
shape: {kind: list_of, element: {kind: scalar, item_type: ITEM}}
# S6F19 / S6F20 — Individual Report Request / Data (host-initiated).
# Host pulls a specific RPTID; equipment replies with the list of VID
# values that report currently holds.
- id: S6F19
stream: 6
function: 19
w: true
builder: s6f19_individual_report_request
parser: parse_s6f19
body: {kind: scalar, item_type: U4, param: rptid}
- id: S6F20
stream: 6
function: 20
builder: s6f20_individual_report_data
parser: parse_s6f20
body:
kind: list_of
element: {kind: scalar, item_type: ITEM}
name: values
# S6F21 / S6F22 — Annotated Individual Report Request / Data.
# Same as S6F19 but the reply carries (VID, V) pairs so the host
# doesn't need to remember the report definition.
- id: S6F21
stream: 6
function: 21
w: true
builder: s6f21_annotated_report_request
parser: parse_s6f21
body: {kind: scalar, item_type: U4, param: rptid}
- id: S6F22
stream: 6
function: 22
builder: s6f22_annotated_report_data
parser: parse_s6f22
body:
kind: list_of
name: items
element:
kind: list
struct_name: AnnotatedValue
fields:
- {name: vid, shape: {kind: scalar, item_type: U4}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
# S6F23 / S6F24 — Request Spooled Data (E30 §6.22; host transmits or purges).
- id: S6F23
stream: 6
@@ -941,6 +1106,29 @@ messages:
# S7 — Process programs
# =====================================================================
# S7F1 / S7F2 — Process Program Load Inquire / Grant. Host announces
# an intended S7F3 of LENGTH bytes; equipment grants or denies based
# on space, busy state, mode etc. PPGNT is the 7-value
# ProcessProgramAck enum (Accept=0 / PermissionNotGranted=1 / ...).
- id: S7F1
stream: 7
function: 1
w: true
builder: s7f1_pp_load_inquire
parser: parse_s7f1
body:
kind: list
struct_name: PPLoadInquire
fields:
- {name: ppid, shape: {kind: scalar, item_type: ASCII}}
- {name: length, shape: {kind: scalar, item_type: U4}}
- id: S7F2
stream: 7
function: 2
builder: s7f2_pp_load_grant
body: {kind: scalar, item_type: BINARY_BYTE, enum: ProcessProgramAck, param: ppgnt}
- id: S7F3
stream: 7
function: 3
@@ -996,6 +1184,26 @@ messages:
element: {kind: scalar, item_type: ASCII}
name: ppids
# S7F17 / S7F18 — Delete Process Program Send / Acknowledge. Body is
# a list of PPIDs to delete; an empty list deletes every PP (the spec
# calls this "delete all"). ACKC7 reuses the S7F4 ack enum.
- id: S7F17
stream: 7
function: 17
w: true
builder: s7f17_delete_pp_send
parser: parse_s7f17
body:
kind: list_of
element: {kind: scalar, item_type: ASCII}
name: ppids
- id: S7F18
stream: 7
function: 18
builder: s7f18_delete_pp_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: ProcessProgramAck, param: ack}
# =====================================================================
# S9 — Protocol error notifications (E5). All carry the 10-byte
# offending message header (MHEAD) as a single BINARY item, except
@@ -1264,6 +1472,201 @@ messages:
builder: s12f8_map_data_send_row_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: MapDataAck, param: maper}
# S12F9 / F10 — Map Data Send (array format, MAPFT=1). The entire
# die grid is one BINARY blob, scanned in the order defined by ORLOC.
# STRP is the starting (col, row) for the first byte of BINLT.
- id: S12F9
stream: 12
function: 9
w: true
builder: s12f9_map_data_send_array
parser: parse_s12f9
body:
kind: list
struct_name: MapDataArray
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- name: strp
shape:
kind: list
struct_name: ReferencePoint
external_struct: true
fields:
- {name: x, shape: {kind: scalar, item_type: I4}}
- {name: y, shape: {kind: scalar, item_type: I4}}
- {name: binlt, shape: {kind: scalar, item_type: BINARY}}
- id: S12F10
stream: 12
function: 10
builder: s12f10_map_data_send_array_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: MapDataAck, param: maper}
# S12F11 / F12 — Map Data Send (coordinate format, MAPFT=2). Each
# entry is a (XYPOS, BIN-byte) pair; sparse maps only carry the dies
# that actually exist. BINLT here is a single BINARY byte (the bin
# code) per coordinate.
- id: S12F11
stream: 12
function: 11
w: true
builder: s12f11_map_data_send_coord
parser: parse_s12f11
body:
kind: list
struct_name: MapDataCoord
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- name: entries
shape:
kind: list_of
element:
kind: list
struct_name: MapDataCoordEntry
fields:
- name: xypos
shape:
kind: list
struct_name: ReferencePoint
external_struct: true
fields:
- {name: x, shape: {kind: scalar, item_type: I4}}
- {name: y, shape: {kind: scalar, item_type: I4}}
- {name: binlt, shape: {kind: scalar, item_type: BINARY}}
- id: S12F12
stream: 12
function: 12
builder: s12f12_map_data_send_coord_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: MapDataAck, param: maper}
# S12F13 / F14 — Map Data Request (row format). Host asks for the
# current map; equipment replies with row payload (RSINF row-start
# info + per-row bin blob).
- id: S12F13
stream: 12
function: 13
w: true
builder: s12f13_map_data_request_row
parser: parse_s12f13
body:
kind: list
struct_name: MapDataIdentifier
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- id: S12F14
stream: 12
function: 14
builder: s12f14_map_data_send_row_reply
parser: parse_s12f14
body:
kind: list
struct_name: MapDataRowReply
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- name: rows
shape:
kind: list_of
element:
kind: list
struct_name: MapDataRowEntry
fields:
- name: rsinf
shape:
kind: list
struct_name: RowStartInfo
fields:
- {name: x, shape: {kind: scalar, item_type: I4}}
- {name: y, shape: {kind: scalar, item_type: I4}}
- {name: direction, shape: {kind: scalar, item_type: I4}}
- {name: binlt, shape: {kind: scalar, item_type: BINARY}}
# S12F15 / F16 — Map Data Request (array format). Same request shape
# as F13; reply mirrors F9.
- id: S12F15
stream: 12
function: 15
w: true
builder: s12f15_map_data_request_array
parser: parse_s12f15
body:
kind: list
struct_name: MapDataIdentifier
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- id: S12F16
stream: 12
function: 16
builder: s12f16_map_data_send_array_reply
parser: parse_s12f16
body:
kind: list
struct_name: MapDataArray
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- name: strp
shape:
kind: list
struct_name: ReferencePoint
external_struct: true
fields:
- {name: x, shape: {kind: scalar, item_type: I4}}
- {name: y, shape: {kind: scalar, item_type: I4}}
- {name: binlt, shape: {kind: scalar, item_type: BINARY}}
# S12F17 / F18 — Map Data Request (coordinate format). Request carries
# SDBIN (the single bin code to filter on, or 0xFF for "all"); reply
# mirrors F11.
- id: S12F17
stream: 12
function: 17
w: true
builder: s12f17_map_data_request_coord
parser: parse_s12f17
body:
kind: list
struct_name: MapDataCoordRequest
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- {name: sdbin, shape: {kind: scalar, item_type: BINARY_BYTE}}
- id: S12F18
stream: 12
function: 18
builder: s12f18_map_data_send_coord_reply
parser: parse_s12f18
body:
kind: list
struct_name: MapDataCoord
fields:
- {name: mid, shape: {kind: scalar, item_type: ASCII}}
- {name: idtyp, shape: {kind: scalar, item_type: BINARY_BYTE}}
- name: entries
shape:
kind: list_of
element:
kind: list
struct_name: MapDataCoordEntry
fields:
- name: xypos
shape:
kind: list
struct_name: ReferencePoint
external_struct: true
fields:
- {name: x, shape: {kind: scalar, item_type: I4}}
- {name: y, shape: {kind: scalar, item_type: I4}}
- {name: binlt, shape: {kind: scalar, item_type: BINARY}}
# S12F19 — Map Error Send. Equipment reports a non-recoverable map
# error (e.g. format mismatch, oversize payload). One-way (no reply).
- id: S12F19