105 lines
5.8 KiB
Markdown
105 lines
5.8 KiB
Markdown
# Provenance of flowrs-record
|
||
|
||
Everything in this crate is written for flowRS and licensed MIT OR Apache-2.0, apart from
|
||
Howard Hinnant's public-domain date algorithms (see `NOTICE`). Per-file origins are listed in
|
||
`tools/runtime-licence.tsv`. This file records where the record formats' facts come from.
|
||
|
||
## Re-cited to primary sources (2026-10-27)
|
||
|
||
The licence audit found two files that had read interoperability facts from GPL projects:
|
||
|
||
- `src/stdf.rs` took its field order from pystdf (GPL-2.0);
|
||
- `src/hardpy.rs` took its key names and enum strings from HardPy's schema module (GPL-3.0).
|
||
|
||
Facts are not copyrightable, but the porting policy wants them cited to a primary source. Each
|
||
file was compared with the sources below, not with the GPL projects.
|
||
|
||
### `src/stdf.rs`: the STDF V4 specification
|
||
|
||
| Source | Licence | Checked |
|
||
|---|---|---|
|
||
| Teradyne, *Standard Test Data Format (STDF) Specification, Version 4* (FrameMaker edition of 1999-07-06, 103 pages; read from the Internet Archive's copy of `kanwoda.com/wp-content/uploads/2015/05/std-spec.pdf`) | Teradyne documentation; facts only | See below |
|
||
| *STDF V4-2007 Specification* (from roos.com) | documentation; facts only | The table of record types and sub-types |
|
||
|
||
The following match the specification:
|
||
|
||
- the record header (`REC_LEN` U*2, data bytes only, then `REC_TYP` and `REC_SUB`);
|
||
- every record's type and sub-type: FAR 0/10, MIR 1/10, MRR 1/20, PCR 1/30, HBR 1/40, SBR 1/50,
|
||
PIR 5/10, PRR 5/20 and PTR 15/10;
|
||
- the field order of every record the writer emits and the reader decodes, field by field
|
||
against the specification's tables;
|
||
- `CPU_TYPE` 2 (little-endian), `STDF_VER` 4, and the missing-data values (`BURN_TIM` 65535,
|
||
`X_COORD`/`Y_COORD` −32768, `TEST_T` 0, the space for C*1);
|
||
- `TEST_FLG` bit 7 (test failed), `PART_FLG` bit 3 (part failed), `HBIN_PF`/`SBIN_PF` `P`/`F`;
|
||
- the rule that only optional fields at the end of a record may be left off.
|
||
|
||
The writer builds each record with one small encoder per STDF data type, in the
|
||
specification's field order. It is not a table of field descriptors, which is how pystdf
|
||
describes records.
|
||
|
||
**Deviation found and fixed (2026-10-27).** The writer used to mark an absent low (or high)
|
||
test limit with `OPT_FLAG` bit 4 (or 5), and the reader took that bit to mean "absent". It
|
||
also wrote the reserved bit 1 as 0. The specification's PTR field description says:
|
||
|
||
- bit 1 is "reserved for future used and must be 1";
|
||
- bit 4 means "LO_LIMIT and LLM_SCAL are invalid. The default values set for these fields in
|
||
the first PTR with this test number will be used", and bit 5 the same for the high limit;
|
||
- "No Low Limit for this test" is bit 6, and "No High Limit" bit 7.
|
||
|
||
The writer now sets bit 1 always, bits 2 and 3 (no LO_SPEC or HI_SPEC is written), and bit 6 or
|
||
7 for an absent limit. It never sets bits 4 or 5: each PTR it writes is the first for its test
|
||
number and carries its own limits. A PTR's `OPT_FLAG` is therefore 0x0E with both limits, 0x8E
|
||
with only a low limit, 0x4E with only a high limit, and 0xCE with none.
|
||
|
||
The reader follows the specification too. A field after `ALARM_ID` that a PTR leaves out, or
|
||
that bit 4 or 5 marks invalid, takes the value of the first PTR with the same test number.
|
||
Bits 6 and 7 mean the test has no such limit. Files flowRS wrote before the fix still read
|
||
correctly: bit 4 or 5 sat on the first PTR for its test, which has nothing to inherit, so the
|
||
limit stays absent.
|
||
|
||
The unit tests and `tools/verify_stdf.py` pin the exact bytes and cite the field description.
|
||
`tools/mutate-stdf.sh` checks that the tests catch each wrong bit.
|
||
|
||
pystdf (GPL-2.0) is only run out of process, as an independent reader of what the writer
|
||
emits (`tools/verify_stdf.py`).
|
||
|
||
### `src/hardpy.rs`: HardPy's public documentation, as an interoperability format
|
||
|
||
| Source | Licence | Checked |
|
||
|---|---|---|
|
||
| HardPy documentation, *Database* (`everypinio.github.io/hardpy/documentation/database/`, read 2026-10-27) | Documentation of a GPL-3.0 project; names only | Listed below |
|
||
| HardPy documentation, *pytest-hardpy* API (`everypinio.github.io/hardpy/documentation/pytest_hardpy/`) | as above | Listed below |
|
||
|
||
The *Database* page gives:
|
||
|
||
- the report keys: `_id`, `_rev`, `name`, `status`, `start_time` and `stop_time` (Unix
|
||
seconds), `dut`, `test_stand`, `process`, `modules`, `user`, `batch_serial_number`,
|
||
`caused_dut_failure_id`, `error_code` and `artifact`;
|
||
- the fields of `dut` (`name`, `type`, `serial_number`, `part_number`, `revision`,
|
||
`sub_units`, `info`), of `test_stand` (`hw_id`, `name`, `revision`, `timezone`, `location`,
|
||
`number`, `instruments`, `info`) and of `process` (`name`, `number`, `info`);
|
||
- a module's and a case's keys;
|
||
- a numeric measurement's keys (`type` `numeric`, `value`, `name`, `unit`, `operation`,
|
||
`comparison_value`, `lower_limit`, `upper_limit`, `result`);
|
||
- the statuses `passed`, `failed`, `skipped` and `stopped`.
|
||
|
||
The API page names the comparison operations and gives the role of `lower_limit`,
|
||
`upper_limit` and `comparison_value`.
|
||
|
||
**Flagged: three names the documentation does not settle.** The module writes them as an
|
||
earlier reading of HardPy's schema module found them:
|
||
|
||
- operations in lower case (`gtlt`), where the documentation's example shows `"GTLT"`;
|
||
- the status `error`;
|
||
- a case's `attempt` key.
|
||
|
||
They should be checked by running HardPy as a black-box oracle: build a report with HardPy's
|
||
public API, serialise it, and compare. That was not done in this session, because running
|
||
HardPy here was not approved.
|
||
|
||
### `src/opentap.rs`: names only
|
||
|
||
`ResultTable` (a name and an array of `ResultColumn`), `ResultColumn` (`Name`, `Data`) and the
|
||
`Verdict` names (`NotSet`, `Pass`, `Inconclusive`, `Fail`, `Aborted`, `Error`) are cited from
|
||
OpenTAP's public API reference and documentation (`doc.opentap.io`, 9.35). No OpenTAP code
|
||
(MPL-2.0) is in this crate.
|