From fb7d9b4f646361acbe5f76f9fce7ffc7ecadec0b Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Sun, 18 Oct 2026 00:39:11 +0700 Subject: [PATCH 1/3] feat(t27c): gen-json -- print a spec's IGLA board event as one JSON object (Closes #10050) t27c gen-json reuses the gen-js value layer (const_value through the JS Target) and arranges the values into the board's event {job, stage, msg, progress, metrics}, the metrics keys taken from the spec's KEY_LENS/KEY_CELLS/KEY_STATUS/KEY_PCT and the 27 cells zipped from CELL_STATUS and CELL_PCT. Hand-written Rust: +30 lines, all in bootstrap/src/main.rs (already on the owner's exception list; a new file would need a protected list change). Offset named by the owner: docs/reports/data/W564-harness.sh (-26) and tools/jtag/read_user1.py (-20, already ported as specs/port/tools/jtag/read_user1.t27); the devhome baseline drops the deleted harness's line. Co-Authored-By: Claude Opus 5.5 --- bootstrap/src/main.rs | 30 ++++++++++++++++++++++++++++++ docs/reports/data/W564-harness.sh | 26 -------------------------- tools/devhome_baseline.txt | 1 - tools/jtag/read_user1.py | 20 -------------------- 4 files changed, 30 insertions(+), 47 deletions(-) delete mode 100755 docs/reports/data/W564-harness.sh delete mode 100644 tools/jtag/read_user1.py diff --git a/bootstrap/src/main.rs b/bootstrap/src/main.rs index b395b3fedd..bb186f759d 100644 --- a/bootstrap/src/main.rs +++ b/bootstrap/src/main.rs @@ -1293,6 +1293,9 @@ enum Commands { /// Input file path input: String, }, + /// Print the IGLA board event a .t27 spec states, as one JSON object + #[command(name = "gen-json")] + GenJson { input: String }, /// Compute deterministic test_vector_hash from conformance JSON Conformance { @@ -5637,6 +5640,31 @@ fn run_gen_python(input_path: &str) -> anyhow::Result<()> { } } +/// `gen-json` (#10050): the IGLA board event a spec states, as one JSON object. Every value comes +/// through the gen-js layer, which spells it as JSON does; this only arranges them, cells zipped. +fn run_gen_json(input_path: &str) -> anyhow::Result<()> { + let (ast, _) = ast_for_codegen(input_path)?; + let scope = codegen_js::Bound::in_spec(&ast); + let v = |name: &str| -> anyhow::Result { + let found = ast.children.iter().find(|n| n.kind == compiler::NodeKind::ConstDecl && n.name == name); + let node = found.ok_or_else(|| anyhow::anyhow!("gen-json: the spec declares no const {name}"))?; + codegen_js::const_value(&codegen_js::JS, node, &scope).map_err(anyhow::Error::msg) + }; + let items = |name: &str| -> anyhow::Result> { + let s = v(name)?; + Ok(s.trim_matches(|c| c == '[' || c == ']').split(", ").map(String::from).collect()) + }; + let (status, pct) = (items("CELL_STATUS")?, items("CELL_PCT")?); + anyhow::ensure!(status.len() == pct.len(), "gen-json: {} statuses, {} percents", status.len(), pct.len()); + let (ks, kp) = (v("KEY_STATUS")?, v("KEY_PCT")?); + let cells: Vec<_> = status.iter().zip(&pct).map(|(s, p)| format!("{{{ks}:{s},{kp}:{p}}}")).collect(); + let lens = items("LENS_PCT")?.join(","); + let metrics = format!("{{{}:[{lens}],{}:[{}]}}", v("KEY_LENS")?, v("KEY_CELLS")?, cells.join(",")); + let (job, stage, msg, progress) = (v("JOB")?, v("STAGE")?, v("MSG")?, v("PROGRESS")?); + println!("{{\"job\":{job},\"stage\":{stage},\"msg\":{msg},\"progress\":{progress},\"metrics\":{metrics}}}"); + Ok(()) +} + fn sha256_hex(data: &[u8]) -> String { sha256::hash_hex(data).iter().map(|&c| c as char).collect() } @@ -11968,6 +11996,7 @@ async fn main() -> anyhow::Result<()> { Commands::GenJs { input } => run_gen_js(&input)?, Commands::GenTs { input } => run_gen_ts(&input)?, Commands::GenPython { input } => run_gen_python(&input)?, + Commands::GenJson { input } => run_gen_json(&input)?, Commands::Conformance { input } => run_conformance(&input)?, Commands::Path { input, synth } => { service::run_path(&std::env::current_dir()?, &input, synth)? @@ -12405,6 +12434,7 @@ fn main() -> anyhow::Result<()> { Commands::GenJs { input } => run_gen_js(&input)?, Commands::GenTs { input } => run_gen_ts(&input)?, Commands::GenPython { input } => run_gen_python(&input)?, + Commands::GenJson { input } => run_gen_json(&input)?, Commands::Conformance { input } => run_conformance(&input)?, Commands::Path { input, synth } => { service::run_path(&std::env::current_dir()?, &input, synth)? diff --git a/docs/reports/data/W564-harness.sh b/docs/reports/data/W564-harness.sh deleted file mode 100755 index 3f43b2e645..0000000000 --- a/docs/reports/data/W564-harness.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/zsh -REPO=/Users/playom/t27/.claude/worktrees/igla-fpga-improvements-3f5e1a -OUT=/tmp/w560/results8.tsv -: > "$OUT" -n=0 -while read -r f; do - n=$((n+1)) - base=$(basename "$f" .t27) - zf="/tmp/w560/r2_${base}_$n.zig" - if ! "$REPO/target/release/t27c" gen "$f" > "$zf" 2>/dev/null || [ ! -s "$zf" ]; then - printf '%s\tGEN_FAIL\t0\n' "$f" >> "$OUT"; continue - fi - log=$(cd /tmp/w560 && zig test "$zf" 2>&1) - # A compile error is authoritative: zig prints "error:" with a file:line prefix. - if echo "$log" | grep -qE '^[^ ]+\.zig:[0-9]+:[0-9]+: error:'; then - printf '%s\tCOMPILE_FAIL\t0\n' "$f" >> "$OUT" - elif echo "$log" | grep -qE "All [0-9]+ tests passed"; then - p=$(echo "$log" | grep -oE "All [0-9]+ tests passed" | grep -oE "[0-9]+") - printf '%s\tALL_PASS\t%s\n' "$f" "$p" >> "$OUT" - elif echo "$log" | grep -qE "panic: assertion failed|terminated with signal ABRT|[0-9]+ passed; [0-9]+ failed"; then - p=$(echo "$log" | grep -cE "\.\.\.OK$") - printf '%s\tTEST_FAIL\t%s\n' "$f" "$p" >> "$OUT" - else - printf '%s\tUNKNOWN\t0\n' "$f" >> "$OUT" - fi -done < /tmp/bdd_ok.txt diff --git a/tools/devhome_baseline.txt b/tools/devhome_baseline.txt index 25f48a6b62..b45529d324 100644 --- a/tools/devhome_baseline.txt +++ b/tools/devhome_baseline.txt @@ -23,7 +23,6 @@ docs/NOW.md 1 docs/fpga/LOCAL-BITSTREAM-FLOW.md 3 docs/reports/OPENXC7-PNR-NOT-FUNCTION-PRESERVING.md 1 -docs/reports/data/W564-harness.sh 1 docs/reports/data/W568-harness.sh 1 docs/reports/data/W586-harness.sh 1 docs/reports/pdf/build_pdf.sh 1 diff --git a/tools/jtag/read_user1.py b/tools/jtag/read_user1.py deleted file mode 100644 index ef03c458f3..0000000000 --- a/tools/jtag/read_user1.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys; sys.path.insert(0,'tools/jtag') -from mpsse_jtag import Mpsse, CLK_BITS_OUT_NEG, CLK_TMS_OUT_NEG -def shift_ir(m, val): - m.tms([1,1,0,0]) - m.w(bytes([CLK_BITS_OUT_NEG, 4, val & 0x1F])) - m.w(bytes([CLK_TMS_OUT_NEG, 0, (((val>>5)&1) << 7) | 0x01])) - m.tms([1,0]) -def user1(idx=0, nbits=4): - m = Mpsse(idx) - try: - m.tms([1,1,1,1,1]); m.tms([0]) - shift_ir(m, 0x02) - m.tms([1,0,0]) - r = m.shift_dr_read(nbits); m.tms([1,1,0]) - return r[0] & ((1< Date: Sun, 18 Oct 2026 00:48:39 +0700 Subject: [PATCH 2/3] gen(json): own_model_board.json, the IGLA board event t27c gen-json prints (Closes #10050) Generated on the Railway lab by ./target/release/t27c gen-json specs/igla/own_model_board.t27 at 0209e0560 (sha256 6d85c82c...c6e2, 745 bytes; metrics object 622 bytes = METRICS_BYTES). Co-Authored-By: Claude Opus 5.5 --- gen/json/igla/own_model_board.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 gen/json/igla/own_model_board.json diff --git a/gen/json/igla/own_model_board.json b/gen/json/igla/own_model_board.json new file mode 100644 index 0000000000..4830795ae0 --- /dev/null +++ b/gen/json/igla/own_model_board.json @@ -0,0 +1 @@ +{"job":"own_model","stage":"own_model","msg":"1 published, 12 verified, 7 drafts, 7 gaps; 42%","progress":0.42,"metrics":{"lens_pct":[45,51,30],"cells":[{"status":4,"pct":60},{"status":4,"pct":70},{"status":4,"pct":80},{"status":3,"pct":80},{"status":3,"pct":60},{"status":3,"pct":10},{"status":3,"pct":50},{"status":0,"pct":0},{"status":0,"pct":0},{"status":4,"pct":100},{"status":4,"pct":100},{"status":4,"pct":20},{"status":4,"pct":80},{"status":4,"pct":65},{"status":4,"pct":60},{"status":3,"pct":40},{"status":0,"pct":0},{"status":0,"pct":0},{"status":4,"pct":70},{"status":4,"pct":15},{"status":5,"pct":60},{"status":4,"pct":40},{"status":3,"pct":35},{"status":0,"pct":0},{"status":0,"pct":0},{"status":0,"pct":0},{"status":3,"pct":50}]}} From 9243cbf01f61c49f3f9380bcd1f69eb8a13e9f67 Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Sun, 18 Oct 2026 11:45:21 +0700 Subject: [PATCH 3/3] gen(json): drop the committed board event; t27c gen-json prints it at post time (Refs #10050) The committed gen/json/igla/own_model_board.json went stale the moment master's map moved (622 bytes / 42% committed, master now states its own METRICS_BYTES and percentage), and every REVIEWED flip would move it again. It was a second home for what own_model_board.t27 already states, and the L2 rule refused it as a copy in a backend directory it does not know. The event is produced when it is posted, by t27c gen-json specs/igla/own_model_board.t27, and is never committed. Co-Authored-By: Claude Opus 5.5 --- gen/json/igla/own_model_board.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 gen/json/igla/own_model_board.json diff --git a/gen/json/igla/own_model_board.json b/gen/json/igla/own_model_board.json deleted file mode 100644 index 4830795ae0..0000000000 --- a/gen/json/igla/own_model_board.json +++ /dev/null @@ -1 +0,0 @@ -{"job":"own_model","stage":"own_model","msg":"1 published, 12 verified, 7 drafts, 7 gaps; 42%","progress":0.42,"metrics":{"lens_pct":[45,51,30],"cells":[{"status":4,"pct":60},{"status":4,"pct":70},{"status":4,"pct":80},{"status":3,"pct":80},{"status":3,"pct":60},{"status":3,"pct":10},{"status":3,"pct":50},{"status":0,"pct":0},{"status":0,"pct":0},{"status":4,"pct":100},{"status":4,"pct":100},{"status":4,"pct":20},{"status":4,"pct":80},{"status":4,"pct":65},{"status":4,"pct":60},{"status":3,"pct":40},{"status":0,"pct":0},{"status":0,"pct":0},{"status":4,"pct":70},{"status":4,"pct":15},{"status":5,"pct":60},{"status":4,"pct":40},{"status":3,"pct":35},{"status":0,"pct":0},{"status":0,"pct":0},{"status":0,"pct":0},{"status":3,"pct":50}]}}