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
| Code | Direction | Description |
|---|---|---|
R | Right | East (+X) |
L | Left | West (−X) |
U | Up | +Y (router south port) |
D | Down | −Y (router north port) |
C | Center | PE 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:
| Modifier | Inputs read from the partner |
|---|---|
> | none |
H | left and right (east/west) |
V | up and down (north/south) |
X | left, 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:
flip(local switch advance) — a Tungstenflip tx[]statement piggybacks a sideband bit on the last data word; when the CE transmits it, the local input switch advances.- 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 withcontrol(); 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, andpop=advandpop=advnopare 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. Withoutring, advancing does not cycle back to the first position.
Common patterns:
| Pattern | Positions | Use case |
|---|---|---|
[C>R ; L>R] | Inject, then passthrough | Serial drain with flip |
[L>R ; C>R] | Passthrough, then inject | Deferred injection (via an advance control wavelet from upstream) |
[C>D ; U>D] | Inject down, then pass-through | Vertical funnel |
[C>D ; U>D ; pop=adv] | Inject, then passthrough; pops the advance that moves it to passthrough and forwards later ones | Funnel 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 modepop=all— unconditional poppop=adv— pop on advancepop=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.