数字部分 2.8 Tl 原子操作

PCIe SerDes 全流程实战

数字部分——TL-原子操作

本项目聚焦于高速串行通信本身。PCIe 作为广泛应用的高速串行通信协议,其历史悠久,协议栈层次多、设计复杂;Synopsys IP 更是在工业级别上对 PCIe 协议做了完整实现。
因此,本文 不 针对数字逻辑的每一个细节展开说明;若需深入,可结合 SystemVerilog 代码与波形自行学习。

个人经验

在 SoC 与操作系统中,原子操作与中断同属核心机制,这也是专门撰写一篇介绍 PCIe Atomic TLP 的原因。

在 Linux 体系结构内,互斥锁(mutex,lock/unlock)与 CAS 锁语义不同。传统的 lock/unlock 需要对整个系统总线加以锁定;而 CAS 语义更为高效,由 PCIe 提供的 Atomic TLP 承载,可在硬件层面完成复杂的并发控制,降低系统负荷。此处仅讨论语义层面,实际实现中,操作系统及硬件平台往往会进行针对性的优化。


以下内容为O3-Pro对system verilog代码和标准文档的深度总结

1 前言

PCI Express (PCIe) 3.0/4.0/5.0 体系里,Atomic Transaction Layer Packet (Atomic TLP) 为软硬件提供了“总线级自旋锁”的能力:它让 Endpoint / Root Complex 能够直接对对端的内存地址执行 Fetch‑Add、Swap、Compare‑and‑Swap(CAS) 等原子语义,而不必再依赖传统的 锁寄存器 + 轮询 方案。


2 Atomic TLP 在标准中的定义

“AtomicOp Requests and Completions must be formatted such that the first byte of data following the TLP header is the least‑significant byte of the first data value…” — Base Spec § 2.2.2

请求类型 32 bit Operand 64 bit Operand 128 bit Operand
FetchAdd/Swap Length = 1 DW Length = 2 DW N/A
CAS Length = 2 DW Length = 4 DW Length = 8 DW

“If the Length field does not match an architected value, the Completer must handle the TLP as a Malformed TLP.” — Table 2‑12 注

此外,标准强制 地址天然对齐:32/64/128 bit CAS 必须落在 4/8/16 byte 对齐地址,否则同样判为 Malformed TLP。


3 Synopsys IP 中的 Atomic 路径

3.1 TLP 解析检查

ku5p_rtlh_tlp_check_slv.sv 第 ≈ 420 行 通过常量表枚举原子 opcode,并在收到 Header1 时立刻分类:

assign atomic_op = (tlp_fmt_type[6:0] == `FETCHADD32)
                 | (tlp_fmt_type[6:0] == `FETCHADD64)
                 | (tlp_fmt_type[6:0] == `SWAP32)
                 | (tlp_fmt_type[6:0] == `SWAP64)
                 | (tlp_fmt_type[6:0] == `CAS32)
                 | (tlp_fmt_type[6:0] == `CAS64);

紧接着做 三类约束校验

assign atomic_operand_err =
        atomic_op && !(operand32 | operand64 | operand128);

assign atomic_addr_align_err = (operand32  && addr[1:0] != 2'h0) ||
                               (operand64  && addr[2:0] != 3'h0) ||
                               (operand128 && addr[3:0] != 4'h0);

若任一条件为真,模块把 extrct_malfm_tlp_err 拉高,后端 FC 逻辑即视作 Malformed TLP 并丢弃。

3.2 Flow Control (NPH/NPD) 预算

Atomic TLP 属于 Non‑Posted Request with Data (NPD)ku5p_rtlh_fc_gen.sv 里声明:

// AtomicOp Request consumes 1 NPH + n NPD units   -- Base Spec Table 2‑42

IP 在 recovery_from_exhaustion_np 分支中对 NPD credit 低于 2 进行抢占更新(§ 2.6.1.2.d 规则),确保 128 bit CAS 仍能一次进链路。

3.3 ECRC 插入

当 Header.TD=1 且 merged_tlp_add_ecrc 置位时,ku5p_xtlh_ctrl.sv 状态机进入 S_ECRC,把 32‑bit CRC 附在最后一个 DW。若上层驱动想禁用 ECRC,可清除 DevCtl2.ECRC_EN,并观察此状态分支不再进入。


4 高速串行链路上的“原子语义”

  1. 不可分割帧
    Atomic TLP 在数据链路层视为普通 Non‑Posted,但由于 Completer 必须在写入前先读旧值,链路上永远是 Request → Completion with Return Data 对。
  2. 顺序性
    • 在同一 Traffic Class 内,表 2‑39 把 AtomicOp 归为 NPR with Data。因此 Posted Write 可以越过它避免死锁,但另一 Atomic 不能越过它。
    • 若软件需要更强顺序,可在发 Atomic 前后插入 Memory Write 并利用 PCIe No_Snoop 与 CPU fencing 保证可见性。
  3. Poison 传播
    Synopsys RTL 在 xtlh_ctrlwreq_poisoned / cpl_poisoned 检测 EP 位,满足 Base Spec § 2.7.2.2。若 Root Port 启用 Downstream Port Containment,Poisoned Atomic 会触发 DPC 并强制返回 UR/CA Completion。

5 与 SoC Cache 和操作系统的协同

5.1 Cache 一致性路径

  • LL/SC vs Atomic TLP
    CPU 的 Load‑Linked/Store‑Conditional 仅保证 片内 L1/L2 原子;跨 PCIe 必须退化成 locked 指令或驱动发出 Atomic TLP
  • 目录缓存(DCT)
    当 RC 把下行 Atomic 目标映射到 MMIO‑coherent region,Last‑Level Cache 需在 Receive Completion 时作 snoop‑invalidate;否则旧值可能仍驻留 L3,违背 Compare‑and‑Swap 语义。

5.2 OS 屏障与驱动接口

  • Linux ≥ 4.5 增加 PCI_EXP_DEVCAP2_ATOMIC_ROUTE 能力位探测;
  • 驱动可调用
pci_set_atomic_op(pdev, PCI_EXP_DEVCTL2_ATOMIC_REQ);

并在关键路径前后使用 dma_wmb()/dma_rmb();相当于 x86 的 mfence,ARM 的 dmb ish.

  • 若平台禁止 Atomic,驱动应 fallback 到 spin_lock_irqsave() + MMIO write.

6 实战:64‑bit Fetch‑Add 流程

时序 TLP 关键字段
 t0 Request Fmt/Type = FetchAdd64, Length=2DW, Addr[2:0]=000
 t1 链路层消耗 1 NPH+2 NPD credit rtfcgen_ca_npd‑‑
 t2 Completer 读 8 B 旧值,执行
 t3 Completion Byte Count=8, Status=SC, Data=旧值

Synopsys rtlh_fc_gen 在 t1 时刻把 rtfcgen_npd_diff 计数减 2;Completion 回来时 rtfcgen_incr_amt 加 1 CPID + 1 CPIH,credit 自动归还。


7 测试与调试建议

  1. 生成器:使用 pcie-tlp-gen 工具构造所有 32/64/128 bit Atomic 序列,覆盖 mis‑aligned 地址与非法 Length 以触发 rtlh_radm_malform_tlp_err
  2. 逻辑分析:在 FC 信号 rtlh_xdlh_fc_req 上打探针,确认 NPD credit 更新提前于后续 FetchAdd。
  3. 性能计数:统计 xtlh_xmt_tlp_donextlh_xmt_tlp_done_early 差值,评估 Pipeline Register 带来的额外延迟。
  4. 系统软件:在 Linux 添加 pci=noatomic 内核参数,比较锁竞争下两种代码路径的 RFO latency

8 总结

Atomic TLP 把 原子加/互换/比较交换 直接下沉至 PCIe 链路,极大降低了 NUMA‑SoC 内外同步开销。硬件需同时实现:

  • 协议层面:Length‑Operand‑Align 三重校验、流控余量抢占、Poison 处理;
  • 体系结构层面:LLC 刷新与 Memory Barrier;
  • 软件层面:驱动能力协商与错误回退。

Synopsys DWC RTL 已为这些规则提供了清晰的钩子:tlp_check_slv 负责语法合法性,rtl*_fc_* 负责 NPD credit,xtlh_ctrl 负责 ECRC/错误上报。理解这些路径,既能指导后端时序收敛,也能帮助系统软件调优 Atomic 指令的实效性。

——完