Skip to content

Pipeline the GF16 matmul (9.97 → 36.36 MHz, bit-exact) and make requests start themselves - #633

Merged
gHashTag merged 2 commits into
mainfrom
feat/pipelined-gf16
Aug 8, 2026
Merged

Pipeline the GF16 matmul (9.97 → 36.36 MHz, bit-exact) and make requests start themselves#633
gHashTag merged 2 commits into
mainfrom
feat/pipelined-gf16

Conversation

@gHashTag

@gHashTag gHashTag commented Aug 8, 2026

Copy link
Copy Markdown
Owner

The core has a publishable number again

Withdrawing the old claim left an honest figure and a problem: 9.97 MHz post-route with a single register stage. Comparable vendor cores reach 100 MHz+, and do it by pipelining — a core at 10 MHz cannot be sold or compared.

The module's own structure hands over the boundaries (four multiplies → two adds → final add), so gf16_dot4_p cuts there. Latency 3 cycles, one result per cycle, arithmetic untouched.

Measured post-route on an XC7A200T, nextpnr-xilinx, hard multipliers off:

Block Fmax Latency
gf16_dot4 combinational 18.83 MHz 0
gf16_dot4_p 3 stages 58.49 MHz 3 3.1×
gf16_matmul4x4_reg 1 stage 9.97 MHz 1
gf16_matmul4x4_p 3 stages 36.36 MHz 3 3.6×

Equivalence proven, not assumed — the whole point of the method this repo sells. tb_equiv.v compares the pipelined dot product against the original delayed by three cycles: 59,993 cycles, zero mismatches, including the format's zero, infinity-like, NaN-like and unity encodings.

Where the floor is, measured: the critical path runs from the second-stage register through the final gf16_add — one float add ≈ 17 ns. The clean cut inside it is between mantissa alignment and the add. Left undone deliberately: that is a rewrite of a 192-line float adder, and a subtly wrong adder is worse than a slow one. The equivalence harness is ready for whoever does it.

The harnesses keep the LFSR and XOR reduction outside the measured path — constants on the inputs let synthesis fold the matmul away, which is exactly how the phantom 323 MHz arose.

Requests start themselves

"Email me" is the step most people never take. An issue form asks the three things that matter, then a workflow acknowledges, clones, and runs what needs no human: elaboration, latch check, synthesis with cell counts, and a count of clocked blocks — so a combinational design is told plainly that no frequency can belong to it. Every command is visible in the comment.

It does not claim to do the whole job: the posted comment says outright that the reference model, per-stage vectors and board replay are still to come and cannot be automated.

Kept narrow on purpose: only a plain https://github.com/owner/repo URL is cloned, and it reaches the shell through the environment rather than interpolated into it, so an issue body cannot inject a command.

🤖 Generated with Claude Code

Dmitrii Vasilev and others added 2 commits August 8, 2026 19:25
Withdrawing the old frequency claim left the core with an honest number and a
problem: 9.97 MHz post-route with a single register stage. Every comparable
vendor core reaches 100 MHz or more, and does it by pipelining, so a core at
10 MHz cannot be sold or compared.

The module's own structure hands over the stage boundaries — four multiplies,
then two adds, then the final add — so gf16_dot4_p cuts there. Latency three
cycles, one result per cycle, and the arithmetic is untouched: the same gf16_mul
and gf16_add instances with registers between them.

Measured post-route on an XC7A200T with nextpnr-xilinx, hard multipliers off:

    gf16_dot4          combinational        18.83 MHz
    gf16_dot4_p        3 stages             58.49 MHz     3.1x
    gf16_matmul4x4_reg 1 register stage      9.97 MHz
    gf16_matmul4x4_p   3 stages             36.36 MHz     3.6x

Equivalence is proven rather than assumed, which is the whole point of the method
this repository sells: tb_equiv.v compares the pipelined dot product against the
original delayed by three cycles across 59,993 cycles of random and special-case
operands — zero mismatches, including the format's zero, infinity-like, NaN-like
and unity encodings.

Where the floor now is, measured rather than guessed: the critical path runs from
the second-stage register through the final gf16_add, so one float add is about
17 ns. The clean cut inside it is between the mantissa alignment and the add.
Left undone deliberately — that is a rewrite of a 192-line float adder, and a
subtly wrong adder is worse than a slow one. The equivalence harness is ready
for whoever does it.

The timing harnesses put the LFSR and the XOR reduction outside the measured
path. That matters for a specific reason: constants on the inputs let synthesis
fold the whole matmul away, which is exactly how the phantom 323 MHz arose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"Email me" is the step most people never take, and it puts the owner in the loop
before there is anything to be in the loop about. A request now runs on its own.

An issue form asks the three things that actually matter — where the RTL is, the
top module, and what "correct" means for it. The third field is the important one
and the form says why: the reference model is written from that description rather
than from the code, because a model derived from the RTL agrees with the RTL,
including where it is wrong.

A workflow then acknowledges, clones the design, and runs the checks that need no
human: elaboration, a latch check, generic synthesis with cell counts, and a
count of clocked blocks — the last so a combinational design is told plainly that
no frequency can belong to it. Results are posted into the issue with every
command visible, so the requester can re-run all of it.

What it does not do is claim to do the whole job. The comment it posts says
outright that the reference model, the per-stage vectors and the board replay are
still to come and cannot be automated. Overstating that would be the fastest way
to lose the only thing being sold.

Two things kept deliberately narrow: only a plain https://github.com/owner/repo
URL is cloned — anything else is left for a human rather than guessed at — and the
URL reaches the shell through the environment rather than being interpolated into
it, so an issue body cannot inject a command.

The service page now leads with this instead of a mailto, with the four steps and
their timings named, and the same page keeps the address for anyone who would
rather write.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag
gHashTag merged commit df6cb3e into main Aug 8, 2026
14 of 25 checks passed
@gHashTag
gHashTag deleted the feat/pipelined-gf16 branch August 8, 2026 12:30
github-actions Bot added a commit that referenced this pull request Aug 8, 2026
Pipeline the GF16 matmul (9.97 → 36.36 MHz, bit-exact) and make requests start themselves (#633)

* Pipeline the GF16 matmul: 9.97 MHz becomes 36.36 MHz, bit-exact

Withdrawing the old frequency claim left the core with an honest number and a
problem: 9.97 MHz post-route with a single register stage. Every comparable
vendor core reaches 100 MHz or more, and does it by pipelining, so a core at
10 MHz cannot be sold or compared.

The module's own structure hands over the stage boundaries — four multiplies,
then two adds, then the final add — so gf16_dot4_p cuts there. Latency three
cycles, one result per cycle, and the arithmetic is untouched: the same gf16_mul
and gf16_add instances with registers between them.

Measured post-route on an XC7A200T with nextpnr-xilinx, hard multipliers off:

    gf16_dot4          combinational        18.83 MHz
    gf16_dot4_p        3 stages             58.49 MHz     3.1x
    gf16_matmul4x4_reg 1 register stage      9.97 MHz
    gf16_matmul4x4_p   3 stages             36.36 MHz     3.6x

Equivalence is proven rather than assumed, which is the whole point of the method
this repository sells: tb_equiv.v compares the pipelined dot product against the
original delayed by three cycles across 59,993 cycles of random and special-case
operands — zero mismatches, including the format's zero, infinity-like, NaN-like
and unity encodings.

Where the floor now is, measured rather than guessed: the critical path runs from
the second-stage register through the final gf16_add, so one float add is about
17 ns. The clean cut inside it is between the mantissa alignment and the add.
Left undone deliberately — that is a rewrite of a 192-line float adder, and a
subtly wrong adder is worse than a slow one. The equivalence harness is ready
for whoever does it.

The timing harnesses put the LFSR and the XOR reduction outside the measured
path. That matters for a specific reason: constants on the inputs let synthesis
fold the whole matmul away, which is exactly how the phantom 323 MHz arose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* A request that starts itself, with no correspondence

"Email me" is the step most people never take, and it puts the owner in the loop
before there is anything to be in the loop about. A request now runs on its own.

An issue form asks the three things that actually matter — where the RTL is, the
top module, and what "correct" means for it. The third field is the important one
and the form says why: the reference model is written from that description rather
than from the code, because a model derived from the RTL agrees with the RTL,
including where it is wrong.

A workflow then acknowledges, clones the design, and runs the checks that need no
human: elaboration, a latch check, generic synthesis with cell counts, and a
count of clocked blocks — the last so a combinational design is told plainly that
no frequency can belong to it. Results are posted into the issue with every
command visible, so the requester can re-run all of it.

What it does not do is claim to do the whole job. The comment it posts says
outright that the reference model, the per-stage vectors and the board replay are
still to come and cannot be automated. Overstating that would be the fastest way
to lose the only thing being sold.

Two things kept deliberately narrow: only a plain https://github.com/owner/repo
URL is cloned — anything else is left for a human rather than guessed at — and the
URL reaches the shell through the environment rather than being interpolated into
it, so an issue body cannot inject a command.

The service page now leads with this instead of a mailto, with the four steps and
their timings named, and the same page keeps the address for anyone who would
rather write.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Dmitrii Vasilev <admin@t27.ai>
Co-authored-by: Claude Opus 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.

1 participant