CompressedToroidalRouteCache::Decompress — Proto 到 Map 的展开
本页所有地址适用于
libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64wheel 中的libtpu.so(buildlibtpu_lts_20260413_b_RC00,build-id89edbbe81c5b328a958fe628a9f2207d)。该二进制带完整 C++ 符号(.textVMA == 文件偏移,base0xe63c000);下文每个地址都是 VMA。已反混淆名称和字段偏移已与 IDA 反编译结果交叉核对。其他版本会不同。
摘要
Decompress 是 预计算 route-cache 加载路径的第一阶段:它接收一个 proto::CompressedToroidalRouteCache,也就是 tsl::ReadBinaryProto 从 embed://…/<shape>.binarypb.compressed 烘焙资源读出的 Brotli 压缩包装器,并产生内部的 proto::ToroidalRouteCache 消息。它是一个很薄的 riegeli 解码流程:验证 format == 2,将 data 字段(一个 absl::Cord)包进 riegeli::BrotliReader,再把解压后的字节 ParseMessage 成内部 proto。解压出的 proto 还不是 内存中的查找结构;它是按每个 (src,dst) 列出的 RouteScheme 记录列表。
本页随后记录将该 proto 转成内存中 (src,dst) → path map 的两个阶段。ToroidalRouteCache 构造函数(@0x20b5d8e0)会根据 第一个 RouteScheme 的 route oneof case 设置对象的内存 布局判别量 [obj+0],也就是 distance vs static-path vs bit-encoded vs random-hop;该值决定四个 FlatHashMap 槽中的哪一个保存每个 pair 的值。CacheRead(@0x20b5da20)是 逐条目展开循环:它从去重 orientation vector 构建 TopologyRotationHelper,然后对每个 RouteScheme 将 (src_chip_id, dest_chip_id) 旋转进此 topology 的芯片 id 空间,按布局判别量解码路径主体,并把 (rotated_src, rotated_dst) → value pair 插入匹配的 map。
CacheRead 消费的去重 orientation vector 由 route-cache-dedup.md 产生;type-2(bit_encoded_path)variant 的 bit-stream 主体由 DecodePathFromBits 解包,记录在 route-cache-codec.md;容器对象、它在 topology 中的嵌入,以及运行时读侧分派位于 toroidal-route-cache.md。本文负责 Decompress 函数体、ToroidalRouteCacheType proto enum(文件 选择器,区别于布局判别量),以及 CacheRead 展开循环。
重新实现时,契约为:
Decompress—format == 2gate、absl::Cord→riegeli::BrotliReader设置,以及ParseMessage到proto::ToroidalRouteCache。- 两个判别量 —
proto::ToroidalRouteCacheType(密集[0,4]文件/代号 enum,选择要加载哪个烘焙 blob)与内存中的[obj+0]布局 int{0,1,2,3}(scheme 携带哪个 oneof,进而决定哪个 map)。 - 展开循环 — 对每个
RouteScheme:对两个芯片 id 做RotateId,按 layout type 解码路径(RotateCoordinates/ 每跳RotateOrientation/DecodePathFromBits),find_or_prepare_insert进对应类型的 map,并拒绝重复(src,dst)key。
| Decompress | slice_builder::Decompress(const proto::CompressedToroidalRouteCache&) @ 0x20b63320 |
构造函数(设置 [obj+0]) | ToroidalRouteCache::ToroidalRouteCache(const proto::ToroidalRouteCache&, const vector<proto::Orientation>&) @ 0x20b5d8e0 |
| 展开循环 | ToroidalRouteCache::CacheRead(const proto::ToroidalRouteCache&, const vector<proto::Orientation>&) @ 0x20b5da20 |
| 文件选择 enum | proto::ToroidalRouteCacheType,密集区间 [0,4],descriptor @0x20c06b00 |
| Brotli reader vtable | off_22015FE0(riegeli::BrotliReader)位于 off_22015E78(riegeli::CordReader)之上 |
| Parse 入口 | riegeli::parse_message_internal::ParseMessageImpl @ 0x20be5d60 |
| 路径编解码器(type 2) | DecodePathFromBits @ 0x20b5c5a0 → route-cache-codec.md |
| 源文件 | platforms/accel_ssw/deepsea/slice_builder/internal/compressed_toroidal_route_cache.cc;…/toroidal_route_cache.cc |
对 Decompress 函数体、[obj+0] 判别量算术、四个 CacheRead map 分支及其 find_or_prepare_insert policy 类型,以及 ToroidalRouteCacheType enum 名称,置信度为 已确认(字节锚定),均已与 IDA 反编译和 .rodata 字符串交叉核对。唯一 LOW 置信度项已在文内标注(random_first_hop 的 proto wire-tag)。
Decompress 在加载路径中的位置
Decompress 是 ToroidalRouteCache::Create(@0x20b5d6e0)的一步,该调用会物化一个预计算缓存。调用链如下:
ToroidalRouteCache::Create (0x20b5d6e0)
├─ GetRouteCacheData (0x20b5c420)
│ ├─ GetRouteCacheDataPath (0x20bf2080) ── "embed://<lower(Type)>_data/<shape>.binarypb.compressed"
│ ├─ tsl::ReadBinaryProto (0x20d02060) ── read CompressedToroidalRouteCache off the baked resource
│ └─ Decompress (0x20b63320) ── *** THIS PAGE: Brotli → proto::ToroidalRouteCache ***
├─ ToroidalRouteCache::ctor (0x20b5d8e0) ── set [obj+0] = layout type from 1st RouteScheme oneof
│ └─ CacheRead (0x20b5da20) ── *** THIS PAGE: proto → 4 FlatHashMaps, rotated ***
└─ move the 4 maps into the StatusOr<ToroidalRouteCache> result
```text
`GetRouteCacheDataPath` 是两个 type 判别量中的 **第一个** 被消费的位置:它将 `ToroidalRouteCacheType` enum 名称转小写,并用 `StrFormat` 写入资源路径。`Decompress`/`CacheRead` 则展开内部 proto。容器及其 `Create` 编排详见 [`toroidal-route-cache.md`](toroidal-route-cache.md);本文从 `Decompress` 边界开始。
---
## Decompress @0x20b63320 — Brotli,不是 zstd
`Decompress` 消费一个 `proto::CompressedToroidalRouteCache`,其 schema 只有两个字段:
| field | tag | type | 内存偏移 | 作用 |
|-------|-----|------|------------------|------|
| `format` | 1 | `int32` | `[proto+0x28]` | 压缩判别量;**必须是 `2`** |
| `data` | 15 | `bytes`(`absl::Cord`) | `[proto+0x18]` | Brotli 压缩的 `ToroidalRouteCache` 字节 |
解码是固定的 riegeli pipeline。位于 `[proto+0x28]` 的 `format` 字段会按 dword 读取并与 `2` 比较;任何其他值都会短路为错误。
```c
// 0x20b63320 — Decompress(this <- StatusOr storage, const CompressedToroidalRouteCache* cc)
StatusOr<proto::ToroidalRouteCache> Decompress(const CompressedToroidalRouteCache* cc) {
if (*((int32_t*)cc + 10) != 2) // [cc+0x28] == format; line 0x20b63335
return MakeError(InvalidArgument, // status code 13
StrFormat("Unsupported format: %d", cc->format));
// cc->data is an absl::Cord at [cc+0x18]; ref-bump it into a local Cord (v26/v27),
// then construct a BrotliReader<CordReader<Cord>> on the heap (operator new(0x158)).
void* reader = operator new(0x158);
*(void**)reader = &off_22015FE0; // riegeli::BrotliReader vtable
*(void**)(reader + 112) = &off_22015E78; // riegeli::CordReader vtable
// copy the borrowed Cord into the reader's owned slot [reader+0x148]
riegeli::CordReaderBase::Initialize(reader + 112, /*Cord*/ reader + 328); // 0x1db11ec0
riegeli::BrotliReaderBase::Initialize(reader, /*src=*/ reader + 112); // 0x20b64ee0
proto::ToroidalRouteCache out; // ctor(&out, 0)
// default_recursion_limit_ packed into the high word; v16 = vtable[+0x60](reader, 1)
int64_t st = riegeli::parse_message_internal::ParseMessageImpl(reader, &out, ...); // 0x20be5d60
if (st == 1) reader->vtable[+0x58](); // VerifyEndAndClose on success
if (!riegeli::Object::Close(reader)) { ... fold reader status into st ... }
reader->vtable[+0x8](); // ~reader / dtor
if (st != 1) // parse failed
return CreateStatusAndConditionallyLog( // tagged compressed_toroidal_route_cache.cc:52
StatusBuilder::InitRepImpl(st));
return out; // move/CopyFrom into the StatusOr payload
}所有关键事实都由字节锚定:
format == 2是唯一可接受值。 比较位于0x20b63335;失败路径运行FormatPack("Unsupported format: %d", 22)和MakeErrorImpl<13>(InvalidArgument),标记为compressed_toroidal_route_cache.cc:40。不存在case 1/zstd 分支;磁盘上的.compressed资源始终是 Brotli 流。- reader 是叠在
riegeli::CordReader上的riegeli::BrotliReader。 两个 vtable 分别写入对象偏移+0(off_22015FE0)和+112(off_22015E78);CordReaderBase::Initialize(@0x1db11ec0)和BrotliReaderBase::Initialize(@0x20b64ee0)连接该链。dataCord通过_InterlockedAdd(refcount, 2)增加引用后借用,并复制进 reader 自有的 Cord 槽[reader+0x148]。 - 内部消息由 riegeli 的
ParseMessageImpl解析(@0x20be5d60),并使用标准的proto2::io::CodedInputStream::default_recursion_limit_。成功时(st == 1),解析出的proto::ToroidalRouteCache会CopyFrom/InternalSwap到StatusOrpayload(尾部选择Copy还是Swap取决于两个 arena 是否匹配,0x20c040a0/…e0)。 - 失败是结构化的,而非 fatal。 parse 或 reader 错误会返回非 OK
Status(标记为compressed_toroidal_route_cache.cc:52);调用方(GetRouteCacheData)会传播它。(对比下方 构造函数,它会在 malformed proto 上CHECK失败;这两个阶段的失败纪律不同。)
注意 — riegeli format 字节 vs 磁盘 magic。
format == 2是CompressedToroidalRouteCache.formatproto 字段,不是 Brotli/riegeli 流 magic byte。它是生产端契约:烘焙.binarypb.compressed资源的一方写入format = 2和 Brotlidatablob。未来的格式1/3在添加解码分支前都会落入Unsupported format错误。
两个 type 判别量(不要混淆)
该子系统中有两个不同整数都会被读作 “type”。它们位于不同位置,并驱动不同决策。
1. proto::ToroidalRouteCacheType — 文件/代号选择器
一个密集 protobuf enum,区间 [0,4],descriptor @0x20c06b00(表 @0x224ab9c0)。五个取值名称原样存在于 .rodata:
| value | enum name | 作用 |
|---|---|---|
| 0 | CACHE_UNKNOWN_TYPE | 哨兵 / 未设置 |
| 1 | CACHE_TWISTED_TORUS | 非 resilient slice-builder twisted torus |
| 2 | CACHE_ICI_RESILIENCY_PUFFERFISH | resilient — pufferfish silicon generation |
| 3 | CACHE_ICI_RESILIENCY_VIPERFISH | resilient — viperfish silicon generation |
| 4 | CACHE_ICI_RESILIENCY_6acc60406 | resilient — 6acc60406 silicon generation |
该 enum 是 GetRouteCacheDataPath(@0x20bf2080)的输入,不是 CacheRead 的输入。反编译显示,密集 enum lookup NameOfDenseEnum<&ToroidalRouteCacheType_descriptor, 0, 4> 受 type <= 4 限制,随后 AsciiStrToLower,再 FormatPack 到资源模板:
"embed://%s_data/%s.binarypb.compressed" (the path template; AsciiStrToLower @0x20bf2080)
│ │
│ └─ StrCat( JoinAlgorithm(dims, "x"), is_twisted ? "_twisted" : "",
│ orientation ? "_" + NameOfDenseEnum<Orientation,0,6>(orient) : "" )
└─ lower(NameOfDenseEnum<ToroidalRouteCacheType,0,4>(type)) e.g. "cache_twisted_torus"
⇒ "embed://cache_twisted_torus_data/12x12x24_twisted.binarypb.compressed"
```text
因此 `ToroidalRouteCacheType` 选择 **加载哪个烘焙 blob**,即每个代号 family 一个。代号选择(以及选择哪个 dedup singleton 和哪个 enum 值)在上游 `InitRouteSolution` 中完成;见 [`route-cache-dedup.md`](route-cache-dedup.md)。用于可选路径后缀的 `Orientation` enum 自身也是密集 `[0,6]` enum(`{UNKNOWN=0, X=1, Y=2, Z=3, A=4, B=5, C=6}`)。
### 2. `[obj+0]` — 内存布局判别量
位于 `ToroidalRouteCache` 对象头部的普通 `int`,取值 `{0,1,2,3}`,由构造函数从 *第一个* `RouteScheme` 的 `route` oneof case 设置。它选择 **四个 `FlatHashMap` 槽中的哪一个** 保存每个 pair 的值。它独立于 `ToroidalRouteCacheType`:一个 `CACHE_TWISTED_TORUS` blob 和一个 `CACHE_ICI_RESILIENCY_VIPERFISH` blob 都可以携带 `bit_encoded_path` scheme,并且二者都得到 `[obj+0]==2`。
> **注意。** 还存在 *第三个* 无关的 “type” int,即 topology 对象上的 twist-shape 判别量 `[topo+0xe8]` `{1,2,3}`(`k·k·2k` / `k·2k·2k` / `k·2k·nk`)。它随 twisted-torus 几何记录,不在本文被消费。
---
## 构造函数 @0x20b5d8e0 — 设置 `[obj+0]`
构造函数将四个 map 槽(`[obj+0x8]`、`[obj+0x28]`、`[obj+0x48]`、`[obj+0x68]`)清零初始化,计算 `[obj+0]`,然后调用 `CacheRead`。布局 int **只由第一个 scheme 的 oneof tag 派生**,但若 *任何* scheme 带有 random-first-hops,则会将 `static_path` 缓存升级为 random-hop 布局。
```c
// 0x20b5d8e0 — ToroidalRouteCache(this, const proto::ToroidalRouteCache* cache_pb, const vector<Orientation>* orients)
void ToroidalRouteCache::ToroidalRouteCache(int* obj, const proto::ToroidalRouteCache* cache_pb, ...) {
obj[0x8>>2] = obj[0x28>>2] = obj[0x48>>2] = obj[0x68>>2] = 0; // 4 empty FlatHashMaps
CHECK(cache_pb->routing_schemes_size() != 0); // hard CHECK; toroidal_route_cache.cc:128
// ("cache_pb.routing_schemes_size() != 0")
auto& scheme0 = cache_pb->routing_schemes(0); // [cache_pb+0x18] repeated field, element 0
int oneof = scheme0._oneof_case; // [scheme0+0x38]
int type;
if (oneof == 3) type = 0; // distance → distance map [obj+0x8]
else if (oneof == 5) type = 2; // bit_encoded_path→ vec<Dir> map [obj+0x28]
else { // static_path (4) and everything else
type = 1; // → vec<Dir> map [obj+0x28]
for (auto& s : cache_pb->routing_schemes) // any scheme with random-first-hops?
if (s.random_first_hop_size() > 0) { // [s+0x20] > 0
type = 3; // → random-hop maps [obj+0x48]/[+0x68]
break;
}
}
obj[0] = type; // *** the layout discriminant *** 0x20b5d97b
CHECK_OK( this->CacheRead(cache_pb, orients) ); // toroidal_route_cache.cc:152
}oneof([scheme0+0x38]) | 附加条件 | [obj+0] | 布局 |
|---|---|---|---|
3(distance) | — | 0 | distance vector |
5(bit_encoded_path) | — | 2 | bit-packed Direction path |
4(static_path) | 没有 scheme 含 random_first_hop | 1 | 单个 Direction path |
4(static_path) | 某个 scheme 有 random_first_hop > 0 | 3 | random-hop path set |
两个 CHECK 使该构造函数在 malformed proto 上不可恢复:空 routing_schemes(toroidal_route_cache.cc:128)和非 OK CacheRead 结果(:152)。由于 proto 来自 烘焙、可信 资源,此处失败就是构建/打包 bug,因此是 abort 类 LogMessageFatal,而不是传播 Status。反编译还用 LogIndexOutOfBoundsAndAbort(标准 generated-proto bounds check)保护 routing_schemes(0) 访问。
注意 — first-scheme homogeneity。 判别量只从 scheme
0读取(另加全局 random-hop 扫描)。因此缓存生产者必须在一个 blob 中发出 同质 的routeoneof;混合 distance/static_path 的文件会被错误定型。CacheRead的逐 schemeRetCheck(见下)正是防御这种情况,将异质 blob 转成非 OK status,而不是静默误插入。
CacheRead @0x20b5da20 — 逐条目展开循环
CacheRead 是主力:它将解析后的 proto 转为四个内存 map。它很大,因为四个 layout 分支都完全内联,每个都有自己的 raw_hash_set find_or_prepare_insert 和 value 构造代码,但结构是统一的。
Prologue — 构建旋转 helper
// 0x20b5da20 — CacheRead(this, const proto::ToroidalRouteCache* cache_pb, const vector<Orientation>* orients)
topo = slice_builder::Topology( cache_pb->topology() ); // field 1 → Topology ctor @0x20bf3820
rot = TopologyRotationHelper::Create(topo, *orients); // @0x20bf2380 (orients = dedup payoff)
if (!rot.ok()) return rot.status(); // toroidal_route_cache.cc:161
int type = this->obj[0]; // the layout discriminant
```text
`orients` 是 dedup `Find` 返回的 `vector<proto::Orientation>`(见 [`route-cache-dedup.md`](route-cache-dedup.md))。缓存 blob 以单一 **规范** orientation 写入;helper `rot` 是从该规范芯片 id/坐标空间到 *此* topology 轴的重映射。后续每个 key 和每个坐标都会通过 `rot`,这正是让一个烘焙 blob 服务一个形状所有 X/Y/Z 旋转的机制。`RotateId`/`RotateCoordinates`/`RotateOrientation` 自身的逐轴置换数学属于 [`route-cache-codec.md`](route-cache-codec.md);此处只标注它 *在哪里* 被应用。
### 逐 scheme 循环
对每个 `RouteScheme`,执行同一个骨架:
```c
for (auto& scheme : cache_pb->routing_schemes) { // field 3, repeated
int skey = rot.RotateId(scheme.src_chip_id); // [scheme+0x28] @0x20bf3020
int dkey = rot.RotateId(scheme.dest_chip_id); // [scheme+0x2c] @0x20bf3020
pair<int,int> key{skey, dkey};
// ... decode value per `type`, then find_or_prepare_insert(key, value) ...
}RotateId 是 topo.GetCoordinate(id) → RotateCoordinates → topo.GetId(coord)(GetCoordinate/GetId 是虚函数,vtable+0x88/+0x90)。两个芯片 id 都在组成 map key 之前 被重映射,因此内存 map 以 此 topology 的 芯片 id pair 为 key,而不是规范 blob 的。
四个 value 解码分支
分派形式为 if (type == 3) … else if (type == 2) … else if (type != 0 /*type 1*/) … else /*type 0*/。每个分支最终都会对不同的 FlatHashMapPolicy 做一次 find_or_prepare_insert,并且每个分支都有 RetCheck 守卫,确认 scheme 确实携带预期的 oneof:
type | 每个 scheme 的 proto oneof | value 解码 | 目标 map | find_or_prepare policy value 类型 |
|---|---|---|---|---|
0 | distance (3) — 由 RetCheck(has_distance()) :166 守卫 | RotateCoordinates(scheme.distance) @0x20b5da20:3039 | [obj+0x8] | superpod::routing::Coordinates |
1 | static_path (4) — 由 RetCheck(has_static_path()) :189 守卫 | 通过 RotateOrientation 旋转每个 static_path.hops[i] | [obj+0x28] | vector<proto::Direction> |
2 | bit_encoded_path (5) — 由 RetCheck(has_bit_encoded_path()) :216 守卫 | DecodePathFromBits(scheme.bit_encoded_path) @0x20b5c5a0 | [obj+0x28] | vector<proto::Direction> |
3 | random_first_hop(repeated) | 每个 random_first_hop[i].hop 一个 vector<Direction>;probability → int8 weights | [obj+0x48](paths)+ [obj+0x68](weights) | vector<vector<proto::Direction>> + vector<int8_t> |
按分支列出的字节锚定说明:
- Type 0(distance)。
superpod::routing::Coordinatesvalue 由 scheme 的distanceChipCoordinate构造(Coordinates::Coordinates@…:3038),经RotateCoordinates(@…:3039)处理,然后插入FlatHashMapPolicy<pair<int,int>, superpod::routing::Coordinates>(find_or_prepare_insert_large@…:3047)。distance value 是一个superpod::routing::Coordinates,即有符号逐轴 distance vector,而 不是slice_builder::Coordinates。这是运行时GetRouteDistance读取的 map。 - Type 1(static_path)。
scheme.static_path.hops中的每个Direction(一个RepeatedPtrField;StaticPath默认实例是…_StaticPath_globals_)都会被复制并用RotateOrientation重映射,累积成插入[obj+0x28]的vec<Direction>map 的vector<proto::Direction>。RetCheck(has_static_path())位于toroidal_route_cache.cc:189。 - Type 2(bit_encoded)。 单个
scheme.bit_encoded_pathbytes字段被传给DecodePathFromBits(@0x20b5c5a0),返回的vector<proto::Direction>插入与 type 1 相同 的[obj+0x28]map:type 1 和 2 是同一个内存 value 的两种编码。bit-stream 布局(BitDecoder::GetVarInt头、每个 Direction 的orientation(2b)/polarity(1b))由route-cache-codec.md负责。RetCheck(has_bit_encoded_path())位于:216。 - Type 3(random-hop)。 体积最大的分支:对每个
random_first_hop[i],一个Direction(hop,经RotateOrientation重映射)变成一个单元素vector<Direction>,这些集合再变成插入[obj+0x48]的vector<vector<Direction>>(FlatHashMapPolicy<pair<int,int>, vector<vector<Direction>>>)。每跳probability(proto 中是int32)被窄化为int8,并累积到一个平行的vector<int8_t>,插入[obj+0x68]。两个 map 都以同一个旋转后的(src,dst)pair 为 key,因此 path set 和 weight vector 保持对齐。
拒绝重复 key
每个分支都会检查 find_or_prepare_insert 结果,并 拒绝第二个具有同一旋转后 (src,dst) key 的 scheme:
// e.g. type 3, around 0x20b5da20:+offset (the "$_0" lambda inline)
if (!inserted_fresh) {
return MakeError(/*code 3 = InvalidArgument*/,
StrCat("Duplicate insertion associated with source: ", skey,
" and destination: ", dkey)); // toroidal_route_cache.cc:322
}
```text
`StrCat` 会拼接字面量 `"Duplicate insertion associated with source: "`、source 芯片 id、`" and destination: "` 和 destination 芯片 id(经 `FastIntToBuffer`)。因此重复项是一个 *硬性、显式* 错误:缓存契约是在 *旋转后* 每个 `(src,dst)` pair 正好一个 `RouteScheme`;碰撞(生产者 bug,或两个旋转前 key 在旋转后 alias)会以精确诊断中止加载,而不是静默覆盖。
### 结果
OK 路径上,`CacheRead` 返回 `Status::OK`(`v15 == 1`),对象上的四个 `FlatHashMap` 槽被填充;随后 `Create` 将它们 move-construct 到 `StatusOr<ToroidalRouteCache>` payload(每个 map 的 C2 mover `@0x1fbe41e0`/`4220`/`4260`/`42a0`)。任何 `RetCheck` 不匹配或重复项都会产生非 OK `Status`,构造函数的 `CHECK_OK`(`:152`)随后会将其转为 fatal。
---
## 端到端(一张图)
```text
GetRouteCacheData(dims, twisted, orient, ToroidalRouteCacheType) # 0x20b5c420
path = "embed://" + lower(NameOf(type)) + "_data/" + <shape> + ".binarypb.compressed"
ReadBinaryProto(path) → CompressedToroidalRouteCache{ format, data:Cord } # 0x20d02060
└─ Decompress: format==2 ? BrotliReader(data) → ParseMessage # 0x20b63320 [THIS PAGE]
→ proto::ToroidalRouteCache{ topology, routing_schemes[] }
ctor(proto, dedup_orientations) # 0x20b5d8e0 [THIS PAGE]
[obj+0] = {distance→0, static_path→1, bit_encoded→2, +random_hop→3}
CacheRead(proto, dedup_orientations): # 0x20b5da20 [THIS PAGE]
rot = TopologyRotationHelper(topology, dedup_orientations) # canonical→actual remap
for scheme in routing_schemes:
key = ( rot.RotateId(src_chip_id), rot.RotateId(dest_chip_id) )
switch [obj+0]:
0: map@+0x8 [key] = rot.RotateCoordinates(distance) # superpod::routing::Coordinates
1: map@+0x28[key] = [rot.RotateOrientation(h) for h in static_path.hops] # vector<Direction>
2: map@+0x28[key] = DecodePathFromBits(bit_encoded_path) # vector<Direction> → codec page
3: map@+0x48[key] = [[hop] for hop in random_first_hop]; # vector<vector<Direction>>
map@+0x68[key] = [int8(p.probability) for p in random_first_hop]
on collision: error "Duplicate insertion associated with source: …"
Create: move the 4 maps into StatusOr<ToroidalRouteCache> # 0x20b5d6e0重新实现检查清单
- [ ]
Decompress:用InvalidArgument("Unsupported format: %d")拒绝format != 2;将dataCord包进riegeli::BrotliReader<CordReader<Cord>>;ParseMessage到proto::ToroidalRouteCache;传播 parse 失败(不要 abort)。 - [ ] 构造函数:
CHECK非空routing_schemes;从routing_schemes(0)._oneof_case设置[obj+0](3→0, 5→2, 4→1),如果 任何 scheme 有random_first_hop_size() > 0,则将1→3。 - [ ]
CacheRead:从去重 orientation vector 构建TopologyRotationHelper;对每个 scheme,将两个芯片 id 都RotateId到 key;按 layout type 解码,并对匹配的has_*()做RetCheck;插入 per-type map;用精确的"Duplicate insertion associated with source: …"消息拒绝重复 key。 - [ ] 保持四种 value type 字节级精确:distance →
superpod::routing::Coordinates;static/bit-encoded →vector<proto::Direction>(同一 map);random-hop →vector<vector<proto::Direction>>加平行的vector<int8_t>weight map。
注意(字段号置信度 LOW)。 按上游 descriptor decode,
random_first_hop字段 tag 是 wire tag 7;本文只锚定构造函数升级和逐元素hop/probability访问所用的内存[scheme+0x20]count 读取。精确 proto 字段 编号(7)来自 descriptor,而不是由本文中的EnumDescriptorProto字节确认;因此图中的(7)标注应按此处理。
交叉引用
route-cache-dedup.md—RouteCacheDeduplicator、RouteCacheIdentifierkey,以及CacheRead消费的vector<proto::Orientation>rotation vector;也包括选择ToroidalRouteCacheType的无参 vs 代号 keyedGetCacheDeduplicatoroverload。route-cache-codec.md—DecodePathFromBits(type-2 bit-stream 解包)以及贯穿CacheRead应用的TopologyRotationHelperRotateId/RotateCoordinates/RotateOrientation置换数学。toroidal-route-cache.md—ToroidalRouteCache容器对象、它的四个FlatHashMap布局及其在 topology 中的嵌入、Create编排,以及基于[obj+0]的运行时读侧分派(CacheHit/GetRouteDistance/GetRoutePath)。overview.md— ICI routing 章节地图:预计算ToroidalRouteCache相对于实时*ToroidalWildFirstPaths生成器和InitRouteSolutioncache-vs-generate 决策的位置。get-static-path.md— packed(hop_count<<6 | polarity<<3 | orientation)DirectionHops编码,由缓存的vector<proto::Direction>条目和实时路径生成器共享。