Skip to content

t27b verilog: inout ports and lane sets for ports wider than 64 bits (Closes #10187) - #10188

Merged
gHashTag merged 4 commits into
masterfrom
claude/laughing-albattani-f3084a
Oct 18, 2026
Merged

gHashTag merged 4 commits into
masterfrom
claude/laughing-albattani-f3084a

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #10187. Refs #10024, #10170 (option A, step 1).

The t27b Verilog emitter can now write the top around a LiteDRAM core. It handles the 256-bit native port and the bidirectional DDR3 data bus. The parser does not change, and MAX_WIDTH stays 64. Everything hand-written is .t27; the Rust under gen/ is regenerated by t27c gen-rust.

  • LANE SET. Extern parameters, or result fields, named base__0 .. base__N, all of one type, adjacent and numbered from 0, become ONE instance port .base({laneN, ..., lane0}). Lane 0 goes in the low bits. Each output lane keeps its own wire inst__base__N. A set has at most 64 lanes (MAX_LANES).
    • Decided in verilog_plan.t27 (lane_at, lane_index, is_lane_of).
    • Written in verilog_emit.t27 (put_instance, sibling).
  • INOUT. A pub const X : T = undefined; is an inout wire port (class C_INOUT). It may only be handed by name to an instance port of type T (port_arg). Any other read is refused in ex.
  • Pre-existing bug fixed in passing. Two fail calls in put_instance took a parameter's name from text when it lives in ptext. They now pass ptext.
  • New conformance spec specs/tri/t27b/conformance/verilog_wide_inout.t27. It models the shape of the LiteDRAM core: four 64-bit write lanes, four read lanes, a 32-bit inout dq, and DATA_WIDTH = 256.

Evidence (Railway lab, x86_64, branch at 194a926 plus the regenerated files)

Test reports. Each has 0 vacuous passes:

spec result
verilog_plan.t27 17/17
verilog_emit.t27 9/9
verilog_wide_inout.t27 3/3

New tests:

  • a_lane_set_is_named_by_its_base_and_numbered_from_zero (plan)
  • a_lane_set_is_one_port_and_an_inout_is_handed_through (emit, 13 asserts, including the refusals)
  • the inout case in hardware_only_consts_are_found_to_a_fixed_point

gen-rust.

  • A pristine master worktree reproduces both committed gen files byte for byte.
  • On the branch, both are deterministic.
  • t27b builds with them.

t27b verilog on the conformance spec. The output has the port inout wire [31:0] ddr3_dq and this instance:

.wdata({{beat + 64'd3}, {beat + 64'd2}, {beat + 64'd1}, beat}),
.rdata({core__rdata__3, core__rdata__2, core__rdata__1, core__rdata__0})

Yosys (read_verilog; proc; write_json):

  • Instance connection widths: dq 32, wdata 256, rdata 256, we 1, ready 1. DATA_WIDTH = 256.
  • Port ddr3_dq has direction inout, width 32.
  • rdata[63:0] is core__rdata__0 and rdata[255:192] is core__rdata__3.
  • wdata[63:0] is beat.

Negative controls. Each one edits the conformance spec. Each exits 2 with an exact refusal that names the identifier:

control refused at
lane gap wdata__7
lane of another type wdata__2
output-lane gap rdata__9
output lane of another type rdata__3
set without lane 0 wdata__1
inout read in an expression ddr3_dq, line 24
inout read on the clock line 38
inout handed to a u16 port "inout of another type than the port it is handed to"

Mutation controls. Each mutation is applied to the spec, then the test report is run. All 9 are killed:

mutation result
inout type check removed FAIL emit
inout read allowed FAIL emit
output lanes written low lane first FAIL emit
input lanes written low lane first FAIL emit
lane type check removed FAIL emit
leading-zero lane accepted FAIL plan
base length unchecked FAIL plan
inout without pub FAIL plan
lane cap lifted FAIL plan

"Base length unchecked" survived at first. The new assert !is_lane_of("rdatax__2", ...) kills it.

Corpus diff. The master t27b and the branch t27b each ran verilog on all 2,217 specs under specs/, and stdout, stderr and exit codes were compared. 2,214 are identical. The 3 that differ are all expected:

  • specs/tri/t27b/conformance/verilog_wide_inout.t27: the new spec.
  • specs/port/tools/jtag/read_user1.t27: pub const CLK_BITS_OUT_NEG: u8 = undefined; and its sibling were input ports and are now inout.
  • specs/port/tools/jtag/mpsse_jtag.t27: the refusal now says "inout" instead of "input" (exit 2 on both).

Both JTAG specs are host-side tool specs, not hardware targets. pub const ... = undefined was undocumented as a port form until now; the documented INPUT form is the non-pub const X : T = undefined;, and it is unchanged.

Seals. Resealed:

  • t27b_T27bVerilogPlan (17 tests)
  • t27b_T27bVerilogEmit
  • the new conformance_T27bConformanceVerilogWideInout

Ledger. docs/reports/t27b_expectations.json gains the row verilog_wide_inout.t27: pass.

Not verified here

  • Native t27b was not run on these specs. The lab is x86_64 and the t27b JIT runs only on arm64; the reference (t27c + zig) passes all 8 verilog specs there. The ledger row is a claim that the arm64 t27b native ratchet in CI checks.
  • No Icarus testbench. There is no behavioural model of the extern core, so lane order is checked structurally through Yosys, not in simulation.
  • Nothing was synthesised, routed or measured on a board. This PR is "RTL emitter written" only. The DDR3 harness, synthesis and route for xc7a200tfbg484, and the AX7203 receipt are step 2 of fpga(ax7203): DDR3 head-read bandwidth for own-model cell 26 -- blocked on inout and >64-bit ports #10170.

🤖 Generated with Claude Code

gHashTag and others added 4 commits October 18, 2026 10:29
…64 bits

Refs #10170

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #10170

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#10187)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 03:44:23 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=0f8c66b9ed0e != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

t27b verilog: inout ports and lane sets for ports wider than 64 bits (LiteDRAM native port)

1 participant