Skip to content

t27b verilog: pin attributes on ports -- a board top carries its own pinout (Closes #10199) - #10209

Merged
gHashTag merged 5 commits into
masterfrom
claude/t27b-pin-attrs
Oct 18, 2026
Merged

gHashTag merged 5 commits into
masterfrom
claude/t27b-pin-attrs

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #10199. Refs #10024, #10170 (option A, step 2: the DDR3 head-bandwidth top).

A board top written in t27 can now carry its own pinout. t27b verilog writes each pin's placement and I/O standard as Verilog attributes on the port; yosys keeps them and nextpnr-xilinx reads them. No constraint file is written by hand. The parser does not change. Everything hand-written is .t27; the Rust under gen/ is regenerated by t27c gen-rust.

  • PIN ATTRIBUTE. A module-level const whose value is a string literal, named <port>_<KEY> with KEY one of LOC, IOSTANDARD, SLEW, IN_TERM, is written as (* KEY = "value" *) before that port.
    • It applies to every kind of port: the implicit clk/rst_n/en, an unbound on_clock parameter, an input, an inout, and an output (reg or wire).
    • Attributes go in the fixed order LOC, IOSTANDARD, SLEW, IN_TERM.
    • The naming rule is decided in verilog_plan.t27 (pin_key, is_pin_name, pin_kind, declares_pin). The writing is in verilog_emit.t27 (is_str_const, pin_decl, put_pins, is_port, pin_named).
  • Refusal. A pin attribute that names no port of the module is refused by name ("pin attribute for no port of the module z_LOC"). Otherwise a misspelt pin would leave its port to the placer without a word.
  • New conformance spec specs/tri/t27b/conformance/verilog_pin_attrs.t27. It puts pins on the implicit clk, an on_clock parameter (btn) and a pub var (led).

Evidence (Railway lab, x86_64, branch at 25b9ead plus the regenerated files)

Test reports. Each has 0 vacuous passes:

spec result
verilog_plan.t27 18/18
verilog_emit.t27 10/10
verilog_pin_attrs.t27 3/3

New tests:

  • a_pin_attribute_is_named_by_its_port_and_key (plan, 11 asserts)
  • a_pin_attribute_rides_on_the_port_it_names (emit). It checks the exact port text for an input and an output, the refusal for a pin that names no port, a non-string literal, and an empty name.

gen-rust. Both files are deterministic: two runs are byte-identical. t27b builds with them.

t27b verilog on the conformance spec writes, for example:

(* LOC = "R4" *) (* IOSTANDARD = "LVCMOS33" *) input  wire clk,

Yosys (read_verilog; write_json): the clk, btn and led ports keep LOC, IOSTANDARD and (on led) SLEW.

Negative control. The conformance spec with btn_LOC renamed to btm_LOC exits 2 with "unsupported construct pin attribute for no port of the module btm_LOC". The line number in that message is 0: the glue gives a module-level const no source line. The name is what identifies it.

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

mutation result
length check of declares_pin removed FAIL plan
_ separator check removed FAIL plan
empty port name accepted (ca + s + 2 to + 1) FAIL plan
refusal of a pin for no port removed FAIL emit
keys written in reverse order FAIL emit
string kind not required FAIL emit
port name length not compared FAIL emit
outputs carry no pins FAIL emit

"Separator check removed" survived at first. The test's no-separator name was 4 characters, so the length check rejected it first. A 5-character xyLOC now kills it.

Corpus diff. The master t27b and the branch t27b each ran verilog on all 2,220 specs under specs/, and stdout, stderr and exit codes were compared. 2,219 are identical. The one that differs is the new verilog_pin_attrs.t27 (exit 0 on both).

Seals. Resealed:

  • t27b_T27bVerilogPlan
  • t27b_T27bVerilogEmit
  • the new conformance_T27bConformanceVerilogPinAttrs

Ledger. docs/reports/t27b_expectations.json gains the row verilog_pin_attrs.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 ledger row is a claim that the arm64 t27b native ratchet in CI checks.
  • nextpnr-xilinx was not run. Its reading of these attributes comes from its source: top-port attributes are copied onto the IOB, LOC and IOSTANDARD are honoured, and SLEW and IN_TERM go through FASM. It is not checked here.
  • Nothing was synthesised, routed or measured on a board. This PR is "RTL emitter written" only. The DDR3 harness that uses these pins, and its synthesis, route and AX7203 receipt, follow under 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 5 commits October 18, 2026 11:04
…/_SLEW/_IN_TERM)

Refs #10170

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…re no pin or port

Refs #10199

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

Refs #10199

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

Refs #10199

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

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 04:30:48 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).

@gHashTag
gHashTag enabled auto-merge (squash) October 18, 2026 04:31
@gHashTag
gHashTag merged commit d9e0c6c into master Oct 18, 2026
29 of 32 checks passed
gHashTag pushed a commit to dmitrii-f-t27/t27 that referenced this pull request Oct 18, 2026
… master (Closes gHashTag#8889)

Master gained pin attributes for t27b verilog while this PR was open
(gHashTag#10209, gHashTag#10170: a str const `<port>_LOC` / `_IOSTANDARD` / `_SLEW` /
`_IN_TERM` becomes `(* KEY = "value" *)` on that port; tested by
specs/tri/t27b/conformance/verilog_pin_attrs.t27). That is the same feature
as this PR's `<port>_PIN` / `_IOSTANDARD` / `_SLEW` declarations, with the
same function names (pin_decl, put_pins, pin_named) in verilog_emit.t27, so
the two cannot both stay. Per the DRY rule the master mechanism is kept as
the one implementation and this PR's copy is dropped:

- specs/tri/t27b/verilog_plan.t27, verilog_emit.t27, their gen/rust files
  and their two seals: master's version, byte for byte.
- specs/trinet/eth_top_ax7203.t27: the 22 `<port>_PIN` consts become
  `<port>_LOC` (same pin values, same IOSTANDARD and SLEW); comments name
  gHashTag#10170. `t27b verilog` writes 22 ports with LOC / IOSTANDARD / SLEW
  attributes, 13 instances, 3 t27_period_ps attributes.
- specs/physics/xc7_primitives.t27 (IBUFDS, PLLE2_ADV, ODDR, BSCANE2 DRCK):
  unchanged by master, merged as is.
- docs/reports/t27b_expectations.json: master's rows plus this PR's
  eth_top_ax7203 row, in path order.
- .trinity/seals/trinet_TrinetEthTop.json: saved again (spec changed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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: pin attributes on ports (<port>_LOC, _IOSTANDARD, _SLEW, _IN_TERM)

1 participant