Skip to content

fix: a handshake's return wires are the ones laid backwards - #82

Merged
endrix merged 1 commit into
mainfrom
feat/return-wires-lay-out-backwards
Oct 17, 2026
Merged

endrix merged 1 commit into
mainfrom
feat/return-wires-lay-out-backwards

Conversation

@endrix

@endrix endrix commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Why

A handshake answers backwards: ready leaves an instance on the west, beside the valid it answers, and enters the queue on the east. ELK sees a cycle for every channel and has to lay one of its wires against the flow. Its greedy cycle breaker counts wires, and a queue drives five (data, valid, size, ready, space) while it takes three, so every queue became a source and every actor a sink. Core.vhd of the chips workflow, ten queues and six actors, came out as a column of queues beside a column of actors.

What

WorkflowElkLayoutEngine now tells ELK which wires go with the flow. In a diagram that has a wire leaving a west port or entering an east port, every other wire gets elk.layered.priority.direction 10 and those wires 0, so the return wires are the ones reversed. A real feedback loop still reverses a data wire, as it must.

Measured standalone on the graphs the engine hands to ELK:

graph before after
Core.vhd, 30 nodes, 94 edges 2 layers, 20 data wires backwards 8 layers, 12 backwards (the CPU's feedback)
Load_ld_ld_config.vhd, 175 nodes, 189 edges 21 layers, 16 data wires backwards 20 layers, 1 backwards

Priority 2 and below changes nothing on Core.vhd; 5 and up gives the eight layers.

A diagram without return wires gets no priority at all, so wfpy and streamblocks layouts are byte for byte what they were. The new test pins both: a producer → queue → consumer handshake chain comes out in that order, and a plain graph hands ELK no priority.

Checks

  • diagram-server: 72 files, 356 tests pass
  • tsc --noEmit clean

https://claude.ai/code/session_01UtmwstZRcWJeg3C69s1TnS

A handshake answers backwards: `ready` leaves an instance on the west,
beside the `valid` it answers, and enters the queue on the east. ELK sees
a cycle for every channel and has to lay one of its wires against the
flow. Its greedy cycle breaker counts wires, and a queue drives five
(data, valid, size, ready, space) while it takes three, so every queue
became a source and every actor a sink: a ten-queue, six-actor netlist
came out as a column of queues beside a column of actors.

The engine now tells ELK which wires go with the flow. In a diagram that
has a wire leaving a west port or entering an east port, every other wire
gets `elk.layered.priority.direction` 10 and those wires 0, so the return
wires are the ones reversed; a real feedback loop still reverses a data
wire, as it must. That netlist now lays out in eight layers, memory
interface, decoder, cpu and multiplier in order with the queues between
them, and a 175-node netlist goes from 16 data wires laid backwards to
one. A diagram without return wires gets no priority at all, so its
layout is exactly what it was.

Claude-Session: https://claude.ai/code/session_01UtmwstZRcWJeg3C69s1TnS
@endrix
endrix merged commit 64b826e into main Oct 17, 2026
1 check passed
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