欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

理解 PCIe LTSSM 状态转移的笔记

最编程 2024-08-10 22:58:15
...

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 状态码

f384c45453d34a6dbdfc683e773e26e7.png




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]

																				
															

推荐阅读