Skip to main content

Routing

11. Routing​

region : paint(color [SRC>DST])

Configures the router on every PE in the region for the given color.

Give each PE one rule per color. Where two regions of a union overlap, the rule of the later region wins. A second paint() of the same color on the same region is ignored without a message: after t : paint(c [C>R]) and t : paint(c [L>C]), t routes C>R.

Direction codes​

CodeDirectionDescription
RRightEast (+X)
LLeftWest (−X)
UUp+Y (router south port)
DDown−Y (router north port)
CCenterPE compute element (onramp/offramp)

Multiple destinations can be combined: [C>RU] sends from the center to the right and up. On SDR a position accepts at most one source, so [CL>R] is rejected; use separate switch positions when different sources must take turns.

Common patterns​

(* Transmit: PE sends data rightward *)
t : paint(c [C>R])

(* Receive: data arrives from left into PE *)
t : paint(c [L>C])

(* Pass-through: data flows left to right *)
t : paint(c [L>R])

(* Broadcast: PE sends in two directions *)
t : paint(c [C>RU])

(* Sink: accept from the left and discard *)
t : paint(c [L>])

Boundary operators (|)​

The | operator suppresses a direction on the PEs at an edge of a rectangle:

r : paint(c [L|L>R]) (* don't accept from left on leftmost column *)
r : paint(c [L>R|R]) (* don't send right on rightmost column *)

A position has the form [NOENTER|SRC>DST|NOEXIT]. On the entry side, the directions to suppress come before the first | and the source follows it: [LD|L>R] turns off the input L on the left edge. An entry direction acts only where it is also the source, so [D|L>R] changes nothing. On the exit side, the directions to suppress follow the second |: [L>RU|RU] drops R on the right edge and U on the edge with the largest y.

Apply a | rule to one rect(), tile(), or one rep, hstackrep or vstackrep block that covers the whole grid, as the 9-point stencil does with beach. Paint applies the rule at the edges of each rectangle a region is built from, not at the outline of a union, hstack or vstack. It also gets every rectangle after the first wrong: those lose the suppressed directions on all their PEs. On hstack(tile() tile() tile()), [L|L>R] turns off the input of all three PEs, and Paint gives no message.

Color swap modifiers​

A swap modifier replaces > and makes the color take its input from its partner color (c ^ 1, see Color pairs) on the inputs it names:

ModifierInputs read from the partner
>none
Hleft and right (east/west)
Vup and down (north/south)
Xleft, right, up, down, and the core (onramp)

Only X swaps the core's input. The swap is one setting of the color on that router, shared by all its switch positions, so every position of a rule must use the same modifier. Paint does not check this: it takes the modifier of the first position and ignores the others without a message, so [C>R ; LXR] swaps nothing.

Inputs a rule does not swap still read the color's own wavelets, even where the color has no rule, and every color that reads a wavelet must take its input from the side it arrives on, or the fabric stalls. So a swap usually needs its partner to swap as well: a moat swaps both colors.

(* One socket r for sending right and receiving from the left *)
row : paint(rp [CXR|R]) (* rp carries what the core sends on r *)
row : paint(r [L|LXC]) (* r takes rp from the left, for the core *)
row : colorpair(r rp)

(* A moat that turns c0 back west on c0x *)
moat : paint(c0x [LXL]) (* c0 from the left goes back west as c0x *)
moat : paint(c0 [LXL]) (* so c0 does not also claim it *)
moat : colorpair(c0 c0x)

Color Swapping in the architecture notes draws both patterns.

Switch Positions (;) — Input Switch State Machine​

Sixteen of the 24 colors support dynamic input and output switching: colors 0 to 9, 12, 13, 16, 17, 20 and 21. Paint gives each rule that has positions one of these colors. Each switch can have up to 4 positions (states). Positions are separated by a mandatory ; in the paint routing rule. Whitespace, including a newline, does not separate positions. A trailing ; after the final position remains optional:

(* 2-position switch: inject then passthrough *)
r : paint(c [C>R ; L>R])

(* 3-position switch *)
r : paint(c [L>R; L>U; D>U; ring pop=all])

Modifiers (ring, pop=..., tip, fabadder) follow the last position, after an optional ;. So [L>R; L>U; D>U; ring pop=all] has three positions, and [C>R; tip] has one. Paint does not reject a fifth position: it writes past the four slots and changes the outputs of the earlier positions.

The first position is the initial state, unless another position is marked with *. The switch advances to the next position in response to:

  1. flip (local switch advance) — a Tungsten flip tx[] statement piggybacks a sideband bit on the last data word; when the CE transmits it, the local input switch advances.
  2. Control wavelets — a control wavelet whose command 0 is a switch advance moves the input switch of every router that receives it on that color. That includes the sending tile's own router, which receives it from its CE. A router passes command 0 on unchanged unless its rule pops it (see Modifiers below), so without a pop= one advance moves every switch along its path. Tungsten sends one with control(); the Control Wavelets section of the Tungsten reference gives the word's format.

A router keeps two switch states per color, one for its input and one for its output. The input switch moves as soon as the router receives the control wavelet; the output switch moves after the router sends it on. So the control wavelet leaves in the old direction.

A switch reset wavelet returns the switch to its first position.

The * suffix makes a position the starting one:

r : paint(c [L>R ; C>R*]) (* start in position C>R; a reset returns to L>R *)

Constraints:

  • Input select values may differ across positions.
  • With flip (local switch advance), the output enable mask must be the same in every position, and pop=adv and pop=advnop are not supported. A flipped send may carry data or a control wavelet whose command 0 is a NOP, nothing else. The flip moves only the input switch, so the input and output switches then stand in different positions.
  • The switch wraps to position 0 after the last position only with ring. Without ring, advancing does not cycle back to the first position.

Common patterns:

PatternPositionsUse case
[C>R ; L>R]Inject, then passthroughSerial drain with flip
[L>R ; C>R]Passthrough, then injectDeferred injection (via an advance control wavelet from upstream)
[C>D ; U>D]Inject down, then pass-throughVertical funnel
[C>D ; U>D ; pop=adv]Inject, then passthrough; pops the advance that moves it to passthrough and forwards later onesFunnel advanced by control wavelets

Lesson 10 of the tutorial, Switches: PEs that take turns on one color, is a working example of the serial drain, and the topic Switch protocols advances switches with control wavelets.

Modifiers:

  • ring — operate in ring mode
  • pop=all — unconditional pop
  • pop=adv — pop on advance
  • pop=advnop — pop on advance or nop

To pop a control wavelet is to remove its command 0 as it leaves the router, so the next router acts on the next command. Without ring, pop=adv and pop=advnop pop only while the switch is not in its last position.

Teardown (tip)​

r : paint(c [C>R; tip])

Start the color in teardown state: its router accepts no wavelets on the color until a program on the tile clears the color's teardown-in-progress bit. A teardown control wavelet puts a color in the same state. Paint leaves every color that has no rule on a PE in this state, with its input disabled.