开局两眼一黑一幅协议长图直冲天灵。不过不怕,通道依赖这块的东西不算太多,就是稍微的繁琐了一些咱们慢慢分析就清楚了。
协议前提
AXI协议要求必须维护以下三个关系:
- 写响应必须始终跟随写事务中的最后一次写传输,也就是说bvalid必须在wlast之后才能发出。
- 读数据必须始终跟随数据的读地址。
- 通道握手必须符合通道握手信号间定义的依赖关系。
而协议没有定义通道间的其他关系,而缺乏其他关系定义意味着什么呢?也就是说平时我们附加的一些额外要求在协议本身是不care的,文档中也举例子了"
例如,写数据(理解为wvalid)可以在事务的写地址(理解为awvalid即可)之前出现在接口上。如果写地址通道比写数据通道包含更多的寄存器级,这种情况就可能发生。同样,写数据可能与地址在同一周期出现。比如实际操作中aw和恶w通道的出口都进行fw_bw_pipe那么出口的情况会受到阻塞情况影响,slave端(文档中统一为Subordinate端)先把谁接下来都有可能。又比如文中提到的aw和w通道打拍级数不同导致的不对齐行为,协议中都没有禁止。
但是需要注意的是,当互连单元(interconnect)需要确定目标地址空间或从属空间时,它必须重新对齐地址和写数据。这种重新对齐是必需的,以确保写数据仅在它预定的从属上有效时才被信号为有效。这里也很好理解,有数据需要通过互连模块进行分发时你总得知道要发到哪里去吧,那必然得把地址和数据进行对齐了。
而后文档中有说明了两个要求:
- 当Master(文中统一为Manager)发出写请求时,它必须能够提供该事务的所有写数据,而不依赖于该Master的其他事务。
- 当Master发出读请求时,它必须能够接受该事务的所有读数据,而不依赖于该Master的其他事务。
所以在结构设计时,我们才经常需要保证有读buffer和写buffer。当然如果外部的SOC为各Master端提供了ostd*burst*Bytes的缓存能力,那么在Master端内部也可以不加这buffer。
接口前提
AXI协议本身属于握手接口,为了防止死锁情况,必须遵守握手信号之间存在的依赖规则:
- 发送信息的AXI接口的VALID信号不得依赖于接收该信息的AXI接口的READY信号。
- 接收信息的AXI接口可以等待检测到VALID信号后才使能其相应的READY信号。
而在READY有效前使能VALID是可以的,在检测到相应的VALID之前使能READY也是可以接受的。这其实就是之前在握手专栏里说过的,valid不能看ready,ready可以看valid。
通道间依赖关系
上面的前提是通道内的依赖关系,之后就是协议中规定的通道间的依赖关系,图里有两种箭头:
- 单头箭头指向表示可以在箭头开始的信号有效之前或之后使能的信号。
- 双头箭头指向表示只有在箭头开始的信号有效后才能使能的信号。
可以理解为,单箭头不存在依赖关系,双箭头存在依赖关系,而没有箭头则建议不要有依赖关系。
那么我们先看比较简单的读通道AR和R之间依赖。
读通道间依赖关系
- Master在使能ARVALID之前不得等待Slave ARREADY有效。
- Slave可以在使能ARREADY之前等待ARVALID。
- Slave可以在ARVALID有效之前使能ARREADY。
- Slave必须等待ARVALID和ARREADY都被使能(即AR通道握手)后才能使能RVALID,以表示有效数据可用。
- Slave在使能RVALID之前不得等待Master使能RREADY。
- Master可以在使能RREADY之前等待RVALID有效。
- Master以在RVALID有效之前使能RREADY。
没有啥可说的,这就非常合理的要求,搁谁来做这个协议都得这么搞。
写通道间依赖关系
写通道比都通道就复杂很多了,主要是写通道有三个AW/W/B,搞不好就容易出事。而且AXI3和AXI4中三个通道的依赖关系还有点差别,先看AXI3的。
AXI3
AXI3要求的写通道依赖关系是这样的,具体到每一条要求:
- Master在使能AWVALID或WVALID之前不得等待Slave使能AWREADY或WREADY。
- Slave可以在AWVALID或WVALID,或两者都被使能之前使能AWREADY。
- Slave可以在AWVALID 或WVALID,或两者都没有被使能之前使能AWREADY(还是awready使能与否关不关心管发送端状态都可以)。
- Slave可以在AWVALID或WVALID,或两者都被使能之前使能WREADY。
- Slave可以在AWVALID或WVALID,或两者都没有被使能之前使能WREADY(同样,wready使能与否关不关心管发送端状态都可以)。
- Slave必须等待AWVALID和AWREADY,以及WVALID和WREADY都被使能后才能使能BVALID。 Slave还必须等待 WLAST被使能后才能使能BVALID。等待是必需的,因为写响应 BRESP 必须只在写事务的最后一次数据传输后被信号(但是Master接到的bresp不一定,这种情况一般是error集中在innerConnect处理,innerConnect给Master返回假的bresp)。
- Slave在使能BVALID之前不得等待Master BREADY有效。
- Master可以在BVALID有效前使能BREADY。
- Master可以在BVALID有效后使能BREADY。
这样梳理一下之后就很清晰了,然后文档中也特别提醒了aw和w通道容易死锁的事情:
必须遵守这些依赖规则以防止死锁情况。例如,Master在驱动WVALID之前不得等待AWREADY使能(aw和w对齐时经常会出现这个行为)。如果Slave在使能AWREADY之前等待了WVALID,就可能发生死锁情况。
反正就是把额外的约束和对齐这些事放在一边去做,不要两头都看对面的行为,极容易出现死锁行为。
AXI4和AXI5
AXI4和AXI5定义了Slave写响应的额外依赖性。Slave必须等待AWVALID、AWREADY、WVALID和WREADY都有效后才能使能BVALID。通过发出写响应,Slave承担了对所有后续事务的写事务进行风险检查的责任。
反应在图中就是这样了,多了两条双箭头:
其他的约束项和AXI3没有区别。
当然这也导致了一个问题,AXI4和AXI5写事务依赖性的额外依赖意味着一个在接受所有写数据并在接受地址之前提供写响应的AXI3Slave不符合AXI4或AXI5协议要求。将AXI3遗留Slave转换为AXI4或AXI5需要添加wrapper确保在从属接受适当的地址之前不提供返回的写响应。