1. LTSSM 状态转移图
1.1 主状态跳转图
▲图 1 LTSSM 主状态跳转
1.2 子状态跳转图
1.2.1 子状态跳转总图
▲图 2 LTSSM 子状态跳转 (图片绘制 DOT 代码见附件 A)
1.2.2 Detect 子状态跳转
▲图 3 Detect 子状态转移
1.2.3 Polling 子状态跳转
▲图 4 Polling 子状态转移
1.2.4 Configuration 子状态跳转
▲图 5 Configuration 子状态转移
1.2.5 Recovery 子状态跳转
▲图 6 Recovery 子状态转移
注: Loopback.Entry
<-> Recovery.Equalization
存在,未体现在该图中。
1.2.6 L0s 子状态跳转
▲图 7 L0s 子状态转移
1.2.7 L1 子状态跳转
▲图 8 L1 子状态转移
1.2.8 L2 子状态跳转
▲图 9 L2 子状态转移
1.2.9 Loopback 子状态跳转
▲图 10 Loopback 子状态转移
1.2.10 L0 不含子状态
1.2.11 Disable 不含子状态
1.2.12 Hot Reset 不含子状态
2. 完整的状态跳转
2.1 从初始状态到指定速率
2.1.1 Init -> Gen1
Detect.Quiet -> Detect.Active -> Polling.Active -> Polling.Config -> Config.LinkwidthStart -> Config.LinkwidthAccept -> Config.LanenumWait -> Config.LanenumAccept -> Config.Complete -> Config.Idle -> Gen1 L0
2.1.2 Init -> Gen2
Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen2 L0
2.1.3 Init -> Gen3
Full equalization
Detect.Quiet -> ... -> Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen3 L0
注:Init -> Gen3 可拆分为 Init -> Gen1 ` -> Gen3,为节省篇幅,对 Init -> Gen1 详细过程进行了省略,详情请参考上文。
Bypass equlization to highest rate
Detect.Quiet -> ... -> Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen3 L0
No equlization needed
Detect.Quiet -> ... -> Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen3 L0
2.1.4 Init -> Gen4
Full equalization
Detect.Quiet -> ... -> Gen3 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen4 L0
注:Init -> Gen4 可拆分为 Init -> Gen1 -> Gen3 -> Gen4,为节省篇幅,对 Init -> Gen1 -> Gen3 过程进行了省略,详情请参考上文。
Bypass equlization to highest rate
Detect.Quiet -> ... -> Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen4 L0
No equlization needed
Detect.Quiet -> ... -> Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen4 L0
2.1.5 Init -> Gen5
Full equalization
Detect.Quiet -> ... -> Gen4 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen5 L0
注:Init -> Gen5 可拆分为 Init -> Gen1 -> Gen3 -> Gen4 -> Gen5,为节省篇幅,对 Init -> Gen1 -> Gen3 -> Gen4 过程进行了省略,详情请参考上文。
Bypass equlization to highest rate
Detect.Quiet -> ... -> Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen5 L0
No equlization needed
Detect.Quiet -> ... -> Gen1 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen5 L0
2.2 从某速率切速到指定速率
2.2.1 Gen1/2 -> Gen1/2
Gen1/2 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen1/2 L0
2.2.2 Gen1/2 -> Gen3/4/5
Full Equalization
不管之前是否曾经到过做高速率,从当前速率开始,经过 EQ 先跳转到 Gen3 L0,再到 Gen4 L0,然后到 Gen5 L0,一路跳到目标速率。可参考上文。
No equalization needed
Gen1/2/ L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen3/4/5 L0
2.2.3 Gen3/4/5 -> Gen1/2
Gen3/4/5 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen1/2 L0
2.2.4 Gen3/4/5 -> Gen3/4/5
Full Equalization
相邻两种速率间切速,例如 Gen3 < -> Gen4,Gen4 <-> Gen5,过一遍 EQ 直接切速:
GenA L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> GenB L0
Gen3 -> Gen5,中间需要先切速到 Gen4,然后切速到 Gen5:
Gen3 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen4 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen5 L0
Gen5 -> Gen3,过一遍 EQ 直接切速:
Gen5 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.Eq -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen3 L0
注: 以上为仿真观察到的现象,具体得看下 Spec 怎么讲的。
No equalization needed
Gen3/4/5 L0 -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Speed -> Recovery.RcvrLock -> Recovery.RcvyCfg -> Recovery.Idle -> Gen3/4/5 L0
3. 实战笔记
3.1 SNPS PCIe 5.0 LTSSM 状态码
▼表 1 SNPS PCIe 5.0 LTSSM 状态码
4. 附录
A. DOT 画 LTSSM 子状态转移 代码
# https://hifpga.com/fsm/ #状态机示例 digraph ltssm { "Reset" -> "Detect.Quiet" // Detect //subgraph cluster_detect { label="Detect" "Detect.Quiet" [color=greenyellow; style=filled; fontcolor=black] "Detect.Active" [color=greenyellow; style=filled; fontcolor=black] "Detect.Quiet" -> "Detect.Active" "Detect.Active" -> "Detect.Quiet" //} "Detect.Active" -> "Polling.Active" // Polling //subgraph cluster_polling { label="Polling" "Polling.Active" [color=gold; style=filled; fontcolor=black] "Polling.Compliance" [color=gold; style=filled; fontcolor=black] "Polling.Configuration" [color=gold; style=filled; fontcolor=black] //"Polling.Speed" [color=gold; style=filled; fontcolor=black] //} "Polling.Active" -> "Polling.Configuration" "Polling.Active" -> "Polling.Compliance" "Polling.Active" -> "Detect.Quiet" "Polling.Compliance" -> "Polling.Active" //"Polling.Configuration" -> "Polling.Speed" "Polling.Configuration" -> "Detect.Quiet" "Polling.Configuration" -> "Config.RcvrCfg" //"Polling.Speed" -> "Polling.Active" // Configuration //subgraph cluster_configuration { label="Configuration" "Config.RcvrCfg" [color=plum; style=filled; fontcolor=black] "Config.Idle" [color=plum; style=filled; fontcolor=black] //} "Config.RcvrCfg" -> "Config.Idle" "Config.RcvrCfg" -> "Detect.Quiet" "Config.RcvrCfg" -> "Disable" "Config.RcvrCfg" -> "Loopback.Entry" "Config.Idle" -> "Detect.Quiet" "Config.Idle" -> "L0" // L0 "L0" [color=pink; style=filled; fontcolor=black] "L0" -> "Recovery.RcvrLock" "L0" -> "Tx_L0s.Entry" "L0" -> "Rx_L0s.Entry" // L0s //subgraph cluster_L0s { label="L0s" "Tx_L0s.Entry" [color=orange; style=filled; fontcolor=black] "Tx_L0s.Idle" [color=orange; style=filled; fontcolor=black] "Tx_L0s.FTS" [color=orange; style=filled; fontcolor=black] "Rx_L0s.Entry" [color=lightblue; style=filled; fontcolor=black] "Rx_L0s.Idle" [color=lightblue; style=filled; fontcolor=black] "Rx_L0s.FTS" [color=lightblue; style=filled; fontcolor=black] //} //"L0" -> "Tx_L0s.Entry" [lhead=cluster_L0s] //"L0" -> "Rx_L0s.Entry" [lhead=cluster_L0s] // L0s_Tx "Tx_L0s.Entry" -> "Tx_L0s.Idle" "Tx_L0s.Idle" -> "Tx_L0s.FTS" "Tx_L0s.FTS" -> "L0" // L0s_Rx "Rx_L0s.Entry" -> "Rx_L0s.Idle" "Rx_L0s.Idle" -> "Rx_L0s.FTS" "Rx_L0s.FTS" -> "L0" "Rx_L0s.FTS" -> "Recovery.RcvrLock" // L1 //subgraph cluster_L1 { label="L1" "L1.Entry" [color=salmon; style=filled; fontcolor=black] "L1.Idle" [color=salmon; style=filled; fontcolor=black] //} "L0" -> "L1.Entry" "L1.Entry" -> "L1.Idle" "L1.Idle" -> "Recovery.RcvrLock" // L2 //subgraph cluster_L2 { Label="L2" "L2.TransmitWake" [color=springgreen; style=filled; fontcolor=black] "L2.Idle" [color=springgreen; style=filled; fontcolor=black] //} "L0" -> "L2.Idle" "L2.Idle" -> "L2.TransmitWake" "L2.TransmitWake" -> "Detect.Quiet" // Recovery //subgraph cluster_recovery{ label="Recovery" "Recovery.RcvrLock" [color=khaki; style=filled; fontcolor=black] "Recovery.RcvrCfg" [color=khaki; style=filled; fontcolor=black] "Recovery.Idle" [color=khaki; style=filled; fontcolor=black] "Recovery.Equalization" [color=khaki; style=filled; fontcolor=black] "Recovery.Speed" [color=khaki; style=filled; fontcolor=black] //} "Recovery.RcvrLock" -> "Detect.Quiet" "Recovery.RcvrLock" -> "Config.RcvrCfg" "Recovery.RcvrLock" -> "Recovery.RcvrCfg" "Recovery.RcvrLock" -> "Recovery.Equalization" "Recovery.RcvrLock" -> "Recovery.Speed" "Recovery.Speed" -> "Recovery.RcvrLock" "Recovery.Speed" -> "Detect.Quiet" "Recovery.Equalization" -> "Recovery.RcvrLock" "Recovery.Equalization" -> "Recovery.Speed" "Recovery.RcvrCfg" -> "Recovery.Speed" "Recovery.RcvrCfg" -> "Recovery.Idle" "Recovery.RcvrCfg" -> "Config.RcvrCfg" "Recovery.RcvrCfg" -> "Detect.Quiet" "Recovery.Idle" -> "Loopback.Entry" "Recovery.Idle" -> "Disable" "Recovery.Idle" -> "L0" "Recovery.Idle" -> "Hot Reset" "Recovery.Idle" -> "Config.RcvrCfg" // Loopback //subgraph cluster_loopback { label="Loopback" "Loopback.Entry" [color=mistyrose; style=filled; fontcolor=black] "Loopback.Active" [color=mistyrose; style=filled; fontcolor=black] "Loopback.Exit" [color=mistyrose; style=filled; fontcolor=black] //} "Loopback.Entry" -> "Loopback.Active" "Loopback.Entry" -> "Loopback.Exit" "Loopback.Active" -> "Loopback.Exit" "Loopback.Exit" -> "Detect.Quiet" // Hot Reset "Hot Reset" [color=red; style=filled; fontcolor=black] "Hot Reset" -> "Detect.Quiet" // Disable "Disable" [color=grey; style=filled; fontcolor=black] "Disable" -> "Detect.Quiet" }
参考
- PCI Express Base Spec 5.0, 6.0
- Mindshare PCI Express Technology