Маршрутизация и Граф Активации
Соседи формируют эстафету, данные идут через шину
🗺️ RoutingFlags16
Карта Битов (LSB-first)
| Бит |
Флаг |
Описание |
| bit0 |
N |
Север: активация соседа сверху |
| bit1 |
E |
Восток: активация соседа справа |
| bit2 |
S |
Юг: активация соседа снизу |
| bit3 |
W |
Запад: активация соседа слева |
| bit4 |
NE |
Северо-восток: диагональ |
| bit5 |
SE |
Юго-восток: диагональ |
| bit6 |
SW |
Юго-запад: диагональ |
| bit7 |
NW |
Северо-запад: диагональ |
| bit8 |
BUS_R |
Читать шину (источник ACTIVE) |
| bit9 |
BUS_W |
Писать в шину (WRITE фаза) |
| bit10..15 |
reserved |
Должны быть 0 |
Пример
routing_flags16 = 0x0301
# binary: 0000 0011 0000 0001
# биты: N(0) + BUS_R(8) + BUS_W(9)
🧭 Топология Соседей
Массив Тайлов
tile_id = y * tile_w + x
Кардинальные Соседи
| Направление |
Формула |
Условие |
| N(x,y) |
(x, y-1) |
y > 0 |
| S(x,y) |
(x, y+1) |
y < tile_h-1 |
| W(x,y) |
(x-1, y) |
x > 0 |
| E(x,y) |
(x+1, y) |
x < tile_w-1 |
Диагонали
| Направление |
Формула |
Условие |
| NE(x,y) |
(x+1, y-1) |
x < tile_w-1 и y > 0 |
| SE(x,y) |
(x+1, y+1) |
x < tile_w-1 и y < tile_h-1 |
| SW(x,y) |
(x-1, y+1) |
x > 0 и y < tile_h-1 |
| NW(x,y) |
(x-1, y-1) |
x > 0 и y > 0 |
🔗 Рёбра Активации
Правило
Если у тайла A установлен флаг Dir и сосед B = neighbor(A, Dir) существует
→ ребро A → B
Важные Свойства
| Свойство |
Описание |
| Только ACTIVE |
Рёбра влияют только на вычисление ACTIVE |
| Данные не передаются |
Соседи данные не отправляют |
| Мульти-родители |
Разрешены |
| Циклы |
Разрешены (детерминизм через locked_before) |
🌳 Граф Активации (ACTIVE Closure)
Вычисление ACTIVE
# Seed: источники (корни цепочки)
ACTIVE[t] = 1 если BUS_R[t] == 1
# Propagate: замыкание по графу
ACTIVE[t] = 1 если существует p ∈ Parents(t) такой что:
ACTIVE[p] == 1 И locked_before[p] == 1
# Least fixed point до стабилизации
Пример Эстафеты
Тик N:
Tile A (BUS_R=1): ACTIVE=1, вычисляется, locked_after=1
Tile B (родитель A, флаг N): ACTIVE=0 (пока locked_before[A]=0)
Тик N+1:
Tile A: locked_before=1, драйвит шину
Tile B: ACTIVE=1 (т.к. ACTIVE[A]=1 и locked_before[A]=1)
→ читает VSB_INGRESS → вычисляется
🎯 Parents(t) — Множество Родителей
Parents(t) = { p | у тайла p есть флаг Dir и neighbor(p, Dir) = t }
Пример
Tile(5,5) имеет родителей:
- Tile(5,6) если у него установлен флаг N
- Tile(4,5) если у него установлен флаг E
- Tile(5,4) если у него установлен флаг S
- Tile(6,5) если у него установлен флаг W
- Tile(6,4) если у него установлен флаг NE
- Tile(6,6) если у него установлен флаг NW
- Tile(4,6) если у него установлен флаг SE
- Tile(4,4) если у него установлен флаг SW
🚨 Схлоп Ветки
Если корневой/промежуточный тайл расфюжен (reset/collide):
Тик N: тайл A: locked_before=1, драйвит шину
Тик N+1: тайл A: reset → locked=0
Тик N+2: тайл B (потомок A): ACTIVE=0 → принудительно в 0
Принудительный Ноль
if ACTIVE[t] == 0:
thr_cur16 := 0
locked := 0
drive_vec := {0, 0, 0, 0, 0, 0, 0, 0}
# веса/row/decay не применяются
📐 Пример Конфигурации
Массив 4×4
┌─────┬─────┬─────┬─────┐
│ 0,0 │ 0,1 │ 0,2 │ 0,3 │ BUS_R=1 (источник)
├─────┼─────┼─────┼─────┤
│ 1,0 │ 1,1 │ 1,2 │ 1,3 │ N=1 (активация снизу)
├─────┼─────┼─────┼─────┤
│ 2,0 │ 2,1 │ 2,2 │ 2,3 │ N=1
├─────┼─────┼─────┼─────┤
│ 3,0 │ 3,1 │ 3,2 │ 3,3 │ N=1
└─────┴─────┴─────┴─────┘
Граф Активации
(0,0) BUS_R=1 → ACTIVE seed
│
▼ (N у 1,0)
(1,0) → ACTIVE если locked_before[(0,0)]=1
│
▼ (N у 2,0)
(2,0) → ACTIVE если locked_before[(1,0)]=1
│
▼ (N у 3,0)
(3,0) → ACTIVE если locked_before[(2,0)]=1
🔗 BUS_R / BUS_W
BUS_R (Read)
| Параметр |
Значение |
| Бит |
bit8 (0x0100) |
| Назначение |
Источник ACTIVE (seed графа) |
| Эффект |
ACTIVE[t]=1 независимо от родителей |
BUS_W (Write)
| Параметр |
Значение |
| Бит |
bit9 (0x0200) |
| Назначение |
Разрешение записи в BUS16 |
| Условие |
locked self ИЛИ locked_ancestor |
Bake the Future. Build the Substrate. 🛠️⚡️