dac0747bb4
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
116 lines
8.9 KiB
JSON
116 lines
8.9 KiB
JSON
{
|
||
"_description": "S7-1500 profile — DB1 (2048 bytes) + MB (256 bytes) + TM/CT (64 bytes each) with well-known seeds at named offsets for the smoke + byte-order + string + Timer/Counter tests. Big-endian Siemens wire order throughout.",
|
||
"areas": [
|
||
{
|
||
"area": "DB",
|
||
"index": 1,
|
||
"size": 2048,
|
||
"seeds": [
|
||
{ "_desc": "DB1.DBW0 — read-back probe, S7Driver default ProbeAddress target is MW0; this shadows it",
|
||
"offset": 0, "type": "u16", "value": 4242 },
|
||
{ "_desc": "DB1.DBW10 — i16 smoke value for SmokeI16 read path",
|
||
"offset": 10, "type": "i16", "value": -12345 },
|
||
{ "_desc": "DB1.DBD20 — i32 smoke value for SmokeI32 read path",
|
||
"offset": 20, "type": "i32", "value": 1234567890 },
|
||
{ "_desc": "DB1.DBD30 — f32 smoke value for SmokeF32 read path (IEEE-754 big-endian)",
|
||
"offset": 30, "type": "f32", "value": 3.14159 },
|
||
{ "_desc": "DB1.DBX50.3 — bool bit at byte-50 bit-3 for SmokeBool read path",
|
||
"offset": 50, "type": "bool", "value": true, "bit": 3 },
|
||
{ "_desc": "DB1.DBW100 — scratch for write-then-read round-trip tests; seeded 0",
|
||
"offset": 100, "type": "u16", "value": 0 },
|
||
{ "_desc": "DB1.STRING[200] — S7 string 'Hello' (max 32, cur 5)",
|
||
"offset": 200, "type": "ascii", "value": "Hello", "max_len": 32 },
|
||
|
||
{ "_desc": "DB1.DBW300 — span-planner gate (S7_1500SpanReadTests) starts here. Cluster A spans 300..320 and merges into ONE block read under the 16-byte gap budget. Every seed from 300 on is distinct and non-zero so a mis-sliced block can never accidentally match (the #536 zero-source trap).",
|
||
"offset": 300, "type": "u16", "value": 51001 },
|
||
{ "_desc": "DB1.DBW302 — cluster A, adjacent to DBW300 (gap 0)",
|
||
"offset": 302, "type": "i16", "value": -21001 },
|
||
{ "_desc": "DB1.DBD304 — cluster A, adjacent to DBW302 (gap 0)",
|
||
"offset": 304, "type": "i32", "value": 305419896 },
|
||
{ "_desc": "DB1 @308 — POISON in the 308..310 hole the span reads through; no tag maps here, so a mis-slice yields 0xDEAD rather than a zero that could pass by luck",
|
||
"offset": 308, "type": "u16", "value": 57005 },
|
||
{ "_desc": "DB1.DBX310.5 — cluster A bool (gap 2 from the DBD304 end)",
|
||
"offset": 310, "type": "bool", "value": true, "bit": 5 },
|
||
{ "_desc": "DB1 @311 — POISON in the 311..316 hole",
|
||
"offset": 311, "type": "u8", "value": 90 },
|
||
{ "_desc": "DB1 @312 — POISON in the 311..316 hole (0xDEADBEEF)",
|
||
"offset": 312, "type": "u32", "value": 3735928559 },
|
||
{ "_desc": "DB1.DBD316 — cluster A f32, gap 5 from the bool byte's end; seals the span at 300..320 = 20 bytes",
|
||
"offset": 316, "type": "f32", "value": 2.7182817 },
|
||
|
||
{ "_desc": "DB1.DBW400 — cluster B; 80 bytes past cluster A's end, so the 16-byte gap budget forces a SECOND span rather than one merged read",
|
||
"offset": 400, "type": "u16", "value": 40201 },
|
||
{ "_desc": "DB1.DBW402 — cluster B's second member; two members keep the span off the PrefersPerTagRead demotion",
|
||
"offset": 402, "type": "u16", "value": 40202 },
|
||
|
||
{ "_desc": "DB1.DBW500 — isolated narrow scalar: its own single-member span, demoted by PrefersPerTagRead into a leftover that rides the multi-var pass",
|
||
"offset": 500, "type": "u16", "value": 60001 },
|
||
{ "_desc": "DB1.DBW600 — second isolated narrow scalar, likewise a multi-var leftover",
|
||
"offset": 600, "type": "i16", "value": -32001 },
|
||
|
||
{ "_desc": "CODEC GATE (S7_1500CodecTests, #632/#638). Every seed from 800 to 969 is distinct and non-zero so a decode that returns zero/default can never pass. 800: STRING max 32 cur 10 'Siemens S7'",
|
||
"offset": 800, "type": "ascii", "value": "Siemens S7", "max_len": 32 },
|
||
{ "_desc": "DB1 @840 — WSTRING max 8 cur 5 'Grüße' (ü=00FC, ß=00DF) — non-ASCII proves UTF-16BE, not Latin-1",
|
||
"offset": 840, "type": "hex", "value": "0008 0005 0047 0072 00fc 00df 0065" },
|
||
{ "_desc": "DB1 @870 — CHAR 'Q'", "offset": 870, "type": "u8", "value": 81 },
|
||
{ "_desc": "DB1 @872 — WCHAR U+20AC '€' (does not fit Latin-1)", "offset": 872, "type": "u16", "value": 8364 },
|
||
{ "_desc": "DB1 @880 — DTL 2024-03-15 13:45:56.7890123 (weekday 6 = Friday, ns 789012300)",
|
||
"offset": 880, "type": "hex", "value": "07e8 03 0f 06 0d 2d 38 2f075f4c" },
|
||
{ "_desc": "DB1 @900 — DATE 2021-06-15 = 11488 days since 1990-01-01", "offset": 900, "type": "u16", "value": 11488 },
|
||
{ "_desc": "DB1 @904 — TOD 13:45:56.789 = 49556789 ms", "offset": 904, "type": "u32", "value": 49556789 },
|
||
{ "_desc": "DB1 @910 — TIME +123456789 ms", "offset": 910, "type": "i32", "value": 123456789 },
|
||
{ "_desc": "DB1 @914 — TIME -86400123 ms (negative duration)", "offset": 914, "type": "i32", "value": -86400123 },
|
||
{ "_desc": "DB1 @920 — S5TIME 0x2789: base 2 (x1 s), BCD 789 = 789000 ms", "offset": 920, "type": "u16", "value": 10121 },
|
||
{ "_desc": "DB1 @922 — S5TIME 0x0123: base 0 (x10 ms), BCD 123 = 1230 ms", "offset": 922, "type": "u16", "value": 291 },
|
||
|
||
{ "_desc": "UNDECODABLE buffers — reads must surface BadOutOfRange, not a value. @930 DTL stays all-zero (uninitialised) on purpose. @940: S5TIME 0x0A5F has a non-BCD nibble",
|
||
"offset": 940, "type": "u16", "value": 2655 },
|
||
{ "_desc": "DB1 @944 — TOD 0xFFFFFFFF, past midnight", "offset": 944, "type": "u32", "value": 4294967295 },
|
||
{ "_desc": "DB1 @950 — WSTRING max 3 cur 9 (current length exceeds reserved)",
|
||
"offset": 950, "type": "hex", "value": "0003 0009" },
|
||
{ "_desc": "DB1 @960 — DATE 0xFFFF = 65535 days = 2169-06-06, the far end of the DATE range (still a valid decode)",
|
||
"offset": 960, "type": "u16", "value": 65535 }
|
||
]
|
||
},
|
||
{
|
||
"area": "MK",
|
||
"index": 0,
|
||
"size": 256,
|
||
"seeds": [
|
||
{ "_desc": "MW0 — probe target for S7ProbeOptions.ProbeAddress default",
|
||
"offset": 0, "type": "u16", "value": 1 },
|
||
{ "_desc": "MW10 — span-planner gate: a narrow scalar in a DIFFERENT area from the DB1 leftovers. A block read can never merge across (area, DB); the multi-var pass can, so this pins that the leftover batching crosses the boundary.",
|
||
"offset": 10, "type": "u16", "value": 4097 }
|
||
]
|
||
},
|
||
{
|
||
"_desc": "TM (timers) — 64 bytes = 32 timer cells. A timer is a 2-byte S5TIME word and timer number N lives at byte offset 2*N, so the offsets below ARE the timer numbers doubled. Values are S5TIME-encoded (bits 12..13 = time base, the remaining three nibbles = a BCD 0..999 count) and each decodes to a distinct NON-ZERO duration, because a zero-valued timer reads the same as a timer that was never served at all (the #536 trap). ⚠️ Only T0 is readable through this fixture — see the CT note below and Docker/README.md §'Timer / Counter (TM / CT) areas'.",
|
||
"area": "TM",
|
||
"index": 0,
|
||
"size": 64,
|
||
"seeds": [
|
||
{ "_desc": "T0 @ byte 0 — 0x2456: base 2 (×1s), BCD 456 ⇒ 456.0 seconds. Device 0 is the one cell where snap7's address resolution and a real CPU's agree, so this is the seed S7_1500SpanReadTests asserts on.",
|
||
"offset": 0, "type": "u16", "value": 9302 },
|
||
{ "_desc": "T5 @ byte 10 — 0x1123: base 1 (×0.1s), BCD 123 ⇒ 12.3 seconds. Reachable only from a real CPU (S7_TIMER_NUMBER_ADDRESSING=1).",
|
||
"offset": 10, "type": "u16", "value": 4387 },
|
||
{ "_desc": "T9 @ byte 18 — 0x0250: base 0 (×0.01s), BCD 250 ⇒ 2.5 seconds. Real CPU only, as above.",
|
||
"offset": 18, "type": "u16", "value": 592 }
|
||
]
|
||
},
|
||
{
|
||
"_desc": "CT (counters) — 64 bytes = 32 counter cells, counter number N at byte offset 2*N. The driver surfaces a counter as the RAW big-endian word (S7Driver.DecodeScalarBlock via S7.Net's Counter.FromByteArray), so these seeds are plain u16 counts; distinct + non-zero for the same reason as the timers. ⚠️ snap7's server resolves the TM/CT request address as a BIT address (byte = addr>>3) instead of as a device NUMBER, while S7.Net (and a real CPU) put the device number there — so a read of C{n} lands on byte n>>3, and device 0 is the only n where the two conventions coincide. Live-probed 2026-08-17; see Docker/README.md.",
|
||
"area": "CT",
|
||
"index": 0,
|
||
"size": 64,
|
||
"seeds": [
|
||
{ "_desc": "C0 @ byte 0 — count 4711. The device-0 cell both conventions agree on; asserted by S7_1500SpanReadTests.",
|
||
"offset": 0, "type": "u16", "value": 4711 },
|
||
{ "_desc": "C7 @ byte 14 — count 31337. Reachable only from a real CPU (S7_TIMER_NUMBER_ADDRESSING=1).",
|
||
"offset": 14, "type": "u16", "value": 31337 },
|
||
{ "_desc": "C11 @ byte 22 — count 1234. Real CPU only, as above.",
|
||
"offset": 22, "type": "u16", "value": 1234 }
|
||
]
|
||
}
|
||
]
|
||
}
|