anthropic-design · diagram galleryanthropic-design · 图示案例库

Diagrams that carry the argument 让图替你把话说清

60 hand-built SVG figures in the anthropic-design language — for engineering docs, kernel & hardware work, product walkthroughs, and slide decks. Every figure follows the diagram-craft contract: sized to its content, ≥2 semantic hues, solid color dots, readable at every label. Copy any of them straight into your page. 60 张手工 SVG 图,覆盖工程文档、内核与硬件、产品演示、演讲汇报四类场合。每张都按 diagram-craft 工艺合约执行:画布贴内容、每图 ≥ 2 个语义色、实心色点、所有标签可读。点 Copy SVG 即可直接用进你的页面。

01 · for engineers01 · 写给工程师

Engineering diagrams 工程图

Architecture, flows, sequences, git history, states, deployment — one hue per layer or category, orange reserved for the focus, color always on solid dots and bars rather than flooded fills. 架构、流程、时序、git 历史、状态机、部署拓扑——一层一个色相,橙色只给焦点;颜色落在实心色点和色条上,不做大面积满填。

PRESENTATION user-facing surfaces Web browser client Mobile iOS · Android CLI terminal tools API REST · SDK 1 APPLICATION coordination & policy Router match & dispatch Orchestrator plan · collect · merge Gateway tool calls · rate limits Guard allow · deny · confirm 2 DOMAIN business logic Billing invoices · ledger Catalog products · pricing Identity accounts · roles Reporting rollups · exports 3 INFRASTRUCTURE runtime substrate Database Postgres cluster Storage objects · backups Network LB · CDN · DNS Queue async jobs
architecture · layers架构 · 分层 Four-layer system map. Each layer is a 16-20% tint container with a 4px color bar; nodes are white cards with solid category dots. Template: templates/diagrams/architecture.svg. 四层系统图。每层是 16-20% tint 容器加 4px 色条,节点是白卡加实心类别色点。模板:templates/diagrams/architecture.svg
pass fail · retry Valid? Fetch input Verify Process Publish 1 2 3 4
flow · decision流程 · 决策 Pipeline with numbered badges, a decision diamond (the only emphasis-tint block in the frame), and a gray fail loop routed below. Template: templates/diagrams/flow.svg. 带编号徽章的流水线,决策菱形是全图唯一的强调 tint 色块,失败回流走图下方灰虚线。模板:templates/diagrams/flow.svg
Client browser app Gateway auth · rate limit Worker runs the job Postgres primary db POST /v1/messages 1 schedule(run) 2 INSERT run · queued 3 ack · 12 ms 4 stream tokens 5 200 OK · server-sent events 6 request response data write
sequence · api时序 · API A chat request end to end: solid orange for the request chain, green for the data write, dashed gray for responses. Activation bars mark who is busy when. Read the badges in order — the one that matters is ④: the gateway acknowledges at 12 ms, before the worker has produced a single token, which is why the client can open a stream and wait rather than block on the whole run. 一次对话请求的完整时序:实线橙是请求链,绿色是数据写入,灰虚线是响应。激活条标出谁在何时忙碌。按编号读,关键的是 :网关在 12 ms 就应答了,那时 worker 一个 token 都还没产出——客户端因此可以开一条流去等,而不必阻塞在整次运行上。
main feature/gallery hotfix/1.4.2 init scaffold merge hotfix merge feature gallery grid copy button fix overflow v1.4
git graph · historygit 图 · 历史 Three branches, three hues: orange main, blue feature, gold hotfix. Commits are solid dots with a white core; the release tag is the one solid chip — small elements carry the color. 三条分支三个色相:橙 main、蓝 feature、金 hotfix。提交点是带白芯的实心圆,发布标签是唯一的实心色块——颜色由小元素承担。
start success pause resume error · retry ≤ 2 reset Idle awaiting job Running executing steps Done all gates green Paused operator hold Failed retries exhausted operator action active path terminal · ok terminal · error
state machine · lifecycle状态机 · 生命周期 Run lifecycle as a state machine. The focus state gets the orange tint card; transition lines take the hue of their meaning — green success, blue operator actions, gold errors, gray reset. 任务生命周期状态机。焦点状态用橙 tint 卡;迁移线按语义取色——绿是成功、蓝是人工操作、金是错误、灰是重置。
EDGE anycast · 12 PoPs CDN edge cache · 98% hit WAF rules v34 Load balancer least-conn APP CLUSTER auto-scale 2-8 nodes api REST + SSE ×3 worker queue consumer ×5 scheduler cron + retries dispatch DATA encrypted at rest Postgres 16 primary + replica Redis queues · cache Object store artifacts edge compute data
deployment · topology部署 · 拓扑 Three zones, three tints, one orange focus card. Replica counts ride as solid chips on the cards; the request path drops orange through the stack while data writes go green. 三个区三种 tint,一张橙色焦点卡。副本数以实心小色块贴在卡上;请求路径橙色贯穿,数据写入走绿色。
RAILROAD · WHAT IS OPTIONAL, WHAT REPEATS, WHAT YOU CHOOSE BETWEEN one rule: any path you can walk from the start ring to the end ring is legal. that is the whole notation, and it is why nothing here needs a condition label. AS NOTATION expr := [ '!' ] term { ( '&&' | '||' ) term } term := symbol | symbol '=' symbol | '(' expr ')' correct, complete — and you hold all of it in your head. the square brackets, the braces and the bar are doing three different jobs, and all three look alike. on the right those three jobs become three shapes. AS A RAILROAD · expr '!' term '&&' or '||' round again for another term skip it AS A RAILROAD · term symbol symbol '=' symbol '(' expr ')' three ways in, one way out this box points back at the track above — that is the recursion THE ONLY THREE SHAPES IT USES A over the top = you may skip it A back underneath = you may repeat it A B parallel rows = choose one a railroad diagram contains no decisions, so it must never be given diamonds, arrowheads on every segment, or condition labels — that turns it into a flowchart that is wrong. it beats notation on the three questions readers actually ask: may I leave this out, may I repeat it, which do I pick. each answer is a different shape, not a different bracket. it loses on recursion: notation says term contains expr in one line, while the picture can only point back at the track above. when a grammar is mostly recursive, keep the notation. this grammar is a cut-down form of the boolean expressions a kernel configuration language accepts, trimmed so each of the three shapes appears exactly once. Railroad · grammar as a path
notation · grammar as a path记号 · 把文法走成一条路 One rule: any path from the start ring to the end ring is legal, which is why nothing here carries a condition label. Three shapes do all the work — a bypass over the top means optional, a loop underneath means repeatable, parallel rows mean choose one — and in notation those same three jobs are done by square brackets, braces and a bar, which all look alike. It loses on recursion: notation says term contains expr in one line, while the picture can only point back at the track above. Template: templates/diagrams/railroad.svg. 唯一的规则:从起点环走到终点环,走得通的路径就是合法的——所以图上不需要任何条件标签。三种形状把活全干了:上方绕过 = 可省略、下方回环 = 可重复、并排分支 = 三选一;而在文法记号里,这三件事分别由方括号、花括号和竖线承担,长得都一样。它输在递归:记号一行就说清「term 里含 expr」,图只能指回上面那条轨。模板:templates/diagrams/railroad.svg
02 · kernel & hardware02 · 内核与硬件

Kernel & hardware diagrams 内核与硬件图

The diagrams an embedded engineer actually draws: function control flow with error lanes, register bit fields, SoC blocks, bus waveforms, build chains, scheduler timelines. Real names, real offsets — copy and swap the content. 嵌入式工程师真正天天画的图:带错误车道的函数控制流、寄存器位域、SoC 框图、总线波形、编译链、调度时间线。真实的名字和偏移——复制后换内容即可。

FUNCTION FLOWCHART · mydev_probe() AND ITS UNWIND LADDER happy path error path check HAPPY PATH nonono yes · -ENOMEM yes · -ENOMEM yes · ret mydev_probe() kzalloc() ioremap() request_irq() GFP_KERNEL res->start · SZ_4K IRQF_SHARED · priv !priv !base ret < 0 return 0 1 2 3 ERROR LANE · goto ladder, unwinds right to left falls through falls through err_free: err_unmap: kfree(priv) iounmap(base) err_out: return ret every failure enters the ladder at its own label, then falls through every earlier one — that is why kernel error paths are written with goto and not nested ifs kzalloc, not devm_kzalloc: under devm_ the ladder disappears, and with it the only reason to draw this figure
function flowchart · error lanes函数流程图 · 错误车道 A driver probe() laid out on the horizontal axis: badge 1 kzalloc, badge 2 ioremap, badge 3 request_irq, then return 0. Every diamond's yes branch drops straight down into the error lane, which is an unwind ladder read right to left — a request_irq failure enters at err_unmap and falls through err_free to err_out, while a kzalloc failure enters at err_out and returns immediately. The ladder's arrows point against the happy path because unwinding runs backwards. Vertical template: templates/diagrams/function-flowchart.svg. 驱动 probe() 横向排布:徽章 1 kzalloc、2 ioremap、3 request_irq,然后 return 0。每个菱形的 yes 分支垂直落进下方错误车道;车道是一把从右往左读的解绑梯 —— request_irq 失败从 err_unmap 进,依次落到 err_freeerr_out;kzalloc 失败直接从 err_out 进、立刻返回。梯子的箭头与主路径反向,因为解绑就是倒着走。纵向模板:templates/diagrams/function-flowchart.svg
UART_CTRL offset 0x04 · reset 0x0000_0301 reserved bits read as 0 · write as 0 31302928 27262524 23222120 19181716 BAUD_DIV 15141312 111098 7654 3210 PARITY STOP DATA8 FIFO_TH TX_EN RX_EN BAUD_DIV RW bits 23:16 · baud = PCLK / (16 · div) PARITY RW bits 11:10 · 00 none · 01 even · 10 odd DATA8 RW bit 8 · 1 = 8 data bits · 0 = 7 data bits RX_EN RW bit 0 · receiver enable · 1 at reset
register · bit fields寄存器 · 位域 A 32-bit control register split across two rows: fields as tint spans with solid top bars, reserved bits stay white, access chips and reset value where a datasheet would put them. Works for protocol frames too. Template: templates/diagrams/register-bitfield.svg. 32 位控制寄存器拆两行:字段用 tint 跨格加实心顶条,保留位留白,访问权限 chip 和复位值放在数据手册该放的位置。协议帧格式同样适用。模板:templates/diagrams/register-bitfield.svg
QUARTZ-3550 SoC · BLOCK DIAGRAM arm64 · 12 nm LP · 0.8 V core rail CPU SUBSYSTEM DynamIQ cluster · 1.8 GHz CLOCK & RESET 24 MHz xtal MEMORY AXI slaves HIGH-SPEED PERIPH DMA masters LOW-SPEED PERIPH via APB clk · rst Cortex-A55 ×2 L2 512K GIC-600 PLL ×3 CRU AXI NoC · 64-bit @ 800 MHz APB bridge DDR4 ctrl + PHY SRAM 256K Boot ROM PCIe Gen3 x2 USB 3.0 GbE MAC UART ×4 I2C ×3 SPI ×2 GPIO L1 32K I/D per core unified · ECC interrupt distributor core · ddr · peri gate · reset system interconnect · QoS arbitration · 4 masters AXI-to-APB · 100 MHz DDR4-3200 · 32-bit + ECC on-chip scratch 64K mask root complex · MSI-X xHCI DRD RGMII · TSO 16550A 400 kHz FM mode 0-3 4 banks ×32 1 2 CPU memory high-speed low-speed clock & reset main path
soc · block diagramSoC · 内部框图 Subsystems as tint zones, the interconnect as a neutral spine — never a saturated band. One orange path traces CPU through NoC to DDR; every zone keeps its own hue for internal links. Template: templates/diagrams/soc-block.svg. 子系统是 tint 分区,互连是中性脊柱——绝不画成饱和色带。唯一的橙色路径从 CPU 经 NoC 到 DDR,每个分区的内部连线用自己的色相。模板:templates/diagrams/soc-block.svg
MULTI-DIE INTERCONNECT · ADDRESS MAP memory compute / device MMIO window onto the other space NODE 0 · SOCKET one coherent domain NODE 1 · SOCKET one coherent domain DDR5 Host CPU die Accelerator die DDR5 Host CPU die Accelerator die 512 GB 64 core · 2.4 GHz 96 GB HBM3 · on-package 512 GB 64 core · 2.4 GHz 96 GB HBM3 · on-package DDR5 · 8 ch DDR5 · 8 ch CXL 3.0 · 64 GB/s CXL 3.0 · 64 GB/s fabric · 400 GB/s fabric · 400 GB/s Fabric switch 8 port · non-blocking CPU core · ld / st Accel core · ld / st DDR5 · 512 GB ACCEL HBM WINDOW MMIO 0x0000_0000 0x80_0000_0000 HOST PHYSICAL ADDRESS SPACE HBM3 · 96 GB HOST DDR WINDOW reserved 0x0000_0000 0x18_0000_0000 DEVICE PHYSICAL ADDRESS SPACE CXL.mem · HDM decoder
interconnect · address map互连拓扑 · 地址空间映射 Topology on top, one address space per viewpoint below, and a dashed load/store line stitching the two halves: a CPU core reaches the hatched accelerator window with a plain store, so a pointer can cross — no memcpy. The two strips are never merged: the same DRAM is 0x80_0000_0000 to the host and 0x18_0000_0000 to the device. Segment widths are not to scale. Template: templates/diagrams/interconnect-map.svg. 上半是拓扑,下半是每个视角各一条地址空间,中间那条虚线的落点就是这张图的结论:CPU 核用一条普通 store 就写得到斜纹那一段,指针可以直接递过去,不用 memcpy。两条带永不合并——同一块 DRAM 在 host 眼里是 0x80_0000_0000,在设备眼里是 0x18_0000_0000。段宽不按比例。模板:templates/diagrams/interconnect-map.svg
PROTOCOL LAYERING · PEER VIEW peer agreement · no wire the only real wire this transfer TRANSACTION LAYER TRANSACTION LAYER DATA LINK LAYER DATA LINK LAYER PHYSICAL · LOGICAL PHYSICAL · LOGICAL PHYSICAL · ELECTRICAL PHYSICAL · ELECTRICAL requester completer TLP generatorFlow control TLP parserFlow control Seq num + LCRCReplay buffer LCRC checkACK / NAK gen 128b/130b encodeScrambler Descrambler128b/130b decode TX driverRX equalizer RX equalizerTX driver builds header + payloadcredit based decodes headerreturns credits per packetholds until ACK drops on mismatchDLLP, never a TLP block syncremoves DC bias restores blockrecovers symbols differential pairCDR + de-emphasis CDR + de-emphasisdifferential pair TLP · end to end DLLP · hop by hop symbol stream no line here either the real one runs below PCIe lane ×4 · 32 GT/s 1 2 3 4 5 6 7 8
protocol layering · peer view协议分层 · 对等视角 The three grey dashed lines are agreements, not wires — nothing carries a TLP from one transaction layer straight to the other. The only solid horizontal line in the figure is the lane at the bottom. Follow ① to ⑧ : the bytes go down every layer on the requester, cross once, and climb every layer on the completer. That is why a protocol analyser taps the lane and never the transaction layer. Template: templates/diagrams/protocol-stack.svg. 上面三条灰虚线是约定,不是线 —— 没有任何东西把 TLP 从一侧的传输层直接送到另一侧。全图唯一一条横向实线,是最底下那根 lane。跟着 ①→⑧ 读:字节在发送侧一层层下去,过一次线,再在接收侧一层层上来。协议分析仪只能挂在 lane 上、挂不到传输层,原因就在这张图里。模板:templates/diagrams/protocol-stack.svg
ADDRESS MAP · TWO VIEWPOINTS not DRAM direct mapping reclaim · this remap PCIe MMIO · 64-bit DRAM · reclaimed DRAM · direct MMIO hole DRAM · direct BAR windows of every device the gigabyte that was shadowed 12 GiB PCI · LAPIC · IOAPIC · flash 3 GiB, legacy region at the bottom DRAM 4 – 16 GiB DRAM 3 – 4 GiB DRAM 0 – 3 GiB reachable at its own address shadowed by the hole — needs a remap reachable at its own address SYSTEM PHYSICAL DIMM PHYSICAL · 16 GiB TOUUD REMAPBASE TOLUD 0x40_0000_0000 0x4_4000_0000 0x4_0000_0000 0x1_0000_0000 0xC000_0000 0x0000_0000 TOM 16G 4G 3G 0x0 direct direct reclaim · same DRAM segment heights are not to scale · low addresses at the bottom
address map · two viewpoints地址映射 · 两个视角 Every boundary gets its own leader line, because a boundary is an address while a region is a range — write 4 GiB inside a region and three readings stay open (start, end, size). Symbol names sit in ink pills, literal constants in orange mono ones: TOLUD is a name, 0xC000_0000 is only what it happens to equal on this board. The orange line is the whole point: the gigabyte shadowed by the MMIO hole comes back above TOUUD — same DRAM, a second address. Heights are not to scale; low addresses at the bottom. Template: templates/diagrams/address-map.svg. 每条边界各拉一条引线,因为边界是一个地址、区域是一段范围 —— 把 4 GiB 写在某段中间,起点 / 终点 / 大小三种读法都成立。符号名走墨色药丸,字面常量走橙色等宽药丸:TOLUD 是名字,0xC000_0000 只是它在这块板上恰好等于多少。橙线是这张图的全部理由:被 MMIO 空洞盖住的那 1 GiB,在 TOUUD 之上重新露面 —— 同一块 DRAM,第二个门牌号。高度不按比例,低地址在下。模板:templates/diagrams/address-map.svg
GLYPH SHEET · COPY ONE <g> AT A TIME G-QUEUE finite depth, in order G-BYTESTREAM serialized bytes, not addresses G-SLOTS a place something plugs into G-PORTTAB an interface owned by this die G-DEVCARD pluggable board · model text, no logo G-ACCOUPLING AC coupling capacitor G-SYNC clock-domain crossing only G-HATCH a window onto another space out in TLP header + payload PCIe ×16 slots Host CPU die 64 core IMC 200 GbE NIC 2 × QSFP56 D+ D− sync clk A clk B BAR0 window
glyph sheet构件字形集 A rounded rectangle can stand for anything, so on its own it says nothing. Each glyph here is a noun with one fixed meaning: comb teeth promise a bounded in-order queue, ruler ticks promise serialized bytes, a tab straddling a boundary promises the interface belongs to that die. Draw one where the thing is not actually there and the figure states something false — worse than a plain box. Vendor logos stay out: model text keeps the file editable. Copy one <g> at a time. Template: templates/diagrams/glyphs.svg. 一个圆角矩形能代表任何东西,所以它单独出现时什么也没说。这里每个字形都是一个意义固定的名词:梳齿承诺"深度有限、按序进出",尺状刻度承诺"这是被序列化的字节",骑在边界上的小标签承诺"这个接口属于这块 die"。在没有那样东西的地方画上它,就是在图上写了一句假话 —— 比画个方框糟得多。厂商 logo 一律不进:写型号文字,文件才改得动。用的时候复制一个 <g>。模板:templates/diagrams/glyphs.svg
SPI mode 0 · CPOL=0 CPHA=0 MX25L6433F · JEDEC ID read command phase · MOSI drives data phase · MISO drives SCLK CS_N MOSI MISO 0x9F 0x00 0xC2 0x20 tCSS tSU ≥ 5 ns t0 t1 t2 t3 t4 t5 t6 t7 t8 data-valid window high-Z (not driven) sampling edge · SCLK rising CS_N · focus signal SCLK 25 MHz · bit period 40 ns
waveform · bus timing波形 · 总线时序 An SPI transaction the way a logic analyzer shows it: one lane per signal, the chip-select carries the orange focus, data cells hold real hex, and setup/hold arrows annotate the edges that matter. Template: templates/diagrams/hw-timing-waveform.svg. 逻辑分析仪视角的 SPI 传输:一信号一行,片选承担橙色焦点,数据格里是真实 hex,建立/保持箭头标注关键边沿。模板:templates/diagrams/hw-timing-waveform.svg
LINUX KERNEL · BUILD PIPELINE make ARCH=arm64 Image.gz dtbs make dtbs · runs in parallel .config + Kconfig gcc -c *.o ld vmlinux objcopy Image.gz *.dts dtc *.dtb mkimage FIT boot.itb build configuration compile per-TU object files ELF + symbols strip to binary gzip-compressed board source devicetree compiler flattened blob kernel + dtb pack bootable image 1 2 3 4 tool step artifact devicetree branch
build · pipeline编译 · 流程链 Kernel build from .config to bootable image: tools and artifacts alternate along the orange chain, the devicetree branch joins in gold, the deliverable gets the focus card. Template: templates/diagrams/build-pipeline.svg. 内核编译从 .config 到可启动镜像:工具与产物沿橙色主链交替,设备树分支以金色汇入,最终交付物用焦点卡。模板:templates/diagrams/build-pipeline.svg
SCHED · CFS RUN VIEW · 12 MS WINDOW trace-cmd record -e sched_switch -e sched_migrate_task CPU 0 CPU 1 CPU 2 IRQ eth0 rx app: render irq/eth0 idle preempted by irq/eth0 idle kworker/u8 idle kworker/u8 idle kworker/u8 idle migrate (load balance) idle app: render idle 0 2 4 6 8 10 12 ms irq/eth0 · threaded IRQ kworker/u8 · workqueue app: render · CFS task idle
scheduler · timeline调度 · 时间线 Three CPU lanes, ftrace-style: task blocks keep their hue across cores, the IRQ preemption gets the one orange marker, and the migration arrow shows the load balancer at work. Template: templates/diagrams/sched-timeline.svg. 三条 CPU 泳道,ftrace 风格:任务块跨核保持同色,IRQ 抢占是唯一的橙色标记,迁移箭头画出负载均衡的动作。模板:templates/diagrams/sched-timeline.svg
kfifo ring buffer struct kfifo · buf[16] · mask = size − 1 = 0x0F include/linux/kfifo.h · size must be a power of two out (tail) consumer reads in (head) producer writes 5A6B0D 319CE2 47 012 345 678 91011 121314 15 wrap: idx & (size − 1) kfifo_in(fifo, buf, len) copy to buf[in & mask] · smp_wmb() · in += len kfifo_out(fifo, buf, len) smp_rmb() · copy from buf[out & mask] · out += len len = in − out = 7 valid data free
algorithm · data structure算法 · 数据结构 A kfifo ring buffer as a flat array: occupied cells in tint, solid pointer markers for in/out, the wrap-around drawn as one quiet arrow with the mask trick spelled out. Template: templates/diagrams/algorithm-ringbuffer.svg. kfifo 环形缓冲画成直线阵列:占用格用 tint,in/out 用实心指针标记,回绕只画一条安静的箭头并写明掩码技巧。模板:templates/diagrams/algorithm-ringbuffer.svg
PHYSICAL DATA PATH · NO GPU · WHO ISSUES THE TRANSACTION, AND OVER WHICH WIRE pixel data · AXI config · APB SoC package · anything outside this line is a separate chip DDR4 SDRAM 4 GiB · off-package every framebuffer lives here, always DQ 32-bit · 1600 MT/s = 6.4 GB/s ceiling DDR ctrl + PHY multi-port · QoS p0 CPU p1 GPU p2 display p2 gets the highest QoS class scanout cannot be made to wait AXI NoC 128-bit 800 MHz CPU cluster AXI master 0 GPU AXI master 1 · next figure Display controller AXI master 2 · the DMA lives here fetch DMA · issues the reads FB base address register the only thing software sets line buffer · a few lines only DSI controller packs RGB into HS packets MIPI D-PHY 4 lanes · 1 Gbps LCD panel driver IC + source drivers no memory of a whole frame APB · 32-bit · register writes only 4 bytes per frame · never carries a pixel pixel interface 24-bit RGB · not AXI 1 2 3 4 5 ① one 32-bit register write over APB · ② the DMA then reads on its own · ③ served at the top QoS class ④ pixels leave on a non-AXI wire · ⑤ the D-PHY sends them off-chip config and data are different wires: 4 bytes one way, 8.3 MB a frame the other — setting a framebuffer is a register write, not a copy
hardware · physical data path硬件 · 物理数据通路 The display path with no GPU, drawn as a package cross-section: anything outside the dashed line is a separate chip. Config and data are deliberately different wires — a gold dashed APB carrying 4 bytes a frame, an orange solid AXI carrying 8.3 MB. The orange line enters memory at port p2, the one the DDR controller serves at the top QoS class, because scanout cannot be made to wait. Template: templates/diagrams/soc-dataflow.svg. 没有 GPU 的显示通路,画成封装剖面:虚线以外是另一颗芯片。配置和数据故意画成两根不同的线——金色虚线是 APB,每帧 4 个字节;橙色实线是 AXI,每帧 8.3 MB。橙线从 p2 口进内存,那是 DDR 控制器给最高优先级的一个口,因为扫描输出等不了。模板:templates/diagrams/soc-dataflow.svg
GPU DATA PATH · NOTHING IS EVER MOVED INTO THE GPU who issues the address register poke · APB display side CPU cluster · AXI master 0 L1 + L2 cache write-back CPU MMU virtual → physical it fills the command buffer, then writes one doorbell register. that is its whole part — it never touches a pixel again. flush the cache, or the GPU reads bytes that are still sitting in it GPU · AXI master 1 · drawn open shader core 0 shader core 1 shader core 2 shader core 3 tile buffer 16×16 px · 2 KiB L2 cache 256 KiB GPU MMU page tables live in DDR AXI master port one way in and out one 1080p RGBA frame = 8.3 MB. nothing on this die holds one — so the frame has to stay in DDR. command buffer 64 KiB 0x8000_0000 page tables 2 MiB 0x8001_0000 textures & meshes 48 MiB 0x8021_0000 fb A · front 8.3 MiB 0x8321_0000 fb B · back 8.3 MiB 0x8B21_0000 DDR · one physical address space, five tenants, 6.4 GB/s shared between them Display ctrl fetch DMA · master 2 reads fb A right now DSI + D-PHY 4 lanes 1 Gbps each LCD panel off-package glass at last a desktop card is the exception a discrete PCIe GPU has its own VRAM, so "upload the texture" really is a copy across the bus. on this SoC there is no VRAM — upload means another DDR address. 1 2 3 4 5 6 7 ① CPU fills the command buffer · ② one doorbell write · ③ the GPU MMU fetches its own page tables · ④ textures read in ⑤ tiles written out to fb B · ⑥ fence back to the CPU · ⑦ the display DMA reads fb A the whole time every arrow ends on the same DDR bar. the GPU is not a place data goes — it is a second master issuing addresses into it.
hardware · where the GPU actually sits硬件 · GPU 到底在哪一环 The same DDR with one more bus master. The GPU is drawn open so its tile buffer (2 KiB) and L2 (256 KiB) can be read against one 8.3 MB frame — there is nowhere inside to put it. All seven badges land on the same address bar, which is the whole argument: the GPU is not a place data goes, it is a second master issuing addresses into memory. Template: templates/diagrams/gpu-dataflow.svg. 同一块 DDR,多一个总线主设备。GPU 画成敞开的,好让人把它的 tile buffer(2 KiB)和 L2(256 KiB)跟一帧 8.3 MB 放在一起看——里面根本没地方装。七个徽章全部落在同一条地址条上,这就是整张图要说的:GPU 不是数据去的地方,它是第二个往内存里发地址的主设备。模板:templates/diagrams/gpu-dataflow.svg
DISCRETE CARD · TWO MEMORIES, ONE WIRE · HERE THE COPY IS REAL who issues the transfer on-card traffic display side HOST · motherboard CPU + system MMU decodes, then hands over SYSTEM MEMORY · DDR on the board decoded image · ordinary pages TTM_PL_SYSTEM · the card cannot reach this the same pages, now GART-mapped AMDGPU_GEM_DOMAIN_GTT · readable over the link pin + dma_map_sgtable() that step writes a mapping entry. not one byte has moved yet. the CPU could also write into the BAR window itself, but it is small and uncached — drivers use the engine for anything bulky. PCIe the only wire GRAPHICS CARD · its own board, its own memory GPU DIE SDMA copy engine it does the upload shader array renders L2 cache not a frame display engine VRAM · a second physical address space textures uploaded once fb · back being drawn fb · front scanned out now once a byte is here it stays — shaders and scanout read it without crossing PCIe CPU-visible window · the PCIe BAR visible_vram_size · usually far smaller than the VRAM to the monitor DisplayPort · off-card 1 2 3 4 5 6 ① an app decodes into ordinary system memory · ② the driver pins it and maps it through GART · ③ the card’s SDMA engine reads it over PCIe and writes VRAM ④ the shaders draw into the back buffer · ⑤ the display engine reads the front buffer · ⑥ the CPU can only peek at VRAM through the BAR window two address spaces, one wire. here “upload” is literal — and it is still the card, not the CPU, that issues the reads.
hardware · when there really are two memories硬件 · 真有两块内存的时候 The counterpart to the figure above: a desktop card with its own VRAM, so there are two address bars and one link between them, and the copy is real. Read who performs it — badge ③ is the card’s own SDMA engine reading host memory over PCIe, not the CPU pushing bytes out. Badge ② is the subtle one: pinning the pages and mapping them through GART makes them reachable without moving a byte, which is why the two rows on the left hold the same pages. Every symbol on the figure is a real mainline name. Template: templates/diagrams/vram-dataflow.svg. 上一张图的对照:台式机显卡有自己的显存,于是有两条地址条、中间一根线,拷贝是真的。看清是谁在搬——徽章 ③ 是显卡自己的 SDMA 引擎在通过 PCIe 读主机内存,不是 CPU 把字节推出去。徽章 ② 那步最容易看漏:把页面锁住不让换出、再通过 GART 映射,就让它们变得可读,而一个字节都没搬——这也是左边两排装的是同一批页面的原因。图上每个符号名都是主线内核里的真名。模板:templates/diagrams/vram-dataflow.svg
GLYPH SHEET 2 · MEMORY & ADDRESS · COPY ONE <g> AT A TIME G-ADDRBAR a span of address space, named G-WINDOW a view onto another space, not storage G-PAGEGRID one cell per page, colour is state G-COPYBLOCK the one place bytes actually move G-DIMM a memory module you could hold G-PANEL glass + driver IC + flex cable G-LINKPILL names the interface a line carries G-SIGNCARD the figure states what it is DRAM MMIO hole 0xC000_0000 0xE000_0000 DRAM window DRAM no storage of its own a read here lands in the other space free used cold hot src dst COPY 8.3 MB leave it out and the figure says nothing moved 8 GiB notch + fingers say “off-package, replaceable” active area driver IC FPC no frame of memory lives in here SoC DDR LPDDR4 x32 the wire is not the label — say which bus Display data path a figure that names itself survives being copied out of its page
glyph sheet 2 · memory & address构件表 2 · 内存与地址 The second sheet: how memory and addresses are drawn. An address bar names a span and hangs its boundary values outside on black pills, because a value belongs to a boundary, not to a region. A hatched band is a window — it stores nothing, and a read there lands in another space. A page grid gives one cell per page so state becomes a pattern you can see at a glance. And the orange COPY block is the one thing on this sheet that is a claim rather than a shape: draw it and you are saying bytes really moved. Leave it out and the figure says they did not. Template: templates/diagrams/glyphs-memory.svg. 第二张构件表,管的是内存和地址怎么画。地址条给一段空间命名,边界值用黑药丸挂在条外——值属于边界,不属于哪一段。斜纹带是一扇窗,它不存东西,往那儿读会落到另一个空间去。页帧阵列一格一页,状态于是变成一眼看得见的图案。橙色 COPY 块是这张表上唯一一个「说了一句话」而不只是「一个形状」的构件:画上它就等于断言字节真的动了;不画,就等于说没动。模板:templates/diagrams/glyphs-memory.svg
PLATFORM BLOCK · ONE BOARD · WHAT THE CHIP TALKS TO, AND OVER WHICH INTERFACE SoC package Application processor these four blocks face outward memory ctrl multi-port display ctrl the fetch DMA low-speed IO I2C / PWM DSI TX packs + sends memory · off-package 4 GiB LPDDR4 every framebuffer lives here 6.4 GB/s, shared by every master LPDDR4 x32 display · off-package 1080 x 1920 driver IC no frame of memory in here it must be fed on time, every frame MIPI DSI x4 storage eMMC boot + rootfs SPI NOR bootloader HS200 QSPI sensors & control touch ctrl gestures backlight brightness PMIC rails I2C PWM I2C 1 2 3 4 ① the only wire a pixel travels on the way in · ② the only wire it travels on the way out · ③ boot code, never pixels ④ control traffic — bytes per second, not megabytes. the pill on each link is the part that carries information; the line itself carries none Platform block · one board
hardware · one board, and what it talks to硬件 · 这块板子跟外面怎么连 The board-level counterpart to soc-block: not what is inside the chip, but what the chip talks to and over which interface. The DRAM and the panel are drawn as the parts they are — a green module with gold fingers and a notch, a sheet of glass with a driver IC and a flex cable — because a labelled rectangle makes you read before you recognise. Every link carries a black pill naming the interface, which is the part that carries information; the line itself carries none. Badges separate the two wires a pixel actually travels from the ones that only ever carry boot code or control bytes. Template: templates/diagrams/platform-block.svg. soc-block 的板级对应:那张画片内有什么,这张画芯片跟外面的什么器件相连、走哪种接口。内存和屏按真实外形画——绿色模组带金手指和缺口,一片玻璃带驱动 IC 和排线——因为标了字的方框要先读才认得出。每条连线上骑一个黑药丸写接口名,那才是带信息的部分,线本身不带。编号把像素真正走的那两根线,跟只走引导代码或控制字节的线分开。模板:templates/diagrams/platform-block.svg
ADDRESS SPACES · THE SAME BYTES, THREE DIFFERENT ADDRESSES process space system space device space .text read-only mapped buffer the one we follow heap 0x0055_0000 0x0055_F000 DRAM DRAM registers MMIO device window 0x8020_0000 local memory on the device local memory 0x0100_0000 host window CPU MMU page tables in DRAM device MMU its own page tables, also in DRAM 1 2 3 ① one buffer, seen by the process · ② the same bytes in physical memory · ③ and again, under the address the device must use a hatched band stores nothing — a read there lands in the space below. a translation box is where an address changes meaning. so a pointer alone is never enough: it is only meaningful together with the space it came from. Address spaces · three views
memory · the same bytes, three addresses内存 · 同一批字节,三个地址 address-map draws one space; this draws several, stacked, with dashed leaders joining the same block of content where it appears in each. That stacking is the whole point: “the device sees a different address” is impossible to show on one bar. A translation box sits between each pair of layers and names who does the translating. The closing line is the one to keep: a pointer alone is never enough, because it is only meaningful together with the space it came from. Template: templates/diagrams/address-spaces.svg. address-map 画一个空间,这张画好几个空间叠起来,用竖虚线把同一块内容在各层的位置连上。叠起来正是关键:「设备看到的地址不一样」这件事,在一条地址条上根本画不出来。每两层之间放一个翻译盒,写清是谁做的翻译。要记住的是图脚那句:光有一个指针永远不够,它只有连同它所属的那个空间一起说,才有意义。模板:templates/diagrams/address-spaces.svg
COPY VS SHARE · ONE DIFFERENCE, DRAWN TWICE producer writes the frame consumer reads the frame other frame A written here frame A′ the second copy one address bar COPY 8.3 MB the bar now holds the same picture twice someone paid 8.3 MB of bandwidth to put it there COPYING producer writes the frame consumer reads the frame other frame A the only one other one address bar both arrows land on the same region only a handle changed hands — no orange block anywhere SHARING 1 2 ① bytes move here, and only here · ② nothing moves; the two sides simply agree on an address both halves use identical coordinates on purpose, so the one difference is the only thing your eye has to find. if a figure like this has no orange block, then nothing was copied — whatever the prose around it says. Copy vs share · the one difference
memory · did the bytes actually move内存 · 字节到底动没动 Two halves on identical coordinates, differing in exactly one thing. In the upper half an orange COPY block sits between two regions of the bar and the picture now exists twice; in the lower half both arrows land on the same region and nothing orange appears anywhere. The reason to draw it this way is that prose cannot settle the question — “hand it over”, “send it”, “upload it” all fit either case. A reader who learns this figure gets a test they can apply to any other one: no orange block, no copy. Template: templates/diagrams/copy-vs-share.svg. 上下两半用完全相同的坐标,只差一处。上半在地址条的两段之间放了一个橙色 COPY 块,于是同一张图存了两遍;下半两条箭头落在同一段上,全图找不到一点橙色。之所以要这么画,是因为文字定不了这件事——「交给它」「发过去」「上传」对两种情况都说得通。读者学会这张图,就拿到了一个能用在别处的判断依据:没有橙块,就没有拷贝。模板:templates/diagrams/copy-vs-share.svg
ANIMATED DATA PATH · A LINE THAT FLOWS IS ONE THAT NEVER STOPS flows — walked every frame still — fires once CPU writes one register APB · 4 bytes / frame other framebuffer 8.3 MB other DRAM display controller FB base reg fetch DMA DSI TX packs the glass driver IC AXI 24-bit RGB MIPI x4 1 2 3 4 ② is the only step software takes, and it happens once per frame. ① ③ ④ never stop while the screen is on — that is what the motion is saying. the motion is not decoration: a flowing line means the hardware walks that path continuously, a still line means one transaction and then nothing. it is CSS, not SMIL, so it halts under prefers-reduced-motion, under html[data-motion-freeze], and in every screenshot — captures stay identical run to run. Animated data path
hardware · the only figure here that moves硬件 · 这里唯一一张会动的图 The motion carries a fact, which is the only reason it is allowed. A line that flows is a path the hardware walks continuously — every frame, every line, for as long as the screen is on. A line that stays still fires once and then nothing: badge ② is the single register write software performs per frame, and it is deliberately the one arrow that does not move. A static figure cannot make that distinction; both would be an arrow with a head on it. The animation is CSS rather than SMIL on purpose, because only CSS honours prefers-reduced-motion — so it halts for readers who ask for less motion, halts under html[data-motion-freeze], and halts in every screenshot, which keeps captures byte-identical between runs. All three were tested, not assumed. Template: templates/diagrams/dataflow-animated.svg. 这张图动,是因为动作本身带着一条信息——只有这种情况才允许动。流动的线是硬件一直在走的通路:每一帧、每一行,只要屏亮着就没停过。静止的线则是发生一次就完了:徽章 ② 是软件每帧唯一的那次寄存器写,它被刻意画成全图唯一不动的箭头。静态图说不出这个区别——两者都只是一根带箭头的线。动画用 CSS 写而不用 SMIL 也是刻意的,因为只有 CSS 认 prefers-reduced-motion:读者要求减少动效时它会停,页面加 html[data-motion-freeze] 时会停,截图时也会停,于是每次截出来的图逐字节相同。这三条都实测过,不是想当然。模板:templates/diagrams/dataflow-animated.svg
PAGE FLIP · AN ADDRESS CHANGES, A FRAME DOES NOT FB base register 0x8321_0000 BEFORE fb A front · scanned out fb B back · being drawn the DMA reads from here the GPU is drawing into this one vsync the register latches here — not the moment software wrote it. that one rule is what keeps half an old frame off the glass. FB base register 0x8B21_0000 AFTER fb A back · being drawn fb B front · scanned out the DMA reads from here the GPU is drawing into this one 1 2 3 the bar is byte-identical in both halves. two buffers, same places, same sizes, nothing copied. ① the register named fb A · ② at vsync the hardware took the new value · ③ now it names fb B. four bytes changed. this is why “swap the buffers” costs nothing and “copy the frame” costs 8.3 MB — they are not two names for one operation. and it is why the latch is tied to vsync: let the address change mid-scan and the panel receives the top of one frame with the bottom of the next. the blue line flows because scanout never stops reading — what the flip changes is only where it reads from. Page flip · four bytes
hardware · a flip is four bytes硬件 · 翻页只是四个字节 The same arrangement twice, above and below a vsync marker. The memory bar is byte-identical in both halves — two buffers, same places, same sizes. What changes is the value in one register and, because of that, where the flowing blue line turns down. That turn moving right is the entire page flip. The line flows because scanout never stops reading; the flip changes only where it reads from. Drawing the two halves on identical coordinates is deliberate: it leaves your eye exactly one difference to find, which is the honest size of what happened. Template: templates/diagrams/page-flip.svg. 同一张底图画两遍,中间隔着 vsync。两半的地址条逐字节相同——两块缓冲,位置一样、大小一样。变的只有寄存器里的值,以及那条蓝色流动线拐弯的位置。拐点右移,就是整个「翻页」。线在流,是因为扫描输出从来没停过读;翻页改的只是它从哪儿读。两半用完全相同的坐标是刻意的:只留一处差别给眼睛找,而那一处差别的大小,就是这件事真实的大小。模板:templates/diagrams/page-flip.svg
WHO READS, WHO WRITES · EVERY LINK HAS A DIRECTION one-way read one-way write two-way CPU cluster fills commands, rings reads and writes GPU · drawn open shaders tile buffer 2 KiB L2 256 KiB a frame is 8.3 MB — neither of those can hold one commands 64 KiB page tables 2 MiB textures 48 MiB fb A · front 8.3 MiB fb B · back 8.3 MiB 0x8321_0000 one physical address space · 6.4 GB/s shared display ctrl fetch DMA DSI TX the glass driver IC reads textures writes tiles into fb B reads fb A — never writes no arrow goes from one master to another. nothing is ever handed over — they only meet at the same addresses. the two-way links are two lines on purpose: dashes on one line can only travel one way, so a single double-headed arrow would say “direction unknown”. read the arrowheads and you have the answer to who copies from whom — here, nobody does. One memory, many masters
hardware · who reads, who writes硬件 · 谁在读,谁在写 Every link is a flowing dashed line whose dashes travel the way the data does, so direction stops being something you have to read and becomes something you can see. Two-way links are drawn as two parallel lines going opposite ways rather than one double-headed arrow, because dashes on a single line can only travel one way — a double head would say “direction unknown” at exactly the place ambiguity does damage. Follow the arrowheads and no line crosses from one master to another: nothing is handed over, they only meet at the same addresses. Template: templates/diagrams/gpu-memory-flow.svg. 每条连线都是会流动的虚线,虚线段朝数据走的方向走——于是「方向」不再是要读出来的东西,而是看得见的东西。两头都传的连线画成上下两条反向流动,而不是一条双箭头线:一条线上的虚线只能朝一个方向走,画成双箭头等于在最容易误解的地方写「方向不明」。顺着箭头看,没有一条线从一个主设备连到另一个主设备——没有谁把东西交给谁,它们只是在同一批地址上碰面。模板:templates/diagrams/gpu-memory-flow.svg
DISCRETE CARD · WHO PULLS FROM WHOM requests go this way data comes back host CPU sets it up, then stops SYSTEM MEMORY other image pinned other pinned + mapped so the card can reach it — the pages never move PCIe · the only wire COPY 48 MiB once the card issues the reads — this is a pull not the CPU pushing bytes out graphics card · its own board copy engine it does this shaders display engine VRAM · a second address space textures 48 MiB fb · back fb · front once a byte is here it never crosses PCIe again to the monitor whoever needs the data issues the reads. that rule did not change — only the number of memories did. 1 2 3 ① the copy engine on the card sends read requests across the link · ② the data comes back and lands in VRAM · ③ and stays there. drawing the link as two opposite lines is what makes “pull” visible; one double-headed arrow would have left it ambiguous, and ambiguous is exactly where the misunderstanding lives. Discrete card · a pull, not a push
hardware · a pull, not a push硬件 · 是拉,不是推 The discrete-card case, drawn so the direction of the copy cannot be misread. The link is two opposite flowing lines: requests travelling from the card to host memory, data travelling back. Because the requests start on the card, the copy is a pull — the initiator is the card's own copy engine, not the processor. That is the same rule as on a system on chip: whoever needs the data issues the reads. Only the number of memories changed. One double-headed arrow would have left this ambiguous, and ambiguous is exactly where the misunderstanding lives. Template: templates/diagrams/vram-copy-flow.svg. 独立显卡那种情况,画成方向不会读错的样子。那根线画成两条反向流动的:请求从显卡去主机内存,数据反向回来。请求发起在显卡这边,所以这次拷贝是不是推——发起方是显卡自己的搬运引擎,不是处理器。这跟片上系统是同一条规则:谁要数据谁发读请求,变的只是内存的块数。画成一条双箭头线就会含糊,而含糊正是误解住的地方。模板:templates/diagrams/vram-copy-flow.svg
ONE FRAME · TEN STOPS ON A PHONE SOC pixels being written pixels being read ①–⑤ · THE WRITE SIDE · the GPU renders one frame into memory shader cores they compute pixels tile buffer 16 KiB on-chip GPU MMU virtual → physical interconnect NoC · arbitration memory ctrl queues + refresh 1 2 3 4 5 GPU · one IP, three parts on-chip AXI 128-bit AXI 128-bit DFI CPU cluster runs the compositor APB 32-bit 4 bytes per frame, to the register at stop ⑧. this is the only thing software does. no pixel travels here. 8.3 MB per frame off-chip · DRAM front buffer the display reads this back buffer the GPU writes this textures source art page tables the GPU's other 6 LPDDR4X · the only place in the system where a whole frame exists back on-chip ⑦–⑩ · THE READ SIDE · the display controller pulls it out again, and never stops fetch DMA reads in scanline order blend + timing composes, makes vsync MIPI DSI packetises D-PHY 4 lanes, serial 7 8 9 display controller · VOP / DPU serial link out of the chip 16 lines only 24-bit RGB packets 10 panel the frame never entered the GPU and never entered the display controller. both of them reached into the same DRAM. every box above is a real block with a driver in mainline Linux. the two that hold no frame are the ones people assume do: the GPU, whose tile buffer is 16 KiB, and the display controller, whose line buffer is 16 lines deep (rockchip_drm_vop2.c:500). One frame · ten stops
hardware · one frame, ten stops硬件 · 一帧,十站 The whole journey on a phone-class ARM64 chip, drawn as two rows with the memory between them. Everything above writes into that bar, everything below reads out of it, and no arrow goes from one block straight to another. Drawing memory as a shared spine rather than a stop in a line is the point: blocks do not hand frames to each other, they take turns touching the same addresses. Every link carries its bus type and how many bytes it moves per frame. Stop ⑥ is the memory bar and the only stop that holds a whole frame; ①–⑤ above it all write into it, ⑦–⑩ below it all read out. Template: templates/diagrams/arm64-display-path.svg. 一颗 ARM64 手机芯片上一帧的全程,画成上下两行加中间一条内存。上面的往里写,下面的往外读,没有一根箭头从一个模块直接连到另一个模块。把内存画成横贯全图的一条、而不是流水线上的一站,正是这张图的用意:模块之间不传帧,它们只是轮流去碰同一批地址。每根线都标了总线类型和每帧多少字节。停 ⑥ 是那条内存,也是全程唯一装得下一整帧的地方;上面的 ①—⑤ 都在往里写,下面的 ⑦—⑩ 都在往外读。模板:templates/diagrams/arm64-display-path.svg
WHAT A FRAME IS · AND WHY IT DOES NOT FIT one frame · a full screen of pixels 1080 × 2400 pixels one pixel R G B A 4 bytes nothing here is compressed 1080 × 2400 × 4 = 9.89 MiB, once and there are 60 of them every second THE SAME RULER · one frame, then every on-chip memory drawn to that scale one frame · 9.89 MiB GPU L2 cache 512 KiB — 33 px on this ruler display line buffer 16 lines · 128 KiB — 8 px on this ruler GPU tile buffer 16 KiB — 1 px on this ruler the same three, magnified 12× so they can be seen at all GPU L2 cache display line buffer GPU tile buffer no memory inside the chip is within a hundred times of holding one frame. that is the whole reason the rest of this works the way it does. the largest on-chip memory anywhere in the display path is 53 times too small. on-chip SRAM costs tens of times more silicon area per bit than DRAM, so a chip that could hold a frame would be a chip nobody could afford to buy. the line buffer figure is from rockchip_drm_vop2.c:500 — “a Cluster window has 2048 x 16 line buffer”. sixteen lines, not one frame. A frame · 9.89 MiB, nowhere to put it
hardware · one ruler for all of them硬件 · 同一把尺子量到底 A size argument made visible instead of asserted. One frame becomes a 660-pixel ruler, and every on-chip memory is then drawn on that same ruler: the L2 cache is 33 pixels, the display line buffer is 8, the GPU tile buffer is 1. A magnified strip below repeats the three at 12× so they can be read at all. A table of the same numbers would let the reader nod and move on; the ruler does not. Template: templates/diagrams/what-is-a-frame.svg. 把一个关于大小的论证画出来而不是说出来。一帧变成一把 660 像素的尺子,片上每一块存储再按同一比例画在下面:L2 是 33 像素,显示控制器的行缓冲 8 像素,GPU 的 tile 缓冲 1 像素。下面一条把这三个放大 12 倍,否则根本看不见。同样这些数字列成表格,读者点点头就翻过去了;尺子不给这个机会。模板:templates/diagrams/what-is-a-frame.svg
TILING · HOW A GPU DRAWS A FRAME IT CANNOT HOLD the tile buffer holds 16 KiB and a frame is 9.89 MiB. so the GPU never works on a frame. it works on one 16×16 tile at a time, and there are 10 125 of them. the screen, as the GPU sees it done now waiting 10 125 tiles · 16×16 pixels each 1 inside the chip · 16 KiB of tile buffer rasterise which pixels does this triangle touch 2 depth test is it behind something already here 3 blend mix it with what is here 4 all of it on-chip. zero memory traffic so far. once write to DRAM 4 KiB, one burst 5 and only now does this tile exist outside the chip THE ALTERNATIVE · immediate mode, which is what a desktop card does every layer of overdraw is a read-modify-write of external memory. three layers deep, that is six memory accesses per pixel instead of one write. it is the right trade when memory bandwidth is yours alone; on a phone it is shared with five other blocks. tiling is a bandwidth decision, not a compute decision. that is why it shows up on phones first and why the tile buffer is small on purpose: it has to fit in the power and area budget of something in your pocket. the depth and blend work above happens at full rate inside the chip, and DRAM never sees any of it — which is the same shape of answer as the display controller blending layers on the way past. Tiling · 16 KiB at a time
hardware · tiling, 16 KiB at a time硬件 · 分块,一次 16 KiB How a GPU draws a frame it cannot hold. The screen is 10 125 tiles; one tile is rasterised, depth tested and blended to completion inside the on-chip tile buffer, and only the finished tile is written out. The comparison underneath is immediate mode, where three layers of overdraw cost six external accesses per pixel. Tiling is a bandwidth decision, not a compute one, which is why it appeared on phones first. Steps ②, ③ and ④ all happen on-chip; ⑤ is the only one that touches memory. Template: templates/diagrams/gpu-tile-render.svg. GPU 怎么画一帧它装不下的东西。屏幕是 10 125 个小格,一格的光栅化、深度测试、混合全在片上的 tile 缓冲里做完,只有做完的那一格才写出去。下面对比的是立即模式:三层重叠就是每像素六次外部访存。分块是个带宽决策不是算力决策——这也是它先出现在手机上的原因。图里 ②③④ 三步全在片上做完,只有 ⑤ 碰了一次内存——这一格的全部访存就是那一次。模板:templates/diagrams/gpu-tile-render.svg
INSIDE THE DISPLAY CONTROLLER · WHERE COMPOSITING ACTUALLY HAPPENS a phone screen is never one image. it is four, and something has to add them up. the surprise is where that happens: not in the GPU, and not in memory. status bar 1080×90 app window 1080×2100 video decoder output cursor 96×96 other DRAM · four separate buffers, four separate addresses Cluster 0 fetch DMA + 16-line buffer 1 Cluster 1 fetch DMA + 16-line buffer 2 Esmart 0 fetch DMA + 16-line buffer 3 Esmart 1 fetch DMA + 16-line buffer 4 Smart 0 idle not needed here Smart 1 idle not needed here six hardware windows · each one reads memory by itself layer select · 1 from 6 OVERLAY · blends N of the 6 layers alpha, z-order, colour keys this is the compositor, and it is a piece of silicon 7 the alternative GPU composites into a fifth buffer instead +1.2 GB/s of pure memory traffic VIDEO PORT · timing generator makes hsync, vsync and data enable 8 MIPI DSI HDMI eDP LVDS one gets picked the blended result is never written back to memory. it goes straight out of the chip as a pixel stream. structure follows the block diagram the vendor put in the driver itself (rockchip_drm_vop2.c:41–68). the sixteen-line buffer is from line 500 of the same file. this is why a phone can show video under a translucent status bar at 60 Hz without the GPU waking up at all: the layers were never merged into one image, they were added together on the way past.
hardware · where compositing happens硬件 · 合成到底在哪儿发生 Six hardware windows each pull their own layer out of DRAM with their own fetch DMA; a selector routes any of them to any layer slot; one overlay blends them on the way past. The blended result is never written back — it leaves the chip as a pixel stream. Structure follows the block diagram the vendor put in the driver's own header comment, which is a better source than reasoning about what a display controller probably contains. Template: templates/diagrams/display-controller-inside.svg. 六个硬件窗口各用自己的取数 DMA 从内存里拉自己那一层;选择器可以把任一层送到任一个槽;一个混合器在像素路过时把它们叠好。叠好的结果一个字节都没回内存,直接以像素流出芯片。结构照的是厂商自己写进驱动头部注释的那张框图——这比我推测「显示控制器里大概有什么」要可靠得多。模板:templates/diagrams/display-controller-inside.svg
FRONT AND BACK ARE ROLES, NOT ADDRESSES display is reading it → we call it the FRONT buffer GPU is writing it → we call it the BACK buffer two blocks of DRAM. their addresses never change. what changes is which one each name is pointing at right now. block A 0x8000_0000 block B 0x8080_0000 frame N BACK buffer being drawn into FRONT buffer being read out 0x8000_0000 frame buffer base address register frame N+1 FRONT buffer being read out BACK buffer being drawn into 0x8080_0000 frame buffer base address register frame N+2 BACK buffer being drawn into FRONT buffer being read out 0x8000_0000 frame buffer base address register vsync vsync ↑ one 32-bit register write. that is the entire page flip. nothing was copied, moved or renamed. one register took a different value, and the two roles changed places. read the three columns across and the two rectangles never move: same x, same y, same address, same size. only their colour alternates. that is what makes the words confusing — “front” and “back” sound like places, and they are not. they are two jobs that two blocks of memory take turns doing. on this hardware the register is VOP2_WIN_YRGB_MST (rockchip_drm_vop2.c:1370), and it takes effect at the next vsync rather than when software writes it — let the address change mid-scan and the panel gets the top of one frame with the bottom of another, which is exactly what tearing is. Front and back · two jobs, taking turns
hardware · front and back are roles硬件 · 前和后是角色 Three frames side by side with the same two rectangles at identical coordinates in every column. The addresses are printed once at the head of each row rather than in every column, which is itself the argument: all three columns are the same two blocks of memory. Only the colours alternate. Drawing them at identical coordinates leaves the reader exactly one difference to find, and it is a role, not a position. Template: templates/diagrams/buffer-roles.svg. 三帧并排,两个矩形在每一列都画在完全相同的坐标上。地址只在行首标一次而不是每列一份,这件事本身就是论点:三列画的是同两块内存。变的只有颜色。坐标不动是刻意的——它只留一处差别给眼睛找,而那处差别是角色,不是位置。模板:templates/diagrams/buffer-roles.svg
OUT OF THE CHIP AND INTO THE GLASS this is the one place in the whole path where the signal actually changes form. parallel inside the chip → serial on the cable → parallel again inside the panel. stored nowhere along the way. inside the silicon video port one pixel per clock 1 24 data wires + hsync, vsync, DE parallel MIPI DSI controller one packet per line 2 adds ECC and checksum per packet D-PHY serialiser 3 1.5 Gbit/s per lane lane 0 lane 1 lane 2 lane 3 clock off-chip · down the flex cable the panel · a separate component driver IC deserialises, then drives 4 TE · the panel answers back source driver · 3240 outputs · one whole row at once 5 gate driver 2400 6 the source driver holds one row of colours; the gate driver picks which row gets it. 2400 rows, 60 times a second. the only line in this figure that runs backwards is the one the panel uses to say “I have just finished a refresh”. that line is the tearing effect signal, turned on with the DCS command SET_TEAR_ON, 0x35 (include/video/mipi_display.h:115, issued at drm_mipi_dsi.c:1380). without it a command-mode panel has no way to know when writing is safe. lane count is not fixed by the standard — each panel declares its own (include/drm/drm_mipi_dsi.h:192), and four is simply what a 1080p 60 Hz phone needs.
hardware · out of the chip, into the glass硬件 · 出芯片,进玻璃 The one stage where the signal's form actually changes: 24 parallel wires inside the chip, a serial bit stream on four differential lanes down the flex cable, then parallel again inside the panel where a source driver holds one whole row of subpixels and a gate driver picks which of 2400 rows receives it. One line runs backwards — the tearing effect signal, the panel telling the chip it has just finished a refresh. Read ①②③ as the serialising half, ④ as the chip inside the panel, and ⑤⑥ as the two drivers that address the glass. Template: templates/diagrams/dsi-panel-inside.svg. 整条通路上唯一一处信号形态真的变了的地方:片内是 24 根并行线,出芯片是四对差分线上的串行比特,进屏又变回并行——源极驱动握着一整行子像素,栅极驱动决定 2400 行里哪一行接收它。只有一根线是朝回走的:TE 信号,屏反过来告诉芯片「我刚扫完一遍」。顺 ①②③ 看是串行化,④ 是屏里那颗把包解回并行的芯片,⑤⑥ 才是真正去点亮玻璃的两组驱动。模板:templates/diagrams/dsi-panel-inside.svg
SIX TENANTS, ONE MEMORY BUS sharing one DRAM removed the copies. what it did not remove is the queue. every block on the chip asks the same memory for bandwidth, and there is not enough for everyone at once. display controller 1.2 GB/s hard real time · cannot be late GPU 2.4 GB/s can drop a frame and catch up camera ISP 0.9 GB/s only while the camera is open video codec 0.7 GB/s only while something is playing CPU cluster 0.6 GB/s bursty, small 6.4 GB/s — everything the DRAM can deliver 5.8 GB/s asked for, 6.4 available. one more tenant and somebody waits. THE MEMORY CONTROLLER DOES NOT SERVE THEM IN THE ORDER THEY ASKED request queue finite depth, reordered deep enough to hide a row miss, no more 1 served by consequence, not by arrival the display port is picked first, every time 2 if the GPU is served late one frame is dropped. the next one catches up. nobody outside the phone can tell. if scanout is served late the 16-line buffer empties and the pixel clock does not wait. a band appears across the screen, in that frame, visibly. the two kinds of lateness differ by an order of magnitude in consequence, so the priorities differ too. this is also the answer to “why did adding a camera preview make the display stutter” — nothing in the display path changed; a sixth tenant moved in.
hardware · six tenants, one bus硬件 · 六个租户,一条总线 The price of sharing one memory, which every other figure in this set treats as free. Six requesters on a common bandwidth scale, a request queue of finite depth, and a memory controller that serves by consequence of lateness rather than by arrival. The asymmetry is the point: a late GPU drops a frame nobody notices, a late scanout empties a 16-line buffer while the pixel clock keeps running. Template: templates/diagrams/bus-tenants.svg. 共用一块内存的代价——这一组里其他每张图都把它当成免费的。六个主设备按同一把带宽尺子排开,一条深度有限的请求队列,一个按误了会有什么后果而不是按到达顺序服务的内存控制器。不对称正是重点:GPU 晚了掉一帧没人看得出来,扫描输出晚了行缓冲会空,而像素时钟不会等。模板:templates/diagrams/bus-tenants.svg
WHERE EACH WORD LIVES the words in the table above are not all the same kind of word. most of them name a place. four of them name a moment, and mixing the two is what makes this hard to follow. GPU draws it DRAM holds it display controller reads it out MIPI DSI + D-PHY ships it panel lights it tile-based rendering bus master frame framebuffer front buffer back buffer scanout line buffer fetch DMA blending APB · registers AXI · pixels TE signal each of these names a piece of hardware, or a range of addresses inside one. you can point at it. vsync the gap between two frames page flip one register write, at that gap tearing what you see if it lands late underflow what you see if the fetch is late these four are not in any box above. they are things that happen at an instant — which is why looking for them on a block diagram never works.
hardware · where each word lives硬件 · 每个词住在哪儿 A map for a glossary. Terms hang under the piece of hardware they belong to, and four of them hang under nothing at all — vsync, page flip, tearing and underflow are moments rather than places. Separating those out is the whole reason the figure exists: looking for a moment on a block diagram is a good way to stay confused for a long time. Template: templates/diagrams/display-vocabulary.svg. 术语表的地图。每个词挂在它所属的那个硬件下面,而有四个词底下什么都不挂——vsync、翻页、撕裂、欠载 是时刻不是地方。把这四个单拎出来正是这张图存在的理由:在框图上找一个时刻,是能把自己困住很久的一种找法。模板:templates/diagrams/display-vocabulary.svg
WHEN IT BREAKS · WHICH STOP TO START AT the same eight figures, read backwards: a symptom, and where on the path it comes from. THE SYMPTOM WHAT IT ACTUALLY IS START HERE DO NOT START HERE tearing the flip landed mid-scan figure 05 when the base register takes effect the panel it received exactly what it was sent a band, or a flash underflow — the line buffer ran dry figure 07 who else is using bandwidth the DSI registers DSI is further down than the fault frozen image, no crash the base address stopped being updated figure 01 the flip path in the display driver the GPU it may be drawing perfectly wrong layer order the overlay's layer selection figure 04 window and layer config what the application drew the last column is worth more than the first three. the usual waste is starting at the end of the path, and the fault is almost never there.
hardware · which stop to start at硬件 · 该从哪一站查起 The same set of figures read backwards, as a debugging order. Each row has the same shape: a symptom, the mechanism it is actually reporting, the stop to look at first, and the place not to start. The fourth column is worth more than the other three — display debugging is usually wasted at the far end of the path, because the last registers are the easiest to read and the least likely to be wrong. Template: templates/diagrams/display-triage.svg. 把同一组图倒过来读,变成一个排查顺序。每一行形状相同:症状、它其实是哪个机制在报警、先查哪一站、别先查哪里。第四列比前三列值钱——查显示问题最常见的浪费是从通路最末端开始,因为最后那几个寄存器最好读,而它们恰恰最不可能出错。模板:templates/diagrams/display-triage.svg
CROSS-SECTION · WHAT IS TOUCHING WHAT, AND HOW THICK PLAN VIEW · WHERE THE CUT IS TAKEN active area A A the arrows say which way you are looking — a section line without them is ambiguous SECTION A—A · 12 LAYERS, RELATIVE THICKNESS LED cover glass · 0.55 mm optical adhesive · 150 µm upper polariser colour-filter glass · 0.20 mm liquid-crystal layer · 3.5 µm TFT glass · transistors + one shared conductor lower polariser air gap · not a mistake, it is optical diffuser light guide plate · 0.40 mm reflector metal frame the flex that carries signals out leaves from the TFT glass — the colour-filter glass carries nothing out DETAIL · THAT ONE LAYER AT 40× one continuous conductor strip display calls it Vcom · common electrode touch calls it TX · transmit electrode same piece of metal, time-shared pixel transistors sit underneath, on the same glass consequence: stall the display side and touch stops too — while every touch register still reads back perfectly normal. 1 2 3 glass film adhesive active silicon what this figure is about hatched = cut through solid material ① the plan view carries the section line, so the reader knows where the cut was taken and which way they are facing · ② every thin band is named outside, on a leader ③ the detail panel is joined to its origin by two lines, not one — one line reads as an arrow pointing somewhere, two read as “this region, blown up”. thicknesses are typical for a small-panel module and are drawn to relative, not absolute, scale — measure your own stack before quoting any of them. Cross-section · panel stack
hardware · a cut through the stack硬件 · 把叠层切开 A section only means something once the reader knows where the cut was taken, so the plan view carries the section line and the two arrows that say which way you are facing. Twelve bands is more than any of them can hold as text, so every name goes outside on a leader. The dashed box on the TFT glass reaches the magnified panel by two lines rather than one — one line reads as an arrow pointing somewhere, two read as “this region, blown up”. The detail is the payload: the display’s common electrode and the touch transmit electrode are one piece of metal, which is why a stalled display side takes touch with it while every touch register still reads back normal. Template: templates/diagrams/cross-section.svg. 剖面图只有在读者知道「从哪儿切的」时才成立,所以平面图上要画剖切线,还要画两个箭头说明你朝哪边看。十二层里没有一层塞得下文字,于是名字一律用引线引到外面。TFT 玻璃上那个虚线框用两条线连到放大面板,不是一条——一条读起来是「指向某处的箭头」,两条才读成「这一块,放大」。真正的内容是放大面板本身:显示用的公共电极和触摸用的发射电极是同一片金属,所以显示侧一停,触摸跟着停,而触摸寄存器读回来全是正常值。模板:templates/diagrams/cross-section.svg
EXPLODED VIEW · IN WHAT ORDER, AND WHAT CAN EVER COME APART AGAIN ASSEMBLED one part, from outside the thumbnail is not decoration — without it the column below is just a list of rectangles ASSEMBLY AXIS logic die CPU + GPU memory stack silicon interposer package substrate printed circuit board 1 2 3 4 5 heat spreader lid comes off first in any rework · separable thermal interface one use only — lift the lid and it is scrap two dies, already bonded bonded to the interposer, not to each other underfill cured · from here down nothing separates silicon interposer carries the wide bus between the two dies one broken trace here scraps the whole part copper bumps a joint, not a part · reflowed once package substrate fans the fine pitch out to something a board can take solder balls the only joint here a repair shop can undo printed circuit board everything above arrives as one component solid border · this really does come apart dashed border · permanent once cured or reflowed round elements are joints between two parts, not parts of their own assembly order is ① substrate first, ② interposer onto it, ③ dies onto the interposer, ④ underfill and lid, ⑤ and only then the finished package onto the board. that order is the whole reason to draw this instead of a cross-section: a section shows what touches what, and says nothing about what happened first, or what you can still get back apart. the axis is one straight line and every part is centred on it — that line is the reader’s only clue to how the pieces go back together. the gaps are equal on purpose. unequal gaps get read as real distance, and then two parts that merely sit next to each other look like they are related. Exploded view · chip package
hardware · in what order, and what comes apart硬件 · 装配顺序,以及什么还拆得下来 A cross-section says what touches what. It cannot say what happened first, or what you can still get back apart — and those are the two questions that decide whether a board is repairable. So the parts come off one straight axis at equal spacing, and the numbered badges run in assembly order rather than top to bottom — ① substrate, ② interposer, ③ dies, ④ underfill and lid, ⑤ the finished package onto the board. The border tells you the rest: solid means it separates, dashed means that once it is cured or reflowed the answer is no. The thumbnail on the left is not decoration; without it the column is a list of rectangles. Template: templates/diagrams/exploded-view.svg. 剖面图能说清谁挨着谁,但说不了「先装哪个」和「还拆不拆得下来」——而这两件事才决定一块板子能不能修。所以所有件挂在同一根直轴上、间距相等;编号走的是装配顺序,不是从上到下 —— ① 基板、② 中介层、③ die、④ 填胶加盖、⑤ 最后整颗上板。边框把剩下的话说完:实线表示还能拆开,虚线表示胶固化或焊料回流之后就回不去了。左边那张成品缩略图不是装饰,没有它,右边只是一列矩形。模板:templates/diagrams/exploded-view.svg
DEBUG MAP · EVERY BLOCK CARRIES THE COMMAND THAT LOOKS INSIDE IT START FROM WHAT YOU SEE backlight on, screen black pixels are not arriving → start at the display controller backlight off too nothing is powered → start at regulators, then gpio device node missing the driver never bound → start at probe deferred boots, then stops an interrupt never came → start at interrupts image torn or shifted timing, not content → start at the clock tree the rule this map exists to serve prove a stage received its input before you suspect that stage. half of “the driver is broken” turns out to be a clock that was never enabled. DISPLAY PATH display controller reads the framebuffer, drives timing /sys/kernel/debug/dri/0/state read connector · DSI-1 is the panel even enabled /sys/class/drm/card0-DSI-1/enabled read buffers handed around who allocated, who still holds it /sys/kernel/debug/dma_buf/bufinfo read driver chatter, live turn one file's debug prints on dynamic_debug/control ← +p writes PLATFORM SERVICES · CLOCK, POWER, PINS clock tree is the pixel clock running at all /sys/kernel/debug/clk/clk_summary read regulators which rails are on, and who asked regulator/regulator_summary read pin multiplexing is the pin still a GPIO pinctrl/*/pinmux-pins read gpio lines direction and level, per line /sys/kernel/debug/gpio read INTERRUPTS AND BINDING interrupts is the count going up, on which CPU /proc/interrupts read did the driver bind the symlink exists only once it did /sys/bus/platform/devices/<dev>/driver read green pill · only reads, safe to run on a live board gold pill · changes hardware or kernel state an architecture diagram that does not say how to observe each block leaves the reader knowing the shape of the system and still not knowing what to type. read-only and state-changing commands are told apart on the figure itself, because the difference matters most at 2am on someone else’s board. paths under /sys/kernel/debug exist only where debugfs is mounted and the matching kernel options were built in — a missing file is not proof the block is idle. Debug map · commands on blocks
kernel · every block carries its command内核 · 每个方块带着查它的命令 An architecture diagram that does not say how to look inside each block leaves the reader knowing the shape of the system and still not knowing what to type. This one pins the exact path under every card, and colours the pill by consequence: green only reads, gold changes hardware or kernel state — a difference that matters most at 2am on somebody else’s board. The left column is the real entry point, because nobody arrives at a debug session holding a block diagram; they arrive holding a symptom. Template: templates/diagrams/debug-map.svg. 一张不说「怎么看里面」的架构图,只让读者知道系统长什么样,还是不知道该敲什么。这张把具体路径钉在每张卡下面,药丸按后果上色:绿色只读,金色会改硬件或内核状态——这个区别在凌晨两点、在别人的板子上最要命。左边那一列才是真正的入口,因为没人是捧着方块图进调试现场的,进来时手里拿的是一个现象。模板:templates/diagrams/debug-map.svg
ORDERS OF MAGNITUDE · TEN DECADES ON ONE AXIS every step to the right is ten times longer. that is the only way twelve numbers spanning a factor of 150 million fit in one picture. 1 ns 10 ns 100 ns 1 µs 10 µs 100 µs 1 ms 10 ms 100 ms 1 s L1 hit branch mispredict uncontended lock one DRAM access one syscall context switch NVMe random read eMMC random read same-rack round trip spinning-disk seek one frame at 60 Hz cross-continent the only one a person can perceive processor memory storage network what your eye is waiting for THE SAME NUMBERS, IF ONE NANOSECOND WERE ONE SECOND L1 hit 1 ns 1 second one DRAM access 80 ns 1.3 minutes one syscall 500 ns 8 minutes NVMe random read 50 µs 14 hours one frame at 60 Hz 16.7 ms 193 days cross-continent 150 ms 4.7 years THE SAME TWELVE POINTS ON A LINEAR AXIS · WHY THIS FIGURE IS NOT LINEAR 0 150 ms eleven of the twelve land on this one mark these are typical orders of magnitude, not measurements — the point is the distance between them, not the digits. measure your own board before quoting any figure. a log axis has to say so on its face: equal spacing means times ten, and a reader who misses that reads every gap as ten times too small. the human-scale row is what turns the ruler into an argument. “a hundred thousand times slower” is a phrase; “one second against a hundred and ninety-three days” is a picture. Magnitude ruler · log scale
performance · ten decades on one axis性能 · 一根轴放下十个数量级 Twelve numbers spanning a factor of 150 million do not fit on a linear axis — the strip at the bottom shows what happens if you try, with eleven of them collapsed onto one mark. A log axis fits them, at the price of one obligation: it has to say on its face that equal spacing means ten times, or the reader silently reads every gap as ten times too small. The row of human-scale cards is what turns the ruler into an argument. “A hundred thousand times slower” is a phrase; “one second against a hundred and ninety-three days” is a picture. Template: templates/diagrams/magnitude-ruler.svg. 十二个数字跨了 1.5 亿倍,线性刻度放不下——底下那条小图就是硬放的结果,十一个点叠在同一个位置上。对数轴放得下,代价是一条义务:必须在图上写明「等距 = 十倍」,否则读者会不出声地把每一段都读小十倍。下面那排「换成人类尺度」的卡片,才是让这把尺子变成论据的东西。「慢十万倍」是一句话,「一秒 对 一百九十三天」是一张图。模板:templates/diagrams/magnitude-ruler.svg
PINOUT · 30-WAY PANEL FLEX, AS THE PART IS ACTUALLY BUILT the strip is the physical row of pads; the table below is what each one carries. one without the other is not a pinout. D3 D2 CLK D1 D0 pin 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 WHAT EACH PAD CARRIES 1 GND 2 VLED- backlight cathode 3 VLED- doubled for current 4 VLED+ backlight anode 5 VLED+ doubled for current 6 GND 7 D3N lane 3 8 D3P lane 3 9 GND pair shield 10 D2N lane 2 11 D2P lane 2 12 GND pair shield 13 CLKN clock 14 CLKP clock 15 GND pair shield 16 D1N lane 1 17 D1P lane 1 18 GND pair shield 19 D0N lane 0 20 D0P lane 0 21 GND pair shield 22 TE tearing effect, panel to host 23 RESET active low 24 IOVCC 1.8 V logic 25 IOVCC doubled 26 VSP +5.5 V analogue 27 VSN -5.5 V analogue 28 SCL I2C to the touch controller 29 SDA I2C to the touch controller 30 GND the trap this figure exists to prevent left and right depend on which face you are looking at. seen from the component side, this connector is the mirror of itself seen from the pad side. so a pinout is only usable when it states the viewing side and marks pin 1 — and the part itself has to carry that mark too, or the drawing cannot be checked. ground power rail differential pair control / I2C bracket · the two halves of one differential pair the pairs are bracketed, not merely listed. a pair split across two table rows reads as two independent pins — and routing them that way is how a lane fails at the far end of the flex. the grounds sitting between pairs are shields, not spare grounds — reassigning one of them to something else changes the impedance of the pair next to it. this is an example arrangement, not a part number. the panel datasheet is the authority for any board you are actually building. Pinout · panel flex connector
hardware · a connector, pin by pin硬件 · 连接器,一根一根 Two things have to be on the page together: the physical row of pads, drawn as the part is actually built, and the table of what each one carries. A table alone cannot be checked against the part in your hand; a strip alone does not tell you what any pad is. Differential pairs get a bracket instead of two neighbouring table rows, because a pair read as two independent pins gets routed as two independent pins. And the orange box is the trap the whole figure exists to prevent: left and right depend on which face you are looking at, so a pinout without a stated viewing side and a pin 1 mark is not usable. Template: templates/diagrams/pinout.svg. 两样东西必须同时在页面上:按实物排布画出来的那一排焊盘,和「每一根是什么」的表。光有表,没法拿实物对着核;光有排布图,读者不知道每根是什么。差分对用一个括号括起来,而不是并排两行表格——一对被读成两根独立的脚,就会被当成两根独立的脚去布线。橙色那个框是整张图存在的理由:左右取决于你从哪一面看,所以不写清「从哪面看」、不标 1 脚的引脚图,是不能用的。模板:templates/diagrams/pinout.svg
OPEN IT FIRST, THEN CLOSE IT INTO A SYMBOL each panel opens the symbol the panel before it handed over. a symbol nobody has seen opened is a symbol nobody will question. 1 two transistors one pulls up, one pulls down WHAT IS INSIDE THE SYMBOL YOU THEN USE supply ground out in 2 transistors the triangle is not new information — it is the pair above, folded up. 2 two of them, in a ring each one feeds the other WHAT IS INSIDE THE SYMBOL YOU THEN USE high low neither one can change without the other disagreeing. so it stays. 1 bit that holds no clock, no refresh 4 transistors the box is worth 4, not 1. that number is the price of the abstraction. 3 a way in and out two more, opened by a word line WHAT IS INSIDE THE SYMBOL YOU THEN USE word line · opens both at once bit line bit line the ring is the same ring. the two new transistors only decide when you may look. one memory cell addressable, at last 6 transistors multiply by a few million and you have the cache the die photo is mostly made of. a wire held high a wire held low “everything above, folded into this” a reader who has seen a symbol opened will question it later. a reader who met it already closed will copy it, and will be stuck the first time the variant does not behave. every symbol carries its transistor count, so the ladder never hides what an abstraction costs — which is the number that decides whether it is used a million times. Abstraction ladder · open, then close
silicon · open the symbol before you use it芯片 · 用符号之前先把它打开 Every technical page runs on abstraction, and every abstraction is a box somebody stopped drawing the inside of. That decision is normally invisible: the reader meets the triangle already closed and is stuck the first time a variant misbehaves. Three panels fix it — each one opens the symbol the panel before it handed over, and each closed symbol carries its transistor count, so the ladder never hides what a level costs. Three rungs is the practical limit; past that the reader loses track of what contains what. Template: templates/diagrams/abstraction-ladder.svg. 任何技术页面都靠抽象运转,而每个抽象都是有人决定不再画里面的那个盒子。这个决定通常是隐形的:读者遇到那个三角形时它已经关着了,然后在第一个不按常理出牌的变体上卡住。三格就能补上——每一格打开上一格交过来的那个符号,而每个折起来的符号都带着自己的晶体管数,所以这条阶梯从不隐藏一层抽象的价钱。三级是实际的上限,再多读者就跟丢了「谁装着谁」。模板:templates/diagrams/abstraction-ladder.svg
THREE STATES, ONE GEOMETRY · ONLY THE COLOUR MOVES the three panels share every coordinate on purpose, and read left to right as one story: the cell holds a zero, a write turns it into a one, then a read gets that one back out. holding nobody is touching it word line bit line · QB side bit line · Q side Q QB the word line is not asserted both access transistors are shut. the ring keeps itself, and holds a zero at Q. writing the drivers win word line bit line · QB side bit line · Q side Q QB the bit lines are driven, and Q flips a write is not persuasion — it is overpowering the ring from outside. Q is a one now. reading the cell barely whispers word line bit line · QB side bit line · Q side Q QB −50 mV both bit lines start high; one dips QB is the low node, so the QB-side bit line is the one that sags. that sag is the entire signal. high low nobody is driving it the word line is asserted a figure redrawn for every state hides which parts moved. a figure recoloured for every state shows it, and the reader stops re-reading the schematic three times. the colour meanings are fixed once for the whole figure. a legend that changes between panels is worse than no legend at all. fifty millivolts is a typical order of magnitude for a cell like this, not a measurement — the point is that it is small, not that it is fifty. State triptych · recolour, do not redraw
silicon · three states, one geometry芯片 · 三个状态,一套坐标 The usual way to show three states is three drawings, and the usual result is that the reader re-finds the circuit three times and never notices what actually changed. Lock every coordinate instead: the eye has nothing to re-parse, and the difference is the only thing left moving. Colour carries the whole argument here, so its meaning is fixed once for the figure — a legend that changes between panels is worse than no legend. The three also read left to right as one story rather than as a menu. Template: templates/diagrams/state-triptych.svg. 展示三个状态的常规做法是画三张图,常规结果是读者把电路重新找了三遍,却始终没注意到到底哪里变了。改成把每一个坐标都锁死:眼睛没有东西要重新解析,唯一还在动的就是那个差别。这里颜色承担了全部论证,所以它的含义对整张图只定义一次——在几格之间会变的图例,比没有图例更糟。三格从左到右还读成一个故事,而不是一份清单。模板:templates/diagrams/state-triptych.svg
ONE PART, SIX STEPS · ONLY THE NEW FEATURE IS OUTLINED every panel is the same section at the same coordinates. what a step added is the only thing outlined in orange, so reading a step costs one glance instead of a comparison. 1 bare core copper on both faces STILL RECOVERABLE? yes, at panel cost scrap costs one sheet of laminate 2 drill a hole straight through STILL RECOVERABLE? yes, at panel cost a hole in the wrong place cannot be moved 3 plate the wall the two faces are joined STILL RECOVERABLE? yes, at panel cost a thin wall shows up much later, in the field 4 etch top copper into traces STILL RECOVERABLE? no over-etch reads as an open circuit, not as a process fault 5 build up one dielectric, one copper STILL RECOVERABLE? no every added layer multiplies the alignment risk 6 finish pads, ready for parts STILL RECOVERABLE? no a bad finish is at least caught at assembly, cheaply from here on, no way back orange outline · what this step added copper core laminate build-up dielectric six independent drawings would make the reader re-find the part six times. keeping every coordinate identical is what turns a row of pictures into a process. outlining only the new feature is the other half: without it the reader has to compare two panels to work out what a step did, and comparing is far slower than looking. the recoverability line under each panel is what a process diagram usually leaves out, and it is the thing a schedule actually turns on. this is the common shape of a build-up substrate, drawn to carry the idea. a real line has more steps than six, and its own order. Process steps · one part, six panels
hardware · one part, six panels硬件 · 同一个零件,六格 Six independent drawings make the reader find the part again in every panel, and by the third they have stopped comparing. Lock the coordinates and the row stops being pictures: the eye holds still and the change moves. Then outline only what the step added, so reading a step costs a glance rather than a comparison. Reading ① to ⑥ is one part being built, not six parts being introduced. The line under each panel — whether the part can still be recovered — is what process diagrams usually leave out, and it is what a schedule actually turns on. Template: templates/diagrams/process-steps.svg. 六张独立的图,会让读者在每一格里重新找一次这个零件,到第三格他已经不再对比了。锁死坐标,这一排就不再是图片:眼睛不动,变化在动。然后只把这一步新增的东西描出来,读一步的代价就从「对比」降成「看一眼」。从 ① 读到 ⑥,读的是同一个零件被造出来,不是六个零件被介绍一遍。每格下面那行——这个零件还救不救得回来——是工序图通常会省掉的,也正是排期真正取决于的那一行。模板:templates/diagrams/process-steps.svg
FOUR PANELS, THREE ORDERS OF MAGNITUDE · EACH ONE OPENS THE LAST a zoom chain only works when each step says where it came from and how much bigger it is. two lines between panels, and a real dimension on every one. 1 a board 100 mm across 2 one package 30 mm across 3 one die 10 mm across 4 the bumps 0.2 mm across 50× the package one of these is the part the next panel opens logic die memory two dies under one lid, joined below core core cache input / output the corner where it meets the world below 40 µm pitch one connection THE SAME FOUR WIDTHS, ON ONE RULE 0.1 mm 1 mm 10 mm 100 mm the board the package the die the bumps the four panels are evenly spaced on the page and nowhere near evenly spaced in reality. the rule underneath is what stops the layout from making that claim on its own. two lines between panels, never one: one line reads as “goes to”, two read as “this region, opened”. it is the same pair of lines a cross-section uses for a detail. every panel carries a real width. a zoom chain without dimensions is decoration — the reader cannot tell a 3× step from a 50× one, and here the last step is the big one. the dimensions are representative of a desktop-class part, chosen so the ratios are honest. they are not a specific product. Scale ladder · zoom chain
hardware · four panels, three orders of magnitude硬件 · 四格,三个数量级 A zoom chain needs three things at every hop: a dashed box saying which region is next, two lines carrying that box into the next panel, and a real dimension so a threefold step can be told from a fiftyfold one. The rule underneath is not decoration — the four panels are evenly spaced on the page and nowhere near evenly spaced in reality, and without the rule the layout makes that claim on its own. The two-line convention is the same one a cross-section uses to attach a detail. Template: templates/diagrams/scale-ladder.svg. 一条放大链,每一跳都要三样东西:一个虚线框说明下一格看的是哪一块、两条线把这个框带进下一格、以及一个真实尺寸,好让「放大三倍」和「放大五十倍」区分得开。底下那把尺子不是装饰——四格在页面上等距排开,在现实里差得很远,没有尺子,排版自己就在宣称那个错误的比例。两条线这个约定,跟剖面图挂放大面板用的是同一个。模板:templates/diagrams/scale-ladder.svg
THREE WAYS TO LOOK INSIDE ONE THING · AND WHAT EACH ONE COSTS “show the inside” is not one drawing. it is three, they answer different questions, and picking the wrong one is why a figure can be careful and still not help. 1 cut it open a plane through the part lid dies substrate hatching says “the knife went through here” ANSWERS what touches what, and how thick PAYS WITH you only see the one plane you cut 2 make it see-through the shell drops to a whisper logic memory the shell is still there — it is just quiet two overlapping parts read as a third ANSWERS how many parts, and how they sit PAYS WITH wherever things overlap, it goes muddy 3 pull it apart along one straight axis equal gaps, one axis, everything centred on it ANSWERS what order, and what still separates PAYS WITH the real adjacency is gone the question picks the drawing, not your taste “what is next to what, and how thick” → cut it · “how many, and where” → make it see-through · “what order, and can it come apart” → pull it apart a figure that tries to answer all three at once answers none of them well: the section grows ghost outlines, the see-through view grows an axis, and the reader stops trusting any of it. see-through is the one to reach for least. it is the only one of the three whose failure is quiet — overlapping parts merge into shapes that were never there, and nothing on the page says so. all three are flat drawings. none of them needs perspective, and adding it costs accuracy in exchange for looking like a render. See inside · three ways, three costs
hardware · three ways to look inside硬件 · 三种看内部的画法 “Show the inside” is not one drawing. Cutting answers what touches what and how thick, and pays by showing only the plane you cut. Making it see-through answers how many parts there are and how they sit, and pays wherever things overlap. Pulling it apart answers what order and what still separates, and pays with the real adjacency. See-through is the one to reach for least, because it is the only one whose failure is quiet. Template: templates/diagrams/see-inside.svg. 「把里面画出来」不是一种画法。切开答的是谁挨着谁、多厚,代价是只看得到那一刀所在的平面;透视答的是里面有几个、怎么摆,代价是重叠处会糊;拆开答的是什么顺序、还拆不拆得开,代价是真实的相邻关系没了。三种里最该少用的是透视——它是唯一一种失败得很安静的。模板:templates/diagrams/see-inside.svg
DRAW THE ARRAY ONCE · MOVE THE HIGHLIGHT, NOT THE DRAWING a dense figure redrawn for every step costs the reader a fresh search each time. keep it still, keep it neutral, and let one row or one cell come forward. 1 nothing selected the structure, and nothing else word bit one page the dashed box is the whole point of this panel: “page” is a word, and this is where it lives. 2 one word line up selecting a row is a physical act word bit the array did not move. one wire came forward, and the cells it opens came with it. 3 one cell addressed a row and a column, and their crossing word bit two layers of highlight is the limit. a third colour on the same picture and nothing is highlighted. not part of this step the word line that is up the bit line being read the one cell in question a name, pinned to the structure the array is drawn once. a dense picture redrawn for every step makes the reader locate it again in each panel, and by the third panel they have stopped looking carefully. neutral is a choice, not a leftover. everything not part of this step is deliberately quiet, which is what gives the one thing that is coloured somewhere to stand out from. a word like page, row, block or bank should be pinned onto the physical picture with a dashed box the first time it appears. described only in prose, it stays a word the reader nods at. two layers of highlight is the working limit. a third colour on the same picture means nothing is highlighted, and it is the point at which the material wants a second figure. Highlight in place · one array
hardware · draw it once, move the highlight硬件 · 底图画一次,动的是高亮 A dense figure redrawn for every step costs the reader a fresh search each time, and by the third panel they have stopped looking carefully. Keep every coordinate, keep everything neutral, and let one row or one cell come forward. The dashed box in the first panel is doing the other half of the job: pinning an abstract word onto the physical structure, which is the difference between a reader nodding at “page” and knowing where it lives. Template: templates/diagrams/highlight-in-place.svg. 密图每一步重画一次,读者每一格都要重新找,到第三格已经不再仔细看了。坐标全锁死、其余全中性,只让一行或一个单元站出来。第一格那个虚线框干的是另一半活:把一个抽象名词钉在物理结构上——这就是读者对「页」这个词点头,和真知道它在哪,之间的区别。模板:templates/diagrams/highlight-in-place.svg
ISOMETRIC · WHEN THE ARRANGEMENT ON THE PLANE IS ALSO PART OF THE ANSWER a front view states every thickness and hides the layout. isometric states both, at the price of four rules it has to keep — they are on the strip below. FRONT VIEW · EVERY THICKNESS, NO LAYOUT package two memory chips thicknesses: exact, and readable at a glance. what it cannot say: are those two chips side by side, or is one behind the other? ISOMETRIC · BOTH, IF IT KEEPS THE RULES package memory 0 memory 1 connector 100 mm now the layout is the easy part: two chips in a row, to the right of the package. four rules, and the projection is only honest while it keeps all four 1 use the real transform sx = (x−y)×0.866, sy = (x+y)×0.5 − z. freehand angles drift, and a drifting angle reads as a shape difference. 2 keep every label upright tilted text is harder to read and its effective size drops after scaling. put it outside on a leader. 3 three flat tints, one hue top lightest, right middle, left darkest. no gradients, no drop shadows — those are fake lighting, not information. 4 always carry a dimension two faces that look equal in isometric can differ by a factor of two. without a dimension line it is a sketch. this replaces a blanket ban. the thing worth banning was never projection — it was decoration: drop shadows, perspective, fake thickness, a gradient standing in for a light source. isometric earns its place only when layout and thickness are both part of the answer. thickness alone wants a section; order alone wants a flat exploded view; this wants both at once. whatever is hidden in an isometric view is simply gone. to show something behind something else, move it apart or make the front one see-through — a reader will not fill it in. the shapes here are one board with four parts on it, sized so the proportions are plausible. the projection is exact; the object is an example. Isometric · four rules
hardware · isometric, and its four rules硬件 · 等距轴测,和它的四条规矩 A front view states every thickness and cannot say whether two chips sit side by side or one behind the other. Isometric states both, on four conditions: the real transform rather than freehand angles, every label upright, three flat tints of one hue instead of fake lighting, and a dimension line, because two faces that look equal in this projection can differ by a factor of two. What was worth banning was never projection — it was drop shadows, perspective and gradients standing in for a light source. Template: templates/diagrams/isometric-stack.svg. 正视图能说清每一层的厚度,却说不了那两颗芯片是并排还是前后。等距两样都能说,条件有四条:用真正的变换而不是随手画的斜边、每个标注保持正立、三个面用同一 hue 的三档平涂而不是假打光、以及必须有一条尺寸线——因为在这种投影里看起来一样大的两个面,实际可能差一倍。当初值得禁的从来不是投影,是投影阴影、透视和拿渐变冒充光源。模板:templates/diagrams/isometric-stack.svg
03 · silicon & code03 · 芯片与代码

Silicon & code diagrams 芯片框图与代码框图

Seven figures for the two things hardware and kernel work keeps asking for: what the silicon looks like inside, and what the code's data actually points at. Each one carries a rule you cannot see in a block diagram — a device card pinned to its own address window, a tile joined at its ring stop, an arrow that leaves the exact field holding the pointer. 七张图,画硬件和内核工作里反复要画的两样东西:芯片里面长什么样,代码里的数据到底指向哪。每一张都带一条方块图看不见的规矩——设备卡钉在自己的地址窗口上、瓦片挂在自己的站点上、箭头从真正持有指针的那一行出发。

SYSTEM TOPOLOGY · PCIe HIERARCHY OVER ITS ADDRESS SPACE DRAM device MMIO window owns this BAR DDR4 · 2 DIMM DDR4 · 2 DIMM ch0 · 3200 MT/s ch1 · 3200 MT/s ch2 · 3200 MT/s ch3 · 3200 MT/s SoC PACKAGE one coherent domain IMC IMC Core 0Core 1 Core 2Core 3 ROOT COMPLEX · BUS 00 RP0 · 00:1c.0 RP1 · 00:1c.4 RP2 · 00:1d.0 Gen4 x4 · BUS 01 Gen4 x8 · BUS 02 Gen3 x1 · BUS 06 x4 · BUS 03 x4 · BUS 04 PCIe SWITCH 1 upstream · 2 downstream · BUS 02 NVMe SSDAccelerator GPUNetwork 01:00.0 · BAR0 16 KiB 03:00.0 · BAR0 256 MiB 04:00.0 · BAR0 512 MiB 06:00.0 · BAR0 128 KiB DRAM · 0 – 2 GiB nvme accel gpu nic DRAM · 4 GiB and up 0x0000_0000 PCI MMIO window · 32-bit 0x1_0000_0000 not to scale
system topology · address windows板级拓扑 · 地址窗口 The PCIe tree and the physical address space in one frame. Every wire carries its link width and bus number, every device card its BDF and BAR size, and a dashed leader drops from each card onto its own segment of the bar. Split these into two figures and the reader has to hold the mapping in their head — which is exactly the part that goes wrong. Template: templates/diagrams/system-topology.svg. PCIe 树和物理地址空间画在同一张图里。每根线标接口宽度和总线号,每张设备卡标 BDF 和 BAR 大小,虚线引线从卡落到地址条上属于它的那一段。拆成两张图,读者就得自己在脑子里做这个映射——而出错的恰恰是这一步。模板:templates/diagrams/system-topology.svg
DIE FLOORPLAN · TILE MESH core cache slice IO tile mesh · ring stop this request UPI ×20 2 links · 10.4 GT/s PCIe ×16 Gen5 · 32 GT/s DMI ×8 to PCH PCIe ×16 Gen5 · 32 GT/s CHA · LLC 3 MiB Core 0 CHA · LLC 3 MiB Core 1 CHA · LLC 2 MiB Core 2 CHA · LLC 3 MiB Core 3 CHA · LLC 2 MiB Core 4 CHA · LLC 2 MiB Core 5 CHA · LLC 3 MiB Core 6 CHA · LLC 3 MiB Core 7 CHA · LLC 2 MiB Core 8 CHA · LLC 3 MiB Core 9 CHA · LLC 3 MiB Core 10 CHA · LLC 2 MiB Core 11 CHA · LLC 3 MiB Core 12 CHA · LLC 3 MiB Core 13 CHA · LLC 2 MiB Core 14 CHA · LLC 2 MiB Core 15 CHA · LLC 3 MiB Core 16 CHA · LLC 2 MiB Core 17 CHA · LLC 3 MiB Core 18 CHA · LLC 3 MiB Core 19 MC 0 MC 1 DDR5 · 3 ch DDR5 · 3 ch 1 2 3 COMPUTE DIE · 20 tiles · 5 × 4 mesh a tile joins the mesh at its ring stop, not at its edge
die floorplan · tile mesh片内布局 · 瓦片网格 Twenty tiles, each a core under its own cache slice, joined by mesh rails whose crossings are the ring stops. A tile joins the mesh at its stop, not at its edge — that distinction is why one request's latency depends on how many stops it crosses. Badges 1 to 3 trace a single miss out to the memory controller. Template: templates/diagrams/die-floorplan.svg. 二十块瓦片,每块是一个核加它自己那片缓存,瓦片之间跑互连轨,交叉点就是站点。瓦片挂在自己的站点上、不是连在轨边上——一次访问的延迟取决于跳了几站,靠的就是这个区别。徽章 1–3 追一次未命中一路走到内存控制器。模板:templates/diagrams/die-floorplan.svg
DATAPATH · 4-WAY SET-ASSOCIATIVE LOOKUP comparator multiplexer OR gate 4712 116 50 TAG · 36 bits SET INDEX · 6 BLOCK OFFSET · 6 6 → 64 decoder · one wordline per set 36 4 V · TAG ARRAY DATA ARRAY · SET 41 way 0 1 0x0004_A1C 64 B line · way 0 = way 1 0 0x00F1_2B8 64 B line · way 1 = way 2 1 0x0004_A1C 64 B line · way 2 = way 3 1 0x0091_7D0 64 B line · way 3 = 4:1 ≥1 word → load unit HIT a miss is this line staying low A B C D E way 1 is invalid, so its comparator can never assert — the valid bit is an input to the match, not a decoration
datapath · comparators, mux, gate数据通路 · 比较器与选择器 A four-way set-associative lookup drawn at gate level: the address splits, a decoder picks the set, four comparators race, and the match lines both drive the multiplexer and feed the OR gate that raises HIT. Way 1 is invalid, so its comparator can never assert — that one deliberate dead lane is what makes the valid bit legible. Badges A to E. Template: templates/diagrams/datapath.svg. 四路组相联查找画到器件一级:地址拆分、译码器选中一组、四个比较器同时比、匹配线一边驱动多路选择器一边进或门抬起 HIT。way 1 的 valid 是 0,它的比较器永远不会成立——故意留死这一路,valid 位才讲得清。徽章 A–E。模板:templates/diagrams/datapath.svg
PACKET ENCAPSULATION · ONE BYTE RULER, THREE LAYERS 8 px = 1 byte · bars are to scale with each other Transaction layer TLP header 16 B data payload 64 B 80 B · what the requester actually meant to send Data link layer the 80 B above, untouched + SeqNum 2 B + LCRC 4 B 86 B · replay needs the number, the receiver needs the CRC Physical layer · framing the 86 B above, untouched + STP 1 B + END 1 B 88 B · now it has a beginning and an end on the wire BYTE STRIPING · x4 LINK Lane 0 byte 0 byte 4 byte 8 Lane 1 byte 1 byte 5 byte 9 Lane 2 byte 2 byte 6 byte 10 Lane 3 byte 3 byte 7 byte 11 SerDes · 128b/130b · 32 GT/s per lane byte n leaves on lane n mod 4
packet encapsulation · byte ruler逐层封装 · 字节标尺 One packet down three layers on a single byte ruler at eight pixels per byte, so each bar's width is its byte count. Two dashed guidelines pin the original eighty bytes: everything a lower layer adds appears outside them, never inside. Fields narrower than their own label get bracketed out to the margin rather than shrunk. Template: templates/diagrams/packet-encap.svg. 同一个报文走过三层,画在一把 8 px/字节的标尺上,所以每根条的宽度就是它的字节数。两条竖虚线钉住最初那 80 字节:下层加的东西一律长在外面,绝不进到里面。窄到装不下标签的字段用括线引到边上写,不缩字号。模板:templates/diagrams/packet-encap.svg
ANNOTATED CONSOLE · PCI ENUMERATION, ONE FAILING DEVICE real output, marked up · never retyped ttyS0 · 115200 8N1 · dmesg | grep -E 'pci|accel|nvme' [ 0.412903] PCI: MMCONFIG for domain 0000 [bus 00-ff] [ 0.418772] pci_bus 0000:00: root bus resource [mem 0x90000000-0xafffffff window] [ 0.431065] pci 0000:00:1c.0: PCI bridge to [bus 01] [ 0.436210] pci 0000:01:00.0: [144d:a80a] type 00 class 0x010802 [ 0.441642] pci 0000:01:00.0: BAR 0: assigned [mem 0x90000000-0x90003fff 64bit] [ 0.447318] pci 0000:00:1c.4: PCI bridge to [bus 02-04] [ 0.451900] pci 0000:02:02.0: bridge window [mem 0xa0100000-0xa01fffff] [ 0.458233] pci 0000:04:00.0: [1de5:1001] type 00 class 0x120000 [ 0.462117] pci 0000:04:00.0: reg 0x10: [mem 0x00000000-0x0fffffff 64bit pref] [ 0.476551] pci 0000:04:00.0: BAR 0: no space for [mem size 0x10000000 64bit pref] [ 0.481990] pci 0000:04:00.0: BAR 0: failed to assign [mem size 0x10000000] [ 0.488412] accel 0000:04:00.0: probe failed with error -12 [ 2.441642] nvme nvme0: 4/0/0 default/read/poll queues [ 2.509377] nvme0n1: p1 p2 / # 1 2 3 4 5 1 The only window there is Everything on this root bus has to fit in 0x9000_0000–0xafff_ffff — 512 MiB. Read this line before you read any BAR line. 2 Firmware already froze the window The bridge down to bus 04 got a 1 MiB window at boot. Nothing behind that bridge can ever be larger, whatever the parent has spare. 3 What the device is asking for reg 0x10 reads back 0x0fff_ffff, so BAR0 wants 256 MiB — 256× the window it must live in. This line is the request, not the result. 4 −12 is −ENOMEM, not a driver bug The resource was never assigned, so pci_iomap() in probe() had nothing to map. Fixing the driver cannot fix this; the window has to grow. 5 The healthy one, for contrast Four lines later nvme got its BAR and its queues. Keep a known-good stretch in the same figure — it is what tells you the log itself is fine.
annotated console · real output终端实录 · 原样标注 Fourteen lines of real PCI enumeration, marked up and never retyped. Five badges pin lines to notes; the highlight blocks sit under the glyphs and are positioned from character indices, because every line is pinned to an exact textLength. The story: a 256 MiB BAR behind a bridge window firmware sized at 1 MiB, and the minus twelve that follows. The healthy NVMe lines stay in frame on purpose. Template: templates/diagrams/terminal-annotated.svg. 十四行真实的 PCI 枚举输出,只加标注、一个字符不改。五个徽章把行钉到右栏说明;高亮块画在文字下面,位置由字符下标算出来——每行都用 textLength 锁死了字符步进。讲的事:一个 256 MiB 的 BAR 挂在 firmware 只给了 1 MiB 的桥窗口后面,接着就是 -12。正常的 nvme 那几行是故意留在画面里的。模板:templates/diagrams/terminal-annotated.svg
STRUCT GRAPH · WHICH FIELD HOLDS WHICH POINTER pointer field · every arrow starts here, not at the edge of the box mm->mm_mt maple tree, keyed by vm_start · replaced the VMA list and rbtree in 6.1 slot 0 0x5566_1000+ slot 1 0x5566_9000+ slot 2 0x7ffd_0000+ struct task_struct pid pid_t comm[16] char mm mm_struct * active_mm mm_struct * files files_struct * struct mm_struct mm_users atomic_t mm_count atomic_t pgd → page tables mmap_base unsigned long mm_mt maple_tree map_count int · 42 VMAs struct vm_area_struct vm_start 0x5566_1000 vm_end 0x5566_9000 vm_flags VM_READ|VM_EXEC vm_pgoff 0 vm_file file * vm_ops vm_operations_struct * anon_vma NULL until first COW struct vm_area_struct vm_start 0x5566_9000 vm_end 0x5566_b000 vm_flags VM_READ|VM_WRITE struct vm_area_struct vm_start 0x7ffd_0000 vm_end 0x7ffd_2000 vm_flags VM_GROWSDOWN struct file f_inode inode * f_mapping address_space * f_op file_operations * struct vm_operations_struct .fault filemap_fault .map_pages filemap_map_pages .open / .close NULL field names from include/linux/mm_types.h and sched.h at v6.6 rows are in reading order, not struct offset order
struct graph · pointer fields结构体指针图 · 字段级 task_struct to mm_struct to the maple tree to three VMAs, with every arrow leaving the field that actually holds the pointer and landing on the target's title bar. Start precise, end whole — that asymmetry is the point. One sibling is drawn in full, the other two keep only what tells them apart. Names checked against include/linux/mm_types.h at v6.6. Template: templates/diagrams/struct-graph.svg. task_struct → mm_struct → maple tree → 三个 VMA,每根箭头从真正持有指针的那一行出发,落在目标卡片的标题栏上。起点精确到字段、终点是整个对象——这个不对称就是重点。兄弟对象只详画一个,其余只留区分它们的那几行。字段名对过 v6.6 的 include/linux/mm_types.h。模板:templates/diagrams/struct-graph.svg
BUS FABRIC · TWO RAILS, ONE TRACED READ master slave APB peripheral this read CPU cluster 4 × A78 · AXI master 0 DMA engine 16 ch · AXI master 1 GPU / VPU AXI master 2 AXI4 · 128-bit · AW W B AR R APB · 32-bit 128 32 32 arbiter SRAM 256 KiB · 0x0000_0000 AXI → APB bridge protocol converter USB3 · GbE high-speed IP DDR4 controller 0x8000_0000 · 4 GiB UART0 I2C0 SPI0 GPIO WDT 1 2 3 4 every drop carries its own width; the rail carries the name of the channels riding it rails are a drawing, not a topology claim · a real AXI NoC is switched
bus fabric · rails and widths总线挂载 · 位宽 Masters above the rail, slaves below, the bridge dropping to a narrower rail with its own peripherals. Each drop carries its width as a slash and a number; the rail carries the names of the channels riding it. One read is traced out solid and back dashed, twelve pixels clear of the rail — at eight it vanished into it. The footer says out loud that rails are a drawing, not a topology claim. Template: templates/diagrams/bus-fabric.svg. 主设备在轨上方、从设备在下方,桥再往下接一条更窄的轨和它自己的外设。每条引下线用斜杠加数字标位宽,轨上写跑在它上面的通道名。一次读事务去程实线、回程虚线,离轨 12 px——8 px 时实测糊进轨里看不见。图脚明写:轨是一种画法,不是拓扑论断。模板:templates/diagrams/bus-fabric.svg
04 · calls & timing04 · 调用与时序

Call relationships and runtime timing 调用关系与运行时时序

Six figures for the two questions that follow every kernel bug: who calls whom across which boundary, and when did it actually run. Three draw structure — the kind of every edge, the place a stack stops being a call chain, the core everyone else waits on. Three draw time — the gap between raising work and running it, the deadline a frame has to beat, the order a panel has to be woken in. 六张图,回答内核问题后面永远跟着的两问:谁隔着什么边界调用了谁,以及它到底什么时候跑的。三张画结构——每条边是哪一种、栈从哪里起不再是调用链、大家在等哪个核。三张画时间——把活扔出去到它真跑之间的间隙、一帧要赶的 deadline、屏必须按什么顺序唤醒。

CALL GRAPH · THREE DRIVERS, FIVE KINDS OF EDGE direct call · same stack through an ops table async handoff · context changes hardware event completion travels back DRM CORE VENDOR DISPLAY DRIVER PANEL + BACKLIGHT in-tree one module two modules queue_work() .atomic_flush .prepare · core reaches the panel over that driver back into core plain exported symbol complete(&flip_done) wakes the worker DSI frame-done IRQ drm_mode_atomic_ioctl() userspace asked for a new frame process drm_atomic_commit() validates, then hands the work over process commit_tail() the queued work item runs here kworker drm_crtc_handle_vblank() core bookkeeping, then wakes waiters hardirq qz_crtc_atomic_flush() latches the new framebuffer address qz_dsi_send_frame() kicks the display DMA qz_dsi_irq() acks, then calls core hardirq qz_panel_prepare() power rails, reset, init sequence backlight_enable() a different module entirely cross-driver grep finds the solid black edges. It cannot find the blue ones (the target is a struct member, resolved at runtime) or the gold one (the target runs later, on another thread).
call graph · five kinds of edge调用关系图 · 五种边 Three drivers, and every edge drawn by kind: a thin solid arrow is a direct call on the same stack, a hollow head means the target is a struct member resolved at runtime, a gold dashed arrow is an asynchronous handoff that changes execution context, a lightning bolt is a hardware event, a dotted arrow is a completion travelling back. The point is the last line: grep only finds the solid black ones. Template: templates/diagrams/call-graph.svg. 三个驱动,每条边按种类画:细实线是同栈直接调用,空心箭头表示目标是运行时才定的结构体成员,金色虚线是换了执行上下文的异步交接,闪电是硬件事件,点线是完成通知往回走。结论在图脚:grep 只找得到黑色实线那几条。模板:templates/diagrams/call-graph.svg
CALL STACK · AND WHERE IT STOPS BEING A CALL CHAIN newest frame on top · the way the kernel prints it Unable to handle kernel NULL pointer dereference at 0x18 this work item kworker skeleton qz_dsi_write_reg +0x2c/0x80 #0 [drm_quartz] qz_panel_prepare +0x64/0x120 #1 [panel_quartz] drm_panel_prepare +0x28/0x50 #2 drm_atomic_helper_commit_modeset_enables +0x2a8/0x430 #3 commit_tail +0xa4/0x180 #4 process_one_work +0x1d8/0x430 #5 worker_thread +0x150/0x460 #6 kthread +0x110/0x11c #7 ret_from_fork +0x10/0x20 #8 the chain of “who called me” ends here drm_atomic_commit() ran queue_work() earlier, in another context. Not on this stack. Where it died 0x2c into an 0x80-byte function. Feed that offset to addr2line, not the raw PC — modules relocate. The boundary worth noticing Frames 0-1 are out-of-tree, 2-4 are core. The bug is almost always on the side with the module tag. Learn the skeletons by sight process_one_work / worker_thread — workqueue. call_timer_fn — timer. rcu_do_batch — RCU. el0_svc_common — a syscall from userspace. Each one marks a cut like this one. A stack answers “how did I get here” only inside one context. Every async boundary — work, timer, IRQ, RCU callback — cuts it, and the cut is invisible unless you know the skeleton frames by sight.
call stack · where it stops being a chain调用栈 · 断在哪里 A nine-frame oops backtrace with a fault line across it. Below the line is the kworker skeleton, which is not a caller chain in any useful sense — process_one_work called whatever was queued, not this. The caller you actually want ran queue_work() earlier in another context, and it is drawn as a dashed ghost card off to the side because it is not on this stack at all. Template: templates/diagrams/call-stack.svg. 九帧 oops backtrace,中间横着一条断层线。线以下是 kworker 骨架,那不是调用链——`process_one_work` 调用的是队列里排到的任何东西。你真正要找的调用者早些时候在别的上下文里跑了 `queue_work()`,它被画成旁边一张虚线幽灵卡,因为它根本不在这张栈上。模板:templates/diagrams/call-stack.svg
RUNTIME TIMELINE · ONE COMPLETION, FOUR CONTEXTS time in µs · one CPU · measured with trace_printk hardirq irq disabled · must not sleep softirq still atomic · may run on any CPU kworker a real thread · may sleep user thread the process that asked blocked in read() since before this frame qz_dma_irq() dma_tasklet() · drain descriptors dma_refill_work() · alloc + re-arm read() returns device raises IRQ tasklet_schedule() complete() queue_work() 0 25 50 75 100 125 150 µs IRQ → handler · 8 µs raise → tasklet · 6 µs queue_work() → worker actually runs · 65 µs Same handoff, two primitives, an order of magnitude apart: the tasklet runs on the way out of the interrupt, the worker waits for the scheduler like any other thread. Draw the gap, not the arrow. An arrow says “then this happens”; only the gap says when — and every latency bug lives in a gap somebody drew as an arrow. If the tasklet lane ever runs longer than MAX_SOFTIRQ_TIME the rest is pushed into ksoftirqd, and this lane turns into a fifth one that competes for the CPU.
runtime timeline · four contexts运行时泳道 · 四个上下文 One DMA completion handed along hardirq, softirq, kworker and the user thread on a shared microsecond axis. Three brackets under the axis carry the numbers: 8 µs from interrupt to handler, 6 µs from raising the tasklet to running it, and 65 µs from queue_work() to the worker actually running. A workqueue is not a slightly slower tasklet — it is an order of magnitude later, because the worker waits for the scheduler like any other thread. Template: templates/diagrams/runtime-timeline.svg. 一次 DMA 完成依次走过硬中断、软中断、kworker 和用户线程,共用一根微秒轴。轴下三条括线给数字:中断到 handler 8 µs,raise 到 tasklet 跑起来 6 µs,`queue_work()` 到 worker 真跑 65 µs。workqueue 不是「慢一点的 tasklet」,是晚一个数量级——worker 就是个普通线程,要排队等调度。模板:templates/diagrams/runtime-timeline.svg
FRAME PIPELINE · GPU → DDR → DMA → DSI → PANEL, ONE 60 Hz PERIOD front buffer · fb A back buffer · fb B CPU · compositor builds the atomic commit GPU renders into the back buffer DDR serves both at once display DMA · CRTC scans out, line by line DSI · D-PHY 4 lanes · 1 Gbps each LCD driver IC holds the pixels on the glass 1 2 3 4 5 atomic commit render frame N+1 → fb B write fb B read fb A · every line, all frame long scanout fb A · 1080 lines one burst per line · HS entry, payload, HS exit showing frame N N+1 VSYNC TE 0 2 4 6 8 10 12 14 16 18 ms slack 6.9 ms · cross ④ and the panel repeats frame N ① vsync IRQ latches the framebuffer address · ② GPU signals its fence · ③ page flip queued ④ scanout done, frame-done IRQ · ⑤ next vsync, fb B goes live the deadline is a vsync edge, not a config value
frame pipeline · one 60 Hz period一帧的数据通路 · 60 Hz Six hardware lanes over one frame period with vsync and TE underneath on the same axis. The memory lane is split in two because it serves both at once — the GPU writing the back buffer and scanout reading the front buffer — and that contention is why scanout underruns when the GPU is busy. Badge 1 the vsync interrupt latches the framebuffer address, badge 2 the GPU signals its fence, badge 3 the page flip is queued, badge 4 scanout finishes, badge 5 the next vsync makes the back buffer live. Cross badge 5 and the panel simply repeats the frame. Template: templates/diagrams/frame-pipeline.svg. 六条硬件泳道铺在一个帧周期上,下面同轴画 vsync 和 TE。内存那条拆成两根小条,因为它同时在服务两边——GPU 在写后台缓冲、扫描输出在读前台缓冲——GPU 一忙扫描输出就 underrun,原因就是这个争用。徽章 1 vsync 中断锁住帧缓冲地址,2 GPU 发出 fence,3 翻页入队,4 扫描输出结束,5 下一个 vsync 让后台缓冲上台。越过徽章 5,面板就重复上一帧。模板:templates/diagrams/frame-pipeline.svg
CROSS-CORE CALLS · WHO WAITS FOR WHOM IPI · wakes another core's hardirq acknowledgement CPU 0 holds the lock, sends the IPI CPU 1 wants the same lock CPU 2 idle, answers at once CPU 3 irqs off in a long section spin_lock() flush_tlb_mm() · waits for every ack unlock spinning · burning cycles, not sleeping acquires flush_tlb_func() irqs off · a long critical section of its own flush_tlb_func() smp_call_function_many() the last ack — the one CPU 0 was waiting for 0 5 10 15 20 25 30 35 40 µs CPU 0 blocked 24 µs — set by the slowest responder, not the average CPU 1 spun 30 µs for a lock it could not have influenced One core with interrupts disabled sets the pace for every core that needs an ack from it. That is the whole reason long irqs-off sections are a system property, not a local one. Per-CPU data needs none of this: no other core can name the variable, so there is no lock, no IPI and no ack — provided the thread cannot migrate between get_cpu() and put_cpu(). Draw the ack arrows, not just the IPI arrows. A fan-out alone reads as fire-and-forget; the acks are what turn it into a wait.
cross-core calls · who waits for whom跨核调用 · 谁在等谁 Four CPU lanes on one microsecond axis. CPU 0 holds a spinlock and sends an IPI to the others, then waits for every acknowledgement. CPU 3 had interrupts disabled for a long stretch, so its ack arrives last and sets how long CPU 0 blocks. Draw the ack arrows, not just the fan-out: a fan-out alone reads as fire-and-forget, and the acks are what turn it into a wait. Template: templates/diagrams/multicore-calls.svg. 四条 CPU 泳道共用一根微秒轴。CPU 0 拿着自旋锁、向其余核发 IPI,然后等每一个应答。CPU 3 有一段长时间关中断,它的应答最晚到,于是 CPU 0 阻塞多久由它说了算。应答箭头必须画出来:只画扇出读作发完就走,画上应答才成为一次等待。模板:templates/diagrams/multicore-calls.svg
PANEL POWER SEQUENCE · RAILS, RESET, COMMANDS, BACKLIGHT not to scale · the brackets carry the real numbers panel_funcs->prepare() enable() owned by VCC_IO 1.8 V · always first VCC_3V3 3.3 V panel supply VDD_MIPI D-PHY rail REFCLK 24 MHz RESET_N active low DSI link lane state undriven LP-11 · ready for commands DCS init sequence init seq on BL_EN PWM + enable t1 ≥ 10 ms · supplies stable → reset release t2 ≥ 10 µs t3 ≥ 5 ms · reset → first DCS t4 ≥ 120 ms · sleep-out → backlight REFCLK must already be running when reset rises, or the panel latches its state from a clock that is not there. Power-down is the exact reverse of this figure, every step. Each broken constraint has its own bench symptom: t1 short → panel never answers; t3 short → the init sequence is swallowed; t4 short → a white flash at every boot — the one people ship.
panel power sequence上电时序 · 屏 Rails, clock, reset, link state, init commands and backlight, laid out by event rather than by linear time — the constraints span four orders of magnitude, so a true-scale axis would render the 10 µs reset pulse as zero pixels. The brackets carry the real numbers with their inequality signs, and the bar along the top says which panel callback owns which stretch. Power-down is the exact reverse, every step, including the waits. Template: templates/diagrams/power-sequence.svg. 电源轨、时钟、复位、链路状态、初始化命令、背光,按事件排而不按线性时间——约束跨了四个数量级,按真实比例画的话 10 µs 那段复位脉冲是 0 像素。括线带着不等号给真实数字,顶上那条横条说明每一段归哪个面板回调管。下电是严格逆序,每一步都要,包括那些等待。模板:templates/diagrams/power-sequence.svg
WIDTH WITH A UNIT · THE SAME PROFILE, DRAWN TWICE a box has two dimensions and most diagrams spend only one of them. here the horizontal one is doing work: it is the share of the profile that frame accounted for. AS A CALL GRAPH · WIDTH MEANS NOTHING main handle_request background_flush parse_json db_query render memcpy net_recv write every box is as wide as its name happens to be. that dimension is empty. it costs nothing to fill. the graph is not wrong — it answers “who calls whom”. it just cannot answer “where did the time go”. AS A FLAME GRAPH · WIDTH IS SHARE OF SAMPLES main 100% handle_request 78% background_flush 22% parse_json 31% db_query 34% render 13% write 19% memcpy 12% net_recv 28% the widest plateau, not the tallest tower 0% 50% 100% share of samples — not elapsed time application code library kernel the one worth acting on the horizontal axis is share of samples, so neighbouring boxes are not sequential. two boxes side by side did not run one after the other — they are sorted by name, which keeps the shape stable between runs. reading a flame graph left to right as a timeline is the single most common way to misread one. the vertical axis is stack depth, not duration. a tall thin tower is a deep call chain that cost almost nothing, and it is exactly what the eye is drawn to first. a profile with no wide plateau is telling you the cost is spread thin. colour here groups frames by where the code lives. random colour is the usual convention for this figure type, and it spends a whole dimension on nothing. the percentages are an illustrative profile, chosen so the arithmetic adds up. the shape is the lesson, not the numbers. Flame graph · width has a unit
runtime · width with a unit运行时 · 宽度带上单位 A box has two dimensions and most diagrams spend one. The same profile is drawn twice here: as a call graph, where every box is as wide as its name happens to be, and as a flame graph, where width is share of samples. The horizontal axis is not time — neighbouring boxes did not run one after the other, and reading it left to right as a timeline is the most common way to misread one. A tall thin tower is a deep chain that cost nothing, and it is what the eye finds first. Template: templates/diagrams/flame-graph.svg. 一个方块有两个维度,大多数图只花掉一个。同一份采样在这里画了两遍:画成调用关系图,每个方块的宽度由名字长度决定;画成火焰图,宽度就是采样占比。横轴不是时间——相邻两块并没有先后关系,把它从左往右当时间线读,是这类图第一号误读。又高又细的塔是一条几乎不花时间的深调用链,而它恰恰最先抓住眼睛。模板:templates/diagrams/flame-graph.svg
A QUEUE IS NOT A PROPORTION · THE LAST 20% OF LOAD IS NOT 20% OF THE TROUBLE the three panels are the same server at three loads. the curve underneath is why the third one looks the way it does, and it is the part a queue drawing usually leaves out. 50% busy half the time it is idle server one at a time arrivals 1 waiting the queue empties between arrivals 80% busy the usual production target server one at a time arrivals 4 waiting four waiting, and it feels fine on a graph 95% busy “we still have headroom” server one at a time +10 arrivals 19 waiting nineteen waiting. nothing broke — it just queued AVERAGE WAIT AGAINST UTILISATION · ONE SERVER, RANDOM ARRIVALS 0% 20% 40% 60% 80% 100% 10× 15× 20× wait the knee 1× at 50% 4× at 80% 9× at 90% 19× at 95% going from 50% to 80% busy costs four times the wait. going from 80% to 95% costs another five times on top of that. the axis is linear; the experience is not. this shape is one server with random arrivals. a real system with bursty arrivals bends earlier and harder, so treat the curve as the floor of the bad news rather than the estimate. the three panels above cannot make this point on their own — a reader who sees only queues believes a busy system is a proportionally slower one. the curve is what says otherwise. the same shape governs an interrupt handler, a ring buffer and a thread pool. what changes between them is what happens after the queue is full, not the shape of the approach. Queue pressure · the knee
runtime · the knee, not a proportion运行时 · 那个膝点,不是比例 Three queues at three loads, and underneath, the reason the third one looks like that. Going from 50% to 80% busy costs four times the wait; going from 80% to 95% costs another five times on top. The axis is linear and the experience is not, which is exactly what a picture of queues alone cannot say. The shape assumes one server and random arrivals, so a real system with bursts bends earlier — treat the curve as the floor of the bad news. Template: templates/diagrams/queue-pressure.svg. 三个负载下的三条队列,下面那条曲线是第三格为什么长那样的原因。从 50% 忙到 80% 忙,等待变成四倍;从 80% 到 95%,在此之上再乘五倍。轴是线性的,体验不是——而这恰恰是只画队列说不出来的事。这条形状的前提是单服务台、随机到达,真实系统有突发,弯得更早——把它当坏消息的下限,别当估计值。模板:templates/diagrams/queue-pressure.svg
05 · for product demos05 · 产品展示

Product mocks 产品 mock

Window skeletons are the highest-yield figures: a browser frame, a terminal, a phone. Real labels beat gray placeholder bars — give the mock one orange action and let everything else stay quiet. 窗口骨架是性价比最高的图:浏览器框、终端、手机框。真实文字标签比灰色占位条更可信——给 mock 一个橙色动作,其余保持安静。

acme.dev/overview Acme Cloud Overview Deployments Logs Billing Production overview Last 30 days · region us-east Deploy now Requests 4,218,304 +12% p95 latency 182 ms −9 ms Error rate 0.42% +0.05 Traffic May 12 May 26 Jun 9 Top services api 42% worker 31% web 18% cron 9%
browser mock · saas浏览器 mock · SaaS The §10 browser skeleton with a real product inside: cream sidebar with one orange-tint active item, stat cards with real numbers, a single blue chart series, one orange CTA. §10 浏览器骨架装进真实产品:奶白侧栏配一个橙 tint 选中项,stat 卡用真实数字,图表只用一条蓝色系列,唯一的橙色 CTA。
design-review — zsh bin/design-review --critic demos/anthropic-design/diagrams.html verify.py ............ OK (32 checks · bilingual pass) visual-audit ......... OK (0 errors · 0 warnings) screenshot ........... shots/diagrams-2026-06-11.png critic ............... 93 / 100 — ship it git commit -m 'feat: diagram gallery' [main 5f2c81a] feat: diagram gallery 3 files changed, 1841 insertions(+)
terminal mock · cli终端 mock · CLI Dark panel, mono type, green prompt, one orange line for the verdict. The legal use of a dark fill: neutral ink, not a saturated hue. 深底、等宽字、绿色提示符,结论行给橙色。深色满填合法的前提:中性墨色,不是饱和色相。
9:41 Runs 3 Search runs A api · run #4821 passed · 2m 14s W worker · run #4820 running · step 3 / 7 G gallery · run #4819 passed · 4m 02s D docs · run #4818 retried · flaky gate Home Runs Settings
phone mock · mobile手机 mock · 移动端 Line-art frame, cream screen, solid avatar circles carrying the four category hues. The active tab is the only orange text. 线稿外框、奶白屏幕,实心头像圆承担四个类别色。选中 tab 是唯一的橙色文字。
BEFORE 3 errors −38% time to answer AFTER One setting per row Defaults that explain themselves Search across every panel Save changes
before / after · redesign前后对比 · 改版 Two window minis and one solid badge between them stating the measured win. The before side earns its clutter; the after side earns its calm. 两个迷你窗口,中间一枚实心徽章写明可度量的收益。改版前的拥挤和改版后的克制都画到位,对比才成立。
ops.acme.dev/board Deploys this week 38 +6 Change failure rate 2.1% −0.4 MTTR 14 min −3 min Queue depth 112 +18 Deploys per day peak 11 Mon Wed Fri Sun Run share by service 12.4k runs / week api 45% web 30% cron 15% batch 10%
dashboard mock · ops仪表盘 mock · 运维 Stat cards on top, one chart per question below. Bars stay blue except the single orange peak; the donut splits by the four category hues with its legend on the right. 上排 stat 卡,下面一图回答一个问题。柱子保持蓝色,只给峰值一根橙柱;环图按四个类别色切分,图例放右侧。
06 · for talks & reports06 · 演讲与汇报

Slides and reporting 演讲汇报图

A slide gets one idea per figure: a big number, a single highlighted bar, a roadmap with today marked. Charts default to soft blue; orange appears once, where you want the room to look. 一页幻灯片一个观点:大数字、单根高亮柱、标出"今天"的路线图。图表默认柔蓝;橙色只出现一次,落在你想让全场看的地方。

92% of pages ship with at least one diagram的页面至少带一张图发布
faster review when the claim is drawn, not described评审提速——观点画出来而不是写出来
23 copy-ready figures in this gallery张可直接复制的图在本页
deploys / month 96 150 120 180 210 170 Jan Feb Mar Apr May Jun
stat + bars · single seriesstat + 柱图 · 单系列 Big numbers carry the claim; the chart backs it. Single-series charts stay blue — the one orange bar is this month's story. 大数字陈述观点,图表提供证据。单系列图保持蓝色——唯一的橙柱就是本月的故事。
today design tokens four gates 16 canonicals diagram craft multi-critic learning loop gallery v2.0 Q1 · foundations Q2 · canonical library Q3 · evaluators Q4 · scale-out
roadmap · quarters路线图 · 季度 One hue per quarter, solid dots for shipped milestones, a hollow dot for the one still ahead, and a dashed line marking today. Hollow means upcoming — the only place rings are allowed. 一个季度一个色相,已交付的里程碑用实心点,唯一未到的用空心点,虚线标出今天。空心只表示"未来"——这是环形唯一被允许的位置。
2025 2026 +24% Q1 Q2 Q3 Q4
grouped bars · yoy分组柱图 · 同比 Two series, two hues, legend on top where the eye starts. The only annotation sits on the bar that closes the argument. 两个系列两个色相,图例放顶部。唯一的标注落在收尾论点的那根柱子上。
Visitors 48,200 42% Signed up 20,250 67% Activated 13,500 32% Paid 4,340
stages · conversion阶段转化 · 分层 Each stage is a tint bar with its solid edge; the conversion rate between stages rides as a solid chip. Bar length is the data — no decoration needed. 每一层是 tint 横条加实心色边,层间转化率用实心小色块标注。条的长度就是数据本身,不需要任何装饰。
Coordinator plans · delegates · merges Search worker 1 · web Search worker 2 · docs Analyse worker 3 · data Analyse worker 4 · code coordinator search workers analysis workers
hierarchy · org / agents层级 · 组织 / agents Orchestration tree: one coordinator, one hue per worker class, icon tiles instead of bare boxes. Works as an org chart by swapping the labels. Template: templates/diagrams/hierarchy.svg. 编排树:一个协调者,每类 worker 一个色相,icon tile 替代裸盒子。换掉标签就是一张组织架构图。模板:templates/diagrams/hierarchy.svg
Which figure answers this? start from the question the reader arrives with, not from the thing you want to describe. twelve questions, twelve figures. A CARD MEANT TO BE SENT ON ITS OWN · NOTHING HERE NEEDS THE PAGE IT CAME FROM what touches what, and how thick cross-section a section, with the cut line shown on a plan view what order, and what comes apart exploded-view one axis, equal gaps, numbered by assembly are these the same thing, bigger? scale-ladder two lines per hop and a real dimension on each how was it built, step by step process-steps one part drawn N times, only the new bit coloured what does it look like in each state state-triptych identical coordinates, only the colour moves what is inside this symbol abstraction-ladder open it, then fold it, with the cost on the fold which command do I actually run debug-map the path pinned under every block, green reads gold writes how far apart are these numbers magnitude-ruler a log axis, and a linear strip showing why where did the time go flame-graph width is share of samples, not a timeline what is optional, what repeats railroad bypass over, loop under, parallel rows what is each conductor pinout physical row plus the table, and which face you are on what happens as it gets busier queue-pressure the knee, not a proportion what this card does not do it says which figure to draw. it says nothing about how to draw one — that is the template library, and each name above is a file in it. anthropic-design · diagram-craft §15 · 2026-09 a figure that travels needs four things the page normally supplies for it: a title saying what it is, one line saying what it answers, a source with a date, and its own limits. all four are on this card. the test is simple and worth applying to any figure: screenshot it, send it to somebody who has not read the page, and see whether they can act on it. most of our figures fail that test, and this one is the shape that passes. Cheat sheet · travels alone
reporting · a card that travels alone汇报 · 一张能自己出门的卡 Twelve questions a reader might arrive with, each pointing at the figure that answers it. The point of the format is the test behind it: screenshot a figure, send it to somebody who has not read the page, and see whether they can act on it. Most figures fail that, because the page was quietly supplying four things — a title, a one-line purpose, a source with a date, and the limits. A card that travels has to carry all four itself. Template: templates/diagrams/cheatsheet.svg. 十二个读者可能带着来的问题,每个指向回答它的那种图。这个形式的意义在它背后那道检验:把一张图截下来,发给一个没读过这个页面的人,看他能不能据此做事。大多数图过不了,因为页面一直在悄悄替它们提供四样东西——标题、一句话说它答什么、带日期的出处、以及边界。一张要自己出门的卡,这四样得自己带上。模板:templates/diagrams/cheatsheet.svg