Transcript Parsers
chia_openpiton/parse.py holds pure functions that take text and return data. They do no I/O, start no subprocesses, and need no Ray. Because they decide whether a simulation passed, the tier-0 tests run them against captured logs in chia_openpiton/test/fixtures/, with no toolchain present.
The patterns come from OpenPiton’s source. piton/verif/env/manycore/pc_cmp.v.pyv prints the PASS line once every hart in the finish mask hits the good trap. piton/verif/env/manycore/monitor.v.pyv owns the fail task and the max-cycles abort. OpenPiton’s regreport tool renders status.log and the regression summary.
Verdicts
An RTL simulation exits 0 whether or not the program passed, so the adapter reads the verdict from the transcript. sim_verdict() classifies these lines:
Transcript line |
Verdict |
|---|---|
|
|
|
|
|
|
|
|
|
|
None of these |
|
The PASS line has no space before the colon and the FAIL line has one; the patterns accept both. The checks run in a fixed order: FAIL, then max cycles, then PASS, then -> timeout happen. A FAIL whose message contains TIMEOUT, matched case-insensitively, counts as "timeout". The order makes the parser fail closed: a FAIL line wins over a PASS line in the same transcript, and timeout happen never overrides a verdict line.
Function reference
# sim.log
sim_verdict(text: str) -> Verdict | None
sim_time(text: str) -> int | None
fail_reason(text: str) -> str
max_cycles(text: str) -> int | None
first_requests(text: str) -> dict[int, int] # generic tile: {tile: first request address}
# fake_uart.log
hart_cycles(text: str) -> dict[int, tuple[int, int]]
# status.log
status_diag(text: str) -> tuple[str, str] | None
cycles(text: str) -> int | None
exec_cycles(text: str) -> int | None
num_tiles(text: str) -> int | None
# regreport summary and verilator_coverage
regress_summary(text: str) -> dict[str, object]
coverage_summary(text: str) -> dict[str, object]
# sims output
sims_die(text: str) -> str
model_dir(text: str) -> str
build_failure_reason(stdout: str, stderr: str = "") -> str
build_errors(stdout: str, stderr: str = "", limit: int = 20) -> tuple[str, ...]
undefined_name(error: str) -> tuple[str, str] | None
close_names(name: str, source: str, limit: int = 3) -> tuple[str, ...]
with_close_names(error: str, source: str) -> str
# Verilator
verilator_version(text: str) -> tuple[int, int] | None
needs_no_timing(version_text: str) -> bool
# diaglists and transcripts
diaglist_group(text: str, group: str) -> tuple[DiagEntry, ...]
first_divergence(reference: str, actual: str) -> tuple[int, str, str] | None
Function |
Returns |
|---|---|
|
|
|
The simulation time that prefixes the verdict line, such as |
|
The message inside |
|
The count from a max-cycles abort, or |
|
|
|
|
|
The |
|
A dict with |
|
|
|
The message from |
|
The path from |
|
A failure tag from the table below, or |
|
The first |
|
|
|
Up to |
|
The error with |
|
|
|
|
|
The tests of one diaglist group, as |
|
The 1-based line number and both lines at the first line where the texts differ. |
run() calls sim_verdict and sim_time on the full sim.log, and cycles and exec_cycles on status.log. PitonRunResult.fake_uart keeps the last 8000 characters of fake_uart.log. A hart_cycles line takes about 16 characters, so the kept text holds the line of every hart on a mesh of up to about 500 harts. build() calls needs_no_timing, build_failure_reason, and, on the full output of a failed build, build_errors. For an error that names an undefined name in a file inside the checkout, build() reads that file and appends with_close_names: a misspelled name was the usual failure of RTL repair on build errors (2026-10-23), where the agents declared the misspelled name instead of correcting it. PitonToolServer calls first_divergence, and the MACE shell calls coverage_summary (see Code Coverage).
Diaglists
diaglist_group returns the tests in one <group>...</group> block of a master_diaglist_* file, in file order, as DiagEntry(alias: str, source: str, args: tuple[str, ...] = ()). Tags match by name, and attributes on the opening tag are ignored. // starts a comment that runs to the end of the line. Nested groups are flattened into the selected group. Flags on a <runargs ...> line inside the group apply to each test line up to </runargs>, and come first in that test’s args. On a test line, the source is the first token after the alias that does not start with - and contains a .; the other tokens follow as args, in file order. A missing group or closing tag raises ValueError.
For group ariane_tile1_simple of OpenPiton’s master_diaglist_princeton, the first entry is:
DiagEntry(alias="ariane-hello-world", source="hello_world.c",
args=("-x_tiles=1", "-y_tiles=1", "-ariane", "-rtl_timeout", "1000000"))