From cd1f2528e8243fed3ce80d5170ef93928e4e7284 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 6 Oct 2026 19:28:39 -0400 Subject: risc-v-gsp-rm-debugger: land docs 45-53 + harness/sim tool set with tests rm_capture (chunked decode), launch_audit, state_seed/state_decode, valprobe, rehost, contracts+run_contracts, host_traffic, gmmu_walk, msgq_attach, libos_port, log_decode, server_snapshot; doc index updates in the tool overview, operations pages and the repo README. --- debug/risc-v-gsp-rm-vm/harness/state_decode.py | 1082 ++++++++++++++++++++++++ 1 file changed, 1082 insertions(+) create mode 100644 debug/risc-v-gsp-rm-vm/harness/state_decode.py (limited to 'debug/risc-v-gsp-rm-vm/harness/state_decode.py') diff --git a/debug/risc-v-gsp-rm-vm/harness/state_decode.py b/debug/risc-v-gsp-rm-vm/harness/state_decode.py new file mode 100644 index 0000000..351515a --- /dev/null +++ b/debug/risc-v-gsp-rm-vm/harness/state_decode.py @@ -0,0 +1,1082 @@ +#!/usr/bin/env python3 +"""Decode engine-visible channel state words into named fields, and diff captures. + +During GR bring-up the answer often hides in a handful of 32-bit words inside +the INSTANCE block, the RAMFC chunk and context-buffer headers: one bit turns +"nothing happens" into an engine that runs or refuses. Raw hex hides that; +this tool turns a captured dump into a named field table and makes two +captures differ field-by-field. + +Schemas: + +* ``greeneye-state-decode/1`` -- the decoded report produced by ``decode``. +* ``greeneye-state-diff/1`` -- the word/field diff produced by ``diff``. +* ``greeneye-server-snapshot/1`` -- an input snapshot emitted elsewhere:: + + {"schema": "greeneye-server-snapshot/1", "source": "...", + "chunks": [{"label": "INSTANCE", "base": "0x0", + "words": ["0x...", "..."]}]} + + (one hex string or integer per 32-bit word; accepted exactly). +* ``greeneye-state-map/1`` -- an optional field map (``--map``), see below. + +Input formats (auto-detected per ``--input``): + +(a) text lines ``LABEL[OFFSET]=VALUE`` -- label case-insensitive, offset and + value hex (``0x..``, letters, or leading-zero padded) or decimal; every + other line is ignored; +(b) a dump row with a bracketed chunk offset and words, e.g. + ``... INSTANCE[0040]: 00100000 00030000 ...`` -- this is the shape live + ladder traces print (8 words per row; any count accepted); +(c) plain hexdump rows ``00000000: 000002d2 00000000 ...`` named with + ``--label``/``--base``; +(d) raw little-endian u32 words (``--bin``, or auto-detected when a text parse + finds nothing and the bytes are control-heavy and 4-byte aligned); +(e) the snapshot JSON above. + +Offsets inside a chunk are byte offsets relative to the chunk start (all +inputs above are u32 word dumps, so offsets are multiples of 4). ``base`` is +the engine-visible address of chunk-relative offset 0: it is recorded as +provenance and for the diff, but it does not shift map lookup. + +Bundled map (deliberately small; extend or override it from a map file, never +by guessing here). Provenance is live bring-up observation (2026-10 GSP +ladder runs): + +* ``INSTANCE`` 0x010: magic ``0xface``. +* ``INSTANCE`` 0x048: GPFIFO VA, observed as ``0x100000``. +* ``RAMFC`` 0x048: ``RAMFC_TARGET`` -- bits 16/17 ``ENG_CTX_VALID`` / + ``CE_CTX_VALID``; the observed live success word ``0x00030000`` sets both. + The bit assignment is observation-driven and fully configurable via the map. + +Map file:: + + {"format": "greeneye-state-map/1", "mode": "extend" | "replace", + "entries": [ + {"chunk": "RAMFC", "label": "RAMFC_TARGET", "offset": "0x48", + "width": 4, + "bits": [{"name": "ENG_CTX_VALID", "lo": 16, "hi": 16, + "values": {"0": "clear", "1": "set"}}], + "note": "..."} + ]} + +A user entry with the same ``chunk`` and ``offset`` replaces the bundled +entry; new chunk/offset pairs extend the table. ``mode: replace`` drops the +bundled table first. An entry without ``bits`` decodes as a named value. + +Honesty: this tool names observed words; it does not prove their meaning. An +unmapped word is silence, not absence. Field offsets without evidence stay +unnamed until a map supplies them. Offline only: no hardware, no module, no +guest, no network. +""" +from __future__ import annotations + +import argparse +import json +import os +import re +import shutil +import sys +import tempfile +from typing import Any + +DECODE_FORMAT = "greeneye-state-decode/1" +DIFF_FORMAT = "greeneye-state-diff/1" +SNAPSHOT_FORMAT = "greeneye-server-snapshot/1" +MAP_FORMAT = "greeneye-state-map/1" +DEMO_FORMAT = "greeneye-state-decode-demo/1" + +WORD_BYTES = 4 +WORD_MASK = 0xFFFFFFFF +WORD_WIDTHS = (4, 8) + + +class StateDecodeError(ValueError): + """An input, map or request the tool cannot honour.""" + + +# --------------------------------------------------------------------------- +# Bundled field table +# --------------------------------------------------------------------------- +# Every entry is an observation from live GSP bring-up traces (2026-10). The +# table is intentionally tiny: unnamed offsets stay unnamed until evidence +# earns them a name, and the map file carries everything else. +BUILTIN_MAP: dict[str, Any] = { + "format": MAP_FORMAT, + "mode": "extend", + "entries": [ + { + "chunk": "INSTANCE", + "label": "MAGIC_0FACE", + "offset": "0x010", + "width": 4, + "note": "Instance magic observed as 0xface at chunk byte 0x010.", + }, + { + "chunk": "INSTANCE", + "label": "GPFIFO_VA", + "offset": "0x048", + "width": 4, + "note": "GPFIFO VA observed as 0x100000 at chunk byte 0x048.", + }, + { + "chunk": "RAMFC", + "label": "RAMFC_TARGET", + "offset": "0x048", + "width": 4, + "bits": [ + {"name": "ENG_CTX_VALID", "lo": 16, "hi": 16}, + {"name": "CE_CTX_VALID", "lo": 17, "hi": 17}, + ], + "note": ("Engine/CE context-valid bits; the observed live success " + "word 0x00030000 sets both. Bits are configurable via " + "--map."), + }, + ], +} + +# --------------------------------------------------------------------------- +# Number and token parsing +# --------------------------------------------------------------------------- + +_EQ_RE = re.compile( + r"^\s*(?P