AXI总线死锁排查:AW-W依赖的形成、识别与设计规避

发布时间:2026/9/8 9:51:56
AXI总线死锁排查:AW-W依赖的形成、识别与设计规避 前几天帮同事排查一个AXI总线卡死问题现象特别典型仿真跑到大约两万周期主机向从机发出一笔写请求写数据通道(W)的w_valid一直拉高可w_ready就是不置位再往下看写地址通道(AW)的aw_valid和aw_ready也全在低电平待着整条总线像被人按了暂停键。当时我下意识就说了一句“这八成是AW-W依赖。”所谓AW-W依赖就是指写地址通道和写数据通道之间形成了循环等待两侧都盯着对方先动作结果谁也没法完成握手。这是AXI总线死锁场景里最经典、也最容易踩的一类。今天这篇文章就围绕它展开讲清楚死锁是怎么形成的在波形上怎么认设计上怎么绕开。如果你做FPGA/ASIC验证、SoC集成或者自己写RTL总线这篇应该能帮你省下好几个通宵。先说句有点绝对的话AXI总线的死锁问题十个里有七个是“每个模块看起来都是对的”堆出来的。尤其是AW-W依赖这种单看主机代码没毛病单看从机代码也没毛病一组合起来就变成死锁。所以我打算按一次真实排查的节奏来讲尽量还原当时看波形、翻代码、找根因的过程而不是把AMBA协议从头念一遍。1. 一次总线“卡死”的现场还原1.1 仿真里的诡异现象先说现场。当时验证环境里有一个CPU类的主机通过AXI总线连续向从机写数据。前几笔事务都很顺利但跑到第20000周期左右仿真时间不再往前走波形上几个关键信号的状态非常固定W通道的w_data上压着一笔有效数据w_valid保持1但w_ready一直为0AW通道从曲线来看并不是突发异常而是主机根本就没把aw_valid拉起来所以从机的aw_ready当然也不会响应B通道完全沉默没有写响应回传。整体观感是主机在等从机拿走写数据从机在等主机送地址两边都没有恶意但就是卡死在原地。如果只看这个现象很容易下意识去查寄存器的时序对不对、复位有没有释放、时钟有没有停。但进一步排查会发现把w_ready强制拉高一个周期后仿真立刻恢复了主机马上发出下一笔AW整个事务链又能往下走。这说明问题不在物理层的时序而在协议层的依赖关系。“别人不给我响应我就不发下一步”这种思路单独放在任何一个模块里都合理但组合起来就可能构成死锁。后来我把波形进一步放大看到主机的状态机停在“WAIT_W_READY”这个状态从机的状态机停在“WAIT_AW_VALID”。两个状态都挺“礼貌”但谁也迈不出下一步。更折磨人的是仿真工具不会提示这里出了问题它只会继续空转直到你把仿真改成单步或者被动地发现应用层请求已经超时。这种情况下如果验证平台没有加超时检测整个回归可能跑到结束后才报错浪费大量时间。1.2 为什么AXI死锁这么隐蔽AXI总线死锁之所以难找根本原因在于AXI是通道化协议写事务被拆成AW、W、B三个独立通道每个通道都有自己的VALID/READY握手。握手规则又允许通道之间存在灵活的顺序关系这让验证人员在排查时很难一眼看出“到底是谁在等谁”。更麻烦的是普通仿真工具不会把“VALID拉高后长时间等不到READY”当成错误——它只是一个等待状态仿真会继续跑但业务层已经一动不动表面上看就像时序跑飞了一样。另一个隐蔽点在于AXI不像读事务那样有AR和R通道天然的一一对应关系。写事务的AW和W之间没有强制的先后约束从机必须通过自己的逻辑去匹配地址和数据。一旦主机和从机各自对顺序做了不同的假设依赖环就悄悄形成了。再加上多笔写事务、乱序、缓存深度不足等情况死锁触发条件往往要在特定序列下才会出现可能跑很多个case都遇不到但遇到一次就够折腾很久。这里还要区分一个概念总线忙等和总线死锁不是一回事。忙等是指某个通道暂时没有握手完成但系统整体还能在别的通道推进或者等待本身有超时机制过一阵子会恢复死锁则是等待关系形成闭环没有任何一侧能够继续推进只有外部干预才能打破。AXI死锁之所以隐蔽是因为它在波形上看起来很像“从机慢了”“主机忙了”如果不做依赖分析很容易被当成性能瓶颈误判过去。2. 先搞懂AXI写事务的“两条腿”AW与W2.1 写事务三通道与握手规则要把AW-W依赖说明白得先复习一下AXI写事务的三条通道。AW通道负责传输写地址和突发属性比如从哪开始写、写多长、每个beat多大W通道负责传输实际要写入的数据以及每笔突发的最后一个beat标志WLASTB通道则是从机在完成写操作后回给主机的响应告诉主机这笔事务到底成功了还是出错了。用寄快递来类比AW就是快递单W是包裹B是签收回执。理论上快递单和包裹可以同时到也可以一前一后到收件人必须拿着单子核对包裹信息才能确定把这箱东西归到哪个订单。AXI的握手规则里有一条很重要的原则VALID信号一旦拉高就不能依赖READY来决定自己是否有效也不允许在握手完成前撤销READY信号则可以等待VALID甚至可以提前拉高等待数据。通道之间允许多笔事务穿插、乱序。这套规则给了设计很大的灵活性但也是死锁的土壤——因为协议并不强制AW和W之间的时序关系只规定了同一ID下写事务的顺序必须和AW顺序一致这就要求各模块自己消化顺序假设。一个很多人没注意到的细节是AHB总线的写地址和写数据是绑在同一个相位里的不存在“地址等数据”或“数据等地址”的问题。AXI把写事务拆开后虽然提升了并行度但也把顺序问题抛给了设计者。很多从AHB迁移到AXI的老工程师会不自觉地沿用“先写数据、再送地址”的思维方式结果第一个死锁往往就发生在这一步。2.2 从机如何匹配AW和W从机处理写事务时通常需要同时知道两样东西才知道该把数据写到哪一是来自AW通道的地址和突发长度二是来自W通道的实际数据。为了应对“W先到”或者“AW先到”的顺序从机一般会在入口处设置AW FIFO和W FIFO缓存先到的一侧。AW通道带有AxIDW通道虽然没有ID但AXI协议要求W数据的全局顺序与AW顺序一致所以从机可以按照AW的顺序从W FIFO里依次取出对应的数据。这里的关键在于如果W数据先到了而AW还没到从机必须把W数据暂时缓存下来不能因为“没有AW就拒绝接收W”。但很多设计中从机为了省存储资源会本能地把WREADY的置位条件里写上“aw_valid为真”。从机逻辑会觉得我还没有地址你送数据来我往哪里放这个想法本身不违规问题在于它把“资源准备”和“通道握手”耦合得太紧。当上游主机又假设AW要在W发送完成之后才发时双方就进入了一个谁也无法打破的僵局。从机的匹配逻辑本身也是容易出错的地方。比如从机收到AW后需要知道突发长度才能决定接受多少个W beat而W通道的最后一个beat用WLAST表示。如果从机在AW还没到时就收到了W数据它并不清楚这笔W数据的突发长度只能通过缓存把所有可能的beat都暂时接住。这也是为什么W缓存深度设计得很浅时从机很容易在乱序场景下提前把W_READY拉低进而诱发死锁。2.3 设计里常见的隐式依赖从我的经验看AW-W依赖死锁往往不是某一个模块“故意”写出来的而是几个模块各自的隐式依赖碰在了一起。主机侧最常见的隐式依赖有两种第一种是为了简化控制逻辑把AW发送状态机放在W事务完全结束之后只有wdata全部握手成功才允许发下一条AW第二种是为了共用数据缓冲AW和W共享同一个FIFO发送AW必须等这个FIFO被W数据释放出空间。从机侧的隐式依赖也有两种一种是上面说的w_ready依赖aw_valid另一种是从机的AW FIFO和W FIFO读写逻辑互相牵扯比如AW FIFO满时就不再接收AW而W FIFO的读出又要等AW FIFO里的地址结果两边都堵死。这些依赖单独看都有设计理由但放在一个系统里就构成环。要认清这个环先把它画出来主机的“发送AW”等待主机的“W数据发送完成”从机的“接收W”等待主机的“发送AW”主机的“W数据发送完成”又等待从机的“接收W”。环一闭合任何一侧都无法推进。这其实就是经典的循环等待和数据库死锁、线程死锁是同一个模型。还有一类隐藏更深的问题来自中断或低功耗控制逻辑。比如主机在等待从机返回写响应B而从机的写响应逻辑又必须等主机结束某个低功耗请求才会发出B如果主机在等待B完成后才继续发送新的AW/W那这个环就不止涉及AW-W还会拉上B通道。因此在审查设计时不能只看AXI接口本身还要留意接口之外的跨模块握手信号它们一样可能成为死锁环的一部分。3. 经典AW-W依赖死锁是怎么形成的3.1 场景一主机把AW藏在W后面最常见的死锁场景是主机把AW藏在W后面。具体流程是这样的应用层来了一个写请求主机先把数据放到W通道w_valid拉高等待从机接收。但主机状态机规定必须等当前事务的所有W beat都握手成功才能生成下一笔AW所以aw_valid在这个时刻不会拉高。再看从机侧从机的设计是必须收到AW之后才知道这次突发的地点和长度因此在aw_valid为低时w_ready一直保持低电平。于是W通道的数据迟迟送不进去wdata_pending一直为1aw_valid也一直不置位两边就这么对着等。这里要特别注意这个场景未必发生在“同一笔事务”上也可能发生在多笔事务的交接处。比如主机已经发完了第N笔的W数据正要发第N1笔的AW但主机逻辑错误地把AW的发送条件写成了“整个写数据FIFO为空”而FIFO里还残留着一笔正在等待从机接收的数据。这时即便数据本身马上要被取走主机也会因为FIFO非空而卡住。此类问题在连续写场景下尤其容易暴露因为总有一笔数据悬在FIFO里。为了更直观理解可以想象一个自助餐厅的出餐口。客人先递上餐盘W但服务员非要看到订单号AW才肯接餐盘而客人又坚持要等餐盘被接走之后才把订单号递上去。于是服务员和客人都愣在原地谁都不先松手。这类死锁往往不需要很复杂的条件只要一次写事务中主机把AW发送放在W发送完成之后就足以触发。3.2 场景二从机FIFO在背后“使绊子”另一种容易被忽略的死锁场景是即使主机严格遵循“先AW后W”的顺序死锁依然可能发生问题出在从机的缓存资源。假设从机入口有一个AW FIFO和一个W FIFO逻辑要求W FIFO的读出必须依赖AW FIFO提供的地址信息。当W数据先一步到达并填满了W FIFO时从机的WREADY会拉低主机看到WREADY低按照信用控制逻辑认为自己应等到W通道有空位时才发送AW。而AW FIFO此时可能为空或已满但都改变不了“AW命令发不出来”的现状。结果AW在等W的空位W的空位又在等AW的地址又形成一个环。这种场景在多主从互联时更常见。比如一个AXI interconnect把来自不同主机的AW请求和W请求分别做仲裁和排队如果interconnect内部的AW仲裁与W仲裁之间存在资源依赖或者它把W通道的接收能力和AW通道的接收能力绑定在一起就很容易出现“你在等我的地址我在等你的数据”的尴尬。排查这种问题比第一种麻烦因为它涉及了不止两个模块信号之间的因果关系拉得很长。还记得我之前提到的那次排查吗第一次发现主机没有问题是从机侧看起来先做出了让步从机有两个FIFOAW FIFO深度16W FIFO深度16。坏就坏在从机的W FIFO读端口必须依赖AW FIFO输出的地址而W FIFO满了之后从机又停止接收新的W数据导致主机的信用计数器一直无法恢复。最后把W FIFO的读出逻辑改成“只要AW FIFO非空就持续读”死锁立刻解除。这种问题只靠看波形很难想到因为你得深入从机内部才能看到FIFO水位和读端条件的耦合关系。3.3 用代码把死锁“画”出来为了更直观地展示死锁我写一个简化版的SystemVerilog代码描述一个主机的错误逻辑。这个代码不是完整RTL但足以看出AW-W依赖是怎么形成的。logic [31:0] wdata; logic w_valid; logic w_ready; logic [31:0] aw_addr; logic aw_valid; logic aw_ready; logic wdata_pending; // 主机把一笔写数据放到W通道等待从机接收 always_ff (posedge clk) begin if (w_ready w_valid) begin wdata_pending 0; w_valid 0; end else if (new_wr_req) begin wdata_pending 1; wdata next_wdata; w_valid 1; end end // 主机错误地让AW发送等待W数据发送完成 always_ff (posedge clk) begin if (!wdata_pending aw_ready) begin aw_addr next_addr; aw_valid 1; end else begin aw_valid 0; end end如果从机的逻辑是“aw_valid为低时w_ready始终为低”那上面这段代码在第一次写事务时就会卡死wdata_pending一直在1w_ready一直在0aw_valid永远不会拉高。修复也很简单把AW的发送条件与wdata_pending解耦只要地址FIFO可写就发AWlogic aw_fifo_not_full; logic master_has_write_req; always_ff (posedge clk) begin if (master_has_write_req aw_fifo_not_full) begin aw_valid 1; aw_addr next_addr; end else begin aw_valid 0; end end但是只改主机还不够。如果从机仍坚持“AW不到就不收W”那么主机即便先发了AW也基本能工作因为此时AW在前、W在后顺序满足从机要求。可这样就把整个系统的正确性押在了“所有主机都严格先AW后W”这个假设上。协议没强制这个假设所以更稳健的做法是让从机把W通道的接收能力与AW是否到达解耦加一个W数据缓存把地址匹配放到缓存之后处理。4. 定位死锁的实操方法4.1 三分钟看波形抓住依赖环遇到总线卡死我不会急着翻代码而是先打开波形把AW、W这两条通道的VALID/READY信号拉出来盯着看三个组合。第一个组合是“W_VALID1且W_READY0”说明从机或interconnect没有接收W数据第二个组合是此时“AW_VALID0”说明主机没有发出AW第三个组合是“AW_VALID1但AW_READY0”说明从机的AW通道被什么堵住了。这三个组合基本能覆盖绝大多数AW-W依赖死锁。如果波形里看到“W_VALID1、W_READY0、AW_VALID0”这个状态保持了几百个周期基本可以断定问题出在主机侧主机把AW发送放在了W完成之后。此时去代码里搜aw_valid的赋值逻辑看它有没有引用w_valid、w_ready或者写数据FIFO的状态。反过来如果看到“AW_VALID1、AW_READY0但W通道没有pending数据”问题大概率在从机侧去查从机的AW FIFO是不是满了或者从机状态机是不是在等待一笔永远等不到的W。实际操作时我习惯先把波形缩放到能看清所有通道的阶段然后按“w_valid and not w_ready”作为搜索条件统计这个条件持续的周期数。如果持续超过几百周期再看此时AW通道是什么状态。很多波形工具支持表达式搜索可以直接把条件写进去几秒钟就能定位到死锁点的位置不需要一帧一帧地翻。这个方法听起来简单但在现场排查时特别能节省时间尤其是死锁发生概率不高、需要快速抓现场的时候。4.2 用断言和看门狗快速留现场仿真波形虽然能定位问题但死锁出现往往需要跑很多周期人眼盯久了容易疲劳。我习惯在验证环境中加一些轻量的看门狗逻辑专门监测通道上长时间未完成握手的情况。比如可以写一个超时计数器如果W通道的VALID和READY在N个周期内没有同时有效就打印一条错误信息并dump现场。这种做法牺牲不了多少仿真性能却能在死锁发生的第一时间把关键信号抓下来省去反复重跑的麻烦。integer w_wait_cnt; always_ff (posedge clk) begin if (w_valid !w_ready) begin w_wait_cnt w_wait_cnt 1; if (w_wait_cnt TIMEOUT_CNT) begin $error(W channel timeout: w_valid high too long without w_ready); end end else begin w_wait_cnt 0; end end同样的看门狗可以复制到AW、B、AR、R通道上。正规一点的做法是直接使用AXI VIP自带的死锁检测选项很多商用验证IP都支持配置最大等待周期超时后会通过scoreboard或assertion报错。如果项目一开始没用VIP也可以自己在testbench里加断言把超时错误引到仿真退出上避免带着错误状态继续跑下去浪费时间。这里要提醒一句看门狗计数器不能一上来就设得很小否则在正常的低功耗场景或跨时钟域桥调频时通道长时间不握手不一定是死锁反而会造成误报。我会把超时阈值设成正常最坏情况等待时间的几倍比如正常最久等100拍那看门狗就设500拍。同时要保证看门狗在复位和低功耗状态下被正确屏蔽不然很容易被干扰信号骗到。4.3 信号状态速查表为了更直观地排查我把几种典型信号状态和对应检查方向整理成一个表遇到卡死时可以直接对照。信号状态可能原因优先检查项W_VALID1, W_READY0, AW_VALID0主机在等W发送完成才发AW主机aw_valid赋值是否引用W通道状态W_VALID1, W_READY0, AW_VALID1, AW_READY0从机AW通道阻塞或从机等待W从机AW_READY为何为低内部状态机依赖AW_VALID1, AW_READY0, W_VALID0从机AW通道满主机在等AW完成才发W从机AW FIFO读端是否依赖未到的W数据B_VALID1, B_READY0主机的B通道阻塞可能影响后续写事务释放主机B通道接收逻辑是否被其他任务占据这个表不用背关键是理解“通道迟迟不握手一定要去另一条通道找原因”的思路。AXI死锁的特点就是一条通道的等待根因往往藏在另一条通道的状态里。我见过不少人只盯着W通道翻来覆去地看却忽略了AW通道早就低电平了这就是没有把“跨通道依赖”放在首要考虑位置导致的。5. 避免死锁的设计规范和修复范例5.1 协议红线通道之间不能有循环依赖在设计阶段防死锁最朴素也最有效的规则就是AW和W两个通道必须保持独立任何一方的握手条件都不能以另一方作为前提。这里说的独立不是说它们在数据语义上不能有关联而是说握手ready信号的产生不能互相等待。主机侧要保证aw_valid的断言条件不依赖W通道的w_ready或w_valid从机侧要保证w_ready的断言条件不依赖AW通道的aw_valid。如果因为存储结构必须等待那就把等待关系约束在模块内部通过FIFO水位、缓存深度来消化而不是直接和通道握手绑在一起。这条规则在AMBA AXI规范里虽然没有专门一句话点名“AW不能依赖W”但它隐含在“通道之间允许同时传输、没有固定时序要求”这个基本前提里。一旦你开始给通道间强加顺序就必须确保这个顺序永远成立并且不会形成环。现实项目里为了省一点缓存资源去破坏这个独立性后面往往要还回来十倍的人力和时间成本。审查设计时我会专门列一份检查清单第一主机的AW发送条件是否引用了W通道的握手信号第二从机的WREADY是否引用了AW通道的VALID第三AXI interconnect是否在AW和W之间共享了同一个资源且没有解耦第四是否存在跨模块的“A等B、B等A”的握手逻辑。这份清单看起来简单但能挡住大部分常见死锁。5.2 主机侧从机侧的修复方案主机侧的修复核心是“把AW发出来这件事提前”。正确的做法是在应用层发起一笔写请求的同时就把地址信息打包到AW通道上让它与W数据并行流动。如果担心多笔写事务的数据和地址错配可以通过增加写地址队列AW FIFO来解决而不是让AW等待W完成。从机侧的修复核心是“给W数据一个临时的家”。从机入口加一个深度适中的W缓存FIFO当W先于AW到达时先把数据存下来等到对应的AW到达后再从缓存中读出数据并按地址写入。这样WREADY只跟缓存水位相关不再受AW是否到达的制约。说个具体改法。错误的主机设计是“aw_valid !wdata_pending”修复后可以改成“aw_valid req_valid aw_fifo_not_full”。错误的从机设计是“w_ready aw_valid w_fifo_not_full”修复后可以改成“w_ready w_fifo_not_full”同时把W缓存里的数据标记为“尚未匹配地址”等AW到达后再做地址匹配和后续写入。这样改完无论W先到还是AW先到握手都能正常完成系统不再依赖发送方的“自觉”。修复之后最好做一轮随机化验证重点压“W先到后AW到”“AW先到后W到”“AW和W同时到”“AW被从机拒绝几拍后才到”这四类时序。很多死锁是在边界条件下才会复现的常规的连续写测试根本覆盖不到。我在实际项目里还见过一种情况主机和从机单独都通过了验证但集成到SoC后因为interconnect的插入延迟导致AW和W之间的相对顺序发生了翻转一下把死锁暴露出来。所以集成测试时也要保留这些边界场景。5.3 乱序、多笔事务下的额外注意事项如果系统里有多笔写事务在飞行防死锁的难度会上一个台阶。AXI允许不同ID的写事务有多个未完成状态但W通道没有ID字段所以W数据打进从机的顺序必须和AW顺序保持一致。从机在缓存W数据时要保证FIFO的读端能按照AW的顺序吐出数据。这里面容易踩的坑是为了支持不同主机的交错访问interconnect在W通道上做了仲裁结果把来自不同主机的W数据顺序打乱从机按照AW顺序去匹配时就永远对不上最终形成新的等待环。这种情况下建议在interconnect层面对W通道和AW通道做统一的排序管理。比如用ID号做重排序缓冲保证进入从机的W数据顺序与从机看到的AW顺序一致。如果做不到完全一致就要确保从机的W缓存足够深能够吸收所有乱序到达的W数据。还有一个容易忽视的点是跨时钟域和低功耗握手在异步桥或门控时钟场景里某个通道可能被暂停一段时间如果另一方还在等待握手超时机制会更早暴露问题。所以在做跨时钟域总线桥时尤其要检查通道间的依赖关系最好配合形式化验证或者断言把所有通道最长的等待时间都约束出上限。形式化验证对死锁检测特别有效。常规仿真只能覆盖到测试用例跑到的场景而形式化工具可以把所有可能的通道状态组合都遍历一遍直接检查是否存在“某通道VALID拉高后永远等不到READY”的路径。我参与过的几个项目里形式化工具发现过很多仿真跑不出来的死锁尤其是AW和W在不同延迟组合下的循环依赖。虽然形式化环境搭起来有点门槛但对于AXI这种规则明确的总线协议性价比相当高。6. 从AXI死锁到数据库死锁、线程死锁本质上是同一件事6.1 资源等待环的抽象一路看到这里你会发现AW-W依赖死锁和我们常说的数据库死锁、线程死锁有惊人的相似之处。数据库里两个事务分别持有锁、又申请对方持有的锁于是双双等待线程死锁里线程A拿着锁1等锁2线程B拿着锁2等锁1AXI总线里则是主机的AW发送权等着W通道释放从机的W接收权又等着AW先到。把这些场景抽象掉具体的业务和信号本质都是同一个东西多个主体各自持有一部分资源同时又在等待其他主体释放资源形成一个环状的等待图。死锁的四个必要条件——互斥、持有并等待、不可剥夺、循环等待——在AXI总线上同样成立。互斥指的是一个通道或一个缓冲在某一时刻只能被一个传输占用持有并等待是模块占着当前的握手状态不放又去等另一个握手条件不可剥夺是指VALID信号拉高后不能主动收回必须由对方READY配合循环等待就是上面画的依赖环。理解了这四个必要条件排死锁的思路就清晰了只要能打破其中任意一个条件死锁就不会出现。比如增加缓存来打破“持有并等待”或者规定通道超时强制撤销来打破“不可剥夺”。顺带一提数据库里“锁表”和“死锁”经常被一起讨论但其实是两个层次的问题。锁表更像某个事务长时间持有锁不放导致其他事务排队等待这是单向阻塞死锁则是双向等待谁也等不到对方释放必须靠超时或死锁检测来解开。AXI总线里也有类似区分一种情况是主机持续霸占AW通道不发完把后面事务全部堵住这更像“总线锁表”另一种情况就是本文讨论的AW-W依赖属于真正的循环等待。搞清楚是单向阻塞还是循环等待排查方向会完全不同。6.2 这套思路对排查其他死锁的启发有了这个抽象我在排查AXI死锁时反而不太容易被具体信号绕晕。遇到“总线卡死”我会先拿一张纸把涉及到的模块和它们等待的资源画成一个有向图标出每一个通道的VALID/READY背后到底在等谁。只要图里出现了一个闭合的环那基本就是死锁源。这种画图的方法不仅适用于总线也适用于定位复杂的互锁逻辑、握手协议、甚至分布式系统里的通信阻塞。很多所谓“诡异的卡死”最后都能在等待环上找到一个突破口。如果进一步把这套思路转成设计原则就一句话不要让任何一个握手信号在等待另一个握手信号除非你能保证这个等待不可能形成闭环。听上去简单真正做到需要从主机、从机、interconnect三个层面分别把关。主机要尽早发AW从机要用缓存消化顺序差异interconnect要保证跨主机的AW/W顺序一致。任何一层偷懒最后都可能变成仿真里的一个“死等”。最后说个我自己的习惯新模块接入SoC之前我会故意在验证环境里把从机的W接收能力设成某一阶段一直为0把主机的AW发送能力也限住然后跑一轮压力测试。这种人为制造资源紧张的做法虽然有点粗暴但往往比跑几十个正常case更能逼出死锁问题。总线死锁这玩意早点暴露一天后面就能少熬好几个通宵。

相关新闻