Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .trinity/seals/conformance_T27bConformanceVerilogSigned.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"built_by": "t27c-bootstrap@0.5.2+24a3abcad",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:315ca2c7706562f2d374a8d1a7a87c6b75f5e24b0a04532fa73b65894f02a406",
"gen_hash_rust": "sha256:e9c5d6d65d4a00f9ab078e6d628ebadefc21599a2ccf84e210f690b727c42c61",
"gen_hash_verilog": "sha256:c4769bdbed2a156cb77ee3d0d1fb6b23b7028fe5e14fa72545a8b19be466bdcf",
"gen_hash_zig": "sha256:4968f7373ab4754a177577747b02bd5b8fcfd4c16b9897809eca53154e288f7d",
"module": "T27bConformanceVerilogSigned",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T11:41:25Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:c58851a4a52bc2af42e4971ae7054689da71248dcf240e4846e6699e9887c0a6",
"spec_path": "specs/tri/t27b/conformance/verilog_signed.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 8,
"total": 8,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"built_by": "t27c-bootstrap@0.5.2+24a3abcad",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:76d7a7fd2227143996e211c370642cbbe3a2ef26ff61cba76929e4e1e438fd22",
"gen_hash_rust": "sha256:918f351234965ef7769edbe5049061b6bd443bce5ad13e0e9fcf42da7b8bd00b",
"gen_hash_verilog": "sha256:7d831e3247fb537cf358aa42531210ff52bf43c40e79afac8da425648f82448e",
"gen_hash_zig": "sha256:58f51ac431b8aaa72cab56ab98ab2358e127a26deabb44b0dc9b34c3a2209d0b",
"module": "T27bConformanceVerilogSignedClock",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T11:41:29Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:f8864c69304e7bc5f0be8a44a64749b3cda45a077cd20a272f7d2122ac0c4e55",
"spec_path": "specs/tri/t27b/conformance/verilog_signed_clock.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 2,
"total": 2,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
6 changes: 3 additions & 3 deletions .trinity/seals/t27b_T27bAstShape.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"built_by": "t27c-bootstrap@0.5.2+b6f775178",
"built_by": "t27c-bootstrap@0.5.2+24a3abcad",
"closure": [
{
"spec": "specs/tri/t27b/ast_scan.t27",
"spec_hash": "sha256:7e38ade9f1dc1c8f06a3c48063f060407b2d85d776aa8695dd6ef42b16d88a17"
},
{
"spec": "specs/tri/t27b/verilog_plan.t27",
"spec_hash": "sha256:c71ad7c23e4e17dc1289fad6c6e11b118d85bcff6002d5165263774200ea6bb0"
"spec_hash": "sha256:bb9714fdff9fdb959aa55a059bc2de6995a996049be3adafa0b7f1d91add5d13"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
Expand All @@ -18,7 +18,7 @@
"module": "T27bAstShape",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T06:03:08Z",
"sealed_at": "2026-10-20T11:41:34Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:16a9ea7c24f3552cb386c4e0dea10e1d806b641faa94a884c812a7d7ba66dd93",
"spec_path": "specs/tri/t27b/ast_shape.t27",
Expand Down
6 changes: 3 additions & 3 deletions .trinity/seals/t27b_T27bEmitKit.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"built_by": "t27c-bootstrap@0.5.2+b6f775178",
"built_by": "t27c-bootstrap@0.5.2+24a3abcad",
"closure": [
{
"spec": "specs/tri/t27b/verilog_plan.t27",
"spec_hash": "sha256:c71ad7c23e4e17dc1289fad6c6e11b118d85bcff6002d5165263774200ea6bb0"
"spec_hash": "sha256:bb9714fdff9fdb959aa55a059bc2de6995a996049be3adafa0b7f1d91add5d13"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
Expand All @@ -14,7 +14,7 @@
"module": "T27bEmitKit",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T06:03:46Z",
"sealed_at": "2026-10-20T11:41:38Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:8c7eea479142c7855d069e2cce5c0bbd03ffb1dccb861c5db334fe459db410d1",
"spec_path": "specs/tri/t27b/emit_kit.t27",
Expand Down
6 changes: 3 additions & 3 deletions .trinity/seals/t27b_T27bTsPlan.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"built_by": "t27c-bootstrap@0.5.2+b6f775178",
"built_by": "t27c-bootstrap@0.5.2+24a3abcad",
"closure": [
{
"spec": "specs/tri/t27b/verilog_plan.t27",
"spec_hash": "sha256:c71ad7c23e4e17dc1289fad6c6e11b118d85bcff6002d5165263774200ea6bb0"
"spec_hash": "sha256:bb9714fdff9fdb959aa55a059bc2de6995a996049be3adafa0b7f1d91add5d13"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
Expand All @@ -14,7 +14,7 @@
"module": "T27bTsPlan",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T06:04:23Z",
"sealed_at": "2026-10-20T11:41:43Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:d046e9702ec1a0a9db5b9d8666e0bc8f7f38361f1bc320e5d9420931f7887e46",
"spec_path": "specs/tri/t27b/ts_plan.t27",
Expand Down
16 changes: 8 additions & 8 deletions .trinity/seals/t27b_T27bVerilogEmit.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"built_by": "t27c-bootstrap@0.5.2+b6f775178",
"built_by": "t27c-bootstrap@0.5.2+24a3abcad",
"closure": [
{
"spec": "specs/tri/t27b/emit_kit; // byte writers, to_front, line_near, resolve and symbols, test trees.t27",
Expand All @@ -11,20 +11,20 @@
},
{
"spec": "specs/tri/t27b/verilog_plan.t27",
"spec_hash": "sha256:c71ad7c23e4e17dc1289fad6c6e11b118d85bcff6002d5165263774200ea6bb0"
"spec_hash": "sha256:bb9714fdff9fdb959aa55a059bc2de6995a996049be3adafa0b7f1d91add5d13"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:281b93e4c401f4885a2d0d6bc5ee2cde92cdbbe61ccc7f66e02b870a69ff1e4d",
"gen_hash_rust": "sha256:49081e7dffcef5342fc40c42c2760db4a29e86a6b88badcccd5dad66fdfba811",
"gen_hash_verilog": "sha256:1a385b65b99093e2addc4adf6f382d110186574b7ad1fcf83a0c41e7e13d304e",
"gen_hash_zig": "sha256:404bcae3892f3be78ba2755b203d92d0b582de42653dc9bec5d90399c763704d",
"gen_hash_c": "sha256:2957236d26b9a045dac12fb47ba567def21361ddc80ed6ed28e501491c6f3629",
"gen_hash_rust": "sha256:d7958fd980cc17f64aa2655a8d18c3ca568231b1b0bc881769b0317b7fc7f613",
"gen_hash_verilog": "sha256:facc1441bdb2328a72783966316870b542b5d2485e335cd3671602f749e880fd",
"gen_hash_zig": "sha256:2ee7814f3d5e270333af06489c3ddec444eb9382f90bd87f7b5be2e0e9806616",
"module": "T27bVerilogEmit",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T06:04:33Z",
"sealed_at": "2026-10-20T11:41:20Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:c34cd680a2f832cf513fb55a3b19956d16649604e605b1f01eaa3cf4294380df",
"spec_hash": "sha256:0951aeb6c8c46d91c89753faa74e8417c76051ed21d1f477a38e74e5f0651c87",
"spec_path": "specs/tri/t27b/verilog_emit.t27",
"tests": {
"failed": 0,
Expand Down
18 changes: 9 additions & 9 deletions .trinity/seals/t27b_T27bVerilogPlan.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
{
"built_by": "t27c-bootstrap@0.5.2+b6f775178",
"built_by": "t27c-bootstrap@0.5.2+24a3abcad",
"closure": [
{
"spec": "specs/tri/t27b/ast_walk.t27",
"spec_hash": "sha256:6653bee4e36f576c6b04d29b537ad52481c959e98b922257f48f3c0d4cf809e3"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:0b1cab301d63a4af4cfee93e69fb641b3ce7edd54d9079f62f01621b531787e5",
"gen_hash_rust": "sha256:e4860aa2da6eb2159bc505ac625c4880fba5fdb25ffe8953f2280c23be67d135",
"gen_hash_verilog": "sha256:71f948e58983e4e5390acbef7144e44371a76bd7b9cd55294df1d99865d92e7a",
"gen_hash_zig": "sha256:c59ac64c3064eaf401315d43ece71253b0917172f8337efbf01fd59a4f6ddacf",
"gen_hash_c": "sha256:41c392b9549baf681eb79f9a9f1008abf85df63a6ff07c2b9d7578d2e6877836",
"gen_hash_rust": "sha256:1d1fe59432160f2a2e56dac6f002257723ed2e6a0c808b751e9e8819a4dd1196",
"gen_hash_verilog": "sha256:161b30d277e176db7484dd970d203e1b7e6bfb423e6410a4ba7d9e86b64bf68e",
"gen_hash_zig": "sha256:159166ea2be21089529b296220a631fe52676fa959d3beaedb8c30c724609624",
"module": "T27bVerilogPlan",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T06:04:36Z",
"sealed_at": "2026-10-20T11:41:14Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:c71ad7c23e4e17dc1289fad6c6e11b118d85bcff6002d5165263774200ea6bb0",
"spec_hash": "sha256:bb9714fdff9fdb959aa55a059bc2de6995a996049be3adafa0b7f1d91add5d13",
"spec_path": "specs/tri/t27b/verilog_plan.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 18,
"total": 18,
"passed": 20,
"total": 20,
"vacuous": 0
},
"toolchain": {
Expand Down
14 changes: 12 additions & 2 deletions cli/t27b/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,18 @@ refused by name, exit 2. Every decision is in `specs/tri/t27b/verilog_plan.t27`:
* how a spec declares an extern module, an instance and a net;
* the port derivation;
* the use closure;
* exact widths;
* the static loop bound.
* exact widths, unsigned and signed;
* the static loop bound;
* constant tables (ROMs) and division by a constant (a multiply-shift, never a divider).

A spec with no `fn on_clock`, var, net, instance or input is a library of decisions, and
`t27b verilog <file> [--top <fn>]` writes one combinational module per `pub fn` whose parameters and
result are integers or bools (inputs = the parameters, output `t27_y`), or only the module of `<fn>`.
`i2`..`i64` lower as `signed`; `@as(T, x)`, `x as T`, `>>` (`>>>` when signed), `-x`, `T[i]` on a
module-level `const T : [N]ty = [..]` and `x / k`, `x % k` for a constant `k` lower as well
(`specs/tri/t27b/conformance/verilog_signed*.t27`; gHashTag/t27#11326). What still refuses: an
`f64`/string parameter, a struct, a `while` with no static bound, a table read by a signed index, a
divisor above 2^62, `@intCast` outside `@as`, and a general `x / y` is Verilog's divider.

The writer is `specs/tri/t27b/verilog_emit.t27`. The fixtures are
`specs/tri/t27b/conformance/verilog_*.t27` (#8796).
Expand Down
6 changes: 3 additions & 3 deletions cli/t27b/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7356,16 +7356,16 @@ const _: () = assert!(NodeKind::StmtExpr as u8 == aw::K_STMT_EXPR && NodeKind::E
#[path = "../../../gen/rust/tri/t27b/verilog_emit.rs"] #[allow(dead_code, unused_parens, unused_variables, while_true)] mod ve; // t27c gen-rust of specs/tri/t27b/verilog_emit.t27: `t27b verilog` (#8796)
#[path = "../../../gen/rust/tri/t27b/ts_emit.rs"] #[allow(dead_code, unused_parens, unused_variables, while_true)] mod tse; // specs/tri/t27b/ts_emit.t27: `t27b ts` (#9994)
/// `t27b verilog` (`t27b ts` when `ts`): `flat`'s bytes and per node four u32 (flags 1 var, 2 pub; line; its params' span in `p`).
pub fn verilog(ast: &Node, ts: bool) -> Result<String, String> {
pub fn verilog(ast: &Node, ts: bool, top: &str) -> Result<String, String> {
fn meta(n: &Node, m: &mut Vec<u8>, p: &mut Vec<u8>) {
let lo = p.len() as u32; n.params.iter().for_each(|(a, b)| p.extend(format!("{a}:{b}\n").bytes()));
for v in [n.extra_mutable as u32 | (n.extra_pub as u32) << 1, n.line, lo, p.len() as u32] { m.extend(v.to_le_bytes()) }
n.children.iter().for_each(|c| meta(c, m, p));
}
let ((a, t), mut m, mut p) = (flat([ast]), Vec::new(), Vec::new());
meta(ast, &mut m, &mut p);
let (mut w, mut out) = (vec![0u8; a.len() / aw::REC * 2 + 70], vec![0u8; 4 * (a.len() + t.len()) + (1 << 20)]);
let n = (if ts { tse::emit } else { ve::emit })(&a, &t, &m, &p, &mut w, &mut out);
let (mut w, mut out) = (vec![0u8; a.len() / aw::REC * 3 + 80], vec![0u8; 4 * (a.len() + t.len()) + (1 << 20)]);
let n = if ts { tse::emit(&a, &t, &m, &p, &mut w, &mut out) } else { ve::emit(&a, &t, &m, &p, &mut w, &mut out, top.as_bytes()) };
let s = String::from_utf8_lossy(&out[..n.unsigned_abs() as usize]).into_owned();
(n >= 0).then(|| s.clone()).ok_or(s)
}
Expand Down
9 changes: 4 additions & 5 deletions cli/t27b/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ struct Opts {
mode: OverflowMode,
time: bool,
quiet: bool,
check: bool,
list: bool,
check: bool, list: bool, top: String,
timeout_ms: u64,
jobs: usize,
json: Option<String>,
Expand Down Expand Up @@ -94,8 +93,7 @@ fn parse_args() -> Result<Opts, String> {
mode: OverflowMode::Trap,
time: false,
quiet: false,
check: false,
list: false,
check: false, list: false, top: String::new(),
timeout_ms: 10_000,
jobs: std::thread::available_parallelism().map_or(4, |n| n.get()),
json: None,
Expand All @@ -121,6 +119,7 @@ fn parse_args() -> Result<Opts, String> {
"--quiet" | "-q" => o.quiet = true,
"--check" => o.check = true,
"--list" => o.list = true,
"--top" => o.top = args.next().ok_or("--top needs a fn name")?,
"--blockers" => o.blockers = true,
"--elf" => o.elf = true,
"--macho" => o.elf = false,
Expand Down Expand Up @@ -235,7 +234,7 @@ fn compile_front(input: &str, o: &Opts) -> Result<(Program, Phases), u8> {
return Err(EXIT_FRONTEND);
}
if o.cmd == "verilog" || o.cmd == "ts" {
return Err(lower::verilog(&parsed.ast, o.cmd == "ts").map_or_else(|e| { errln!("{}", e); EXIT_UNSUPPORTED }, |v| { out(&v); 0 }));
return Err(lower::verilog(&parsed.ast, o.cmd == "ts", &o.top).map_or_else(|e| { errln!("{}", e); EXIT_UNSUPPORTED }, |v| { out(&v); 0 }));
}
if o.blockers {
// Every unsupported construct, not just the first; a file with none
Expand Down
2 changes: 1 addition & 1 deletion gen/rust/tri/t27b/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// This backend emits declarations only. The spec's checks live in
// the Zig and Verilog outputs; do not read this file as verified.

pub const T27B_USAGE: &'static str = "usage:\n t27b test <file.t27> [--overflow trap|wrap] [--time] [--quiet] [--check] [--blockers]\n t27b build <file.t27> -o <out.o> [--elf | --macho] [--overflow trap|wrap] [--time]\n t27b watch <file.t27> -o <out.o> [--elf | --macho] [--overflow trap|wrap] [--then '<cmd>']\n t27b asm <file.t27> [--overflow trap|wrap]\n t27b verilog <file.t27> (the module, and its test bench under `ifdef T27B_TESTBENCH)\n t27b ts <file.t27> (consts, scalar fns and tests as TypeScript; specs/tri/t27b/ts_emit.t27)\n t27b corpus <dir> [--timeout-ms N] [--jobs N] [--overflow trap|wrap] [--list]\n [--json <path>] [--runner '<cmd> [args]']\n [--blockers [--reference <t27c> [--reference-cache <file>]\n [--reference-timeout-ms N]]]\n\n --elf build: an ELF64 object for aarch64 Linux (specs/tri/t27b/elf.t27), the default on\n Linux; --macho: a Mach-O object for arm64 macOS, the default elsewhere\n --then watch: after every successful rebuild, run <cmd> with sh -c (never after a failed one)\n --json corpus: also write per-file results and totals to <path> as JSON\n (with --reference, the reference verdicts too)\n --runner corpus: start each per-file `t27b test` as `<cmd> [args] <t27b> test ...`,\n e.g. --runner 'qemu-aarch64 -L /usr/aarch64-linux-gnu' when the corpus\n itself runs under qemu-user without binfmt_misc\n --blockers test: report every unsupported construct, not just the first.\n corpus: per file, every construct t27b lacks; then the greedy\n order in which supporting them unlocks the most whole files.\n --reference corpus: also run the reference path (`<t27c> test-report`,\n t27c's Zig backend) on every file, and leave the files it fails\n out of the denominator. Where both sides ran a file's tests,\n compare them test by test: `reference_disagree` counts files\n where a test's verdict differs or only one side has it (#6441).\n `mismatch` (= `jit_interp_mismatch`) is t27b's JIT against\n t27b's own interpreter, not against the reference.";
pub const T27B_USAGE: &'static str = "usage:\n t27b test <file.t27> [--overflow trap|wrap] [--time] [--quiet] [--check] [--blockers]\n t27b build <file.t27> -o <out.o> [--elf | --macho] [--overflow trap|wrap] [--time]\n t27b watch <file.t27> -o <out.o> [--elf | --macho] [--overflow trap|wrap] [--then '<cmd>']\n t27b asm <file.t27> [--overflow trap|wrap]\n t27b verilog <file.t27> [--top <fn>] (the module, and its test bench under `ifdef T27B_TESTBENCH; a library of pure fns: a module per pub fn, or only <fn>)\n t27b ts <file.t27> (consts, scalar fns and tests as TypeScript; specs/tri/t27b/ts_emit.t27)\n t27b corpus <dir> [--timeout-ms N] [--jobs N] [--overflow trap|wrap] [--list]\n [--json <path>] [--runner '<cmd> [args]']\n [--blockers [--reference <t27c> [--reference-cache <file>]\n [--reference-timeout-ms N]]]\n\n --elf build: an ELF64 object for aarch64 Linux (specs/tri/t27b/elf.t27), the default on\n Linux; --macho: a Mach-O object for arm64 macOS, the default elsewhere\n --then watch: after every successful rebuild, run <cmd> with sh -c (never after a failed one)\n --json corpus: also write per-file results and totals to <path> as JSON\n (with --reference, the reference verdicts too)\n --runner corpus: start each per-file `t27b test` as `<cmd> [args] <t27b> test ...`,\n e.g. --runner 'qemu-aarch64 -L /usr/aarch64-linux-gnu' when the corpus\n itself runs under qemu-user without binfmt_misc\n --blockers test: report every unsupported construct, not just the first.\n corpus: per file, every construct t27b lacks; then the greedy\n order in which supporting them unlocks the most whole files.\n --reference corpus: also run the reference path (`<t27c> test-report`,\n t27c's Zig backend) on every file, and leave the files it fails\n out of the denominator. Where both sides ran a file's tests,\n compare them test by test: `reference_disagree` counts files\n where a test's verdict differs or only one side has it (#6441).\n `mismatch` (= `jit_interp_mismatch`) is t27b's JIT against\n t27b's own interpreter, not against the reference.";

pub fn usage_byte(i: usize) -> u8 {
return T27B_USAGE.as_bytes()[(i) as usize];
Expand Down
Loading
Loading