UVM实战避坑指南:sequence-driver响应链路与寄存器模型调试
芯片验证干到一定阶段最磨人的不是SystemVerilog语法记不牢也不是UVM的类继承写错而是那种“仿真能编过、波形不动、日志一片死寂”的诡异问题。这一期UVM和SystemVerilog笔记我把最近实际项目中反复踩到的几个坑集中整理一遍包括sequence和driver之间response链路断掉导致的“只发8个包就卡死”、寄存器模型里desired value和mirrored value互相打架、Linux环境下UVM工程编译顺序错误引发的玄学故障以及几个被面试问到烂的UVM机制问题。这些东西单个拿出来都不难但串在一起就是验证工程师日常debug的真实战场适合已经跑通过基础UVM环境、正在做实际模块验证的同学参考。1. 先说清楚为什么sequence会卡死在8个包上做UVM验证的人几乎都遇到过这样一个现象driver那边明明还在跑波形也有但sequence发完若干笔transaction之后突然就不再产生新的激励仿真既没报错也没退出就那么挂着。网上很多人直接给结论说“UVM里sequence不发response就只能发8个包”这个说法方便记忆但容易误导人。UVM标准库里并不存在“硬编码最多发8个item”这个限制“8”更像是一个经验值出现在某些FIFO深度、outstanding计数上限或者自定义循环边界上。真正的问题几乎都出在sequence和driver的握手机制断了。1.1 response机制是怎么一环扣一环的先理清sequence、sequencer、driver三者的协作关系。sequence负责生成transactiondriver负责吃掉transaction并驱动到接口上。sequence发送一个item走的是start_item和finish_item这两步中间会经过sequencer的仲裁。driver那边则是循环调用get_next_item拿到一笔item就开始干活干完了调用item_done告诉sequencer“这笔活我干完了”。sequence和driver如果要交换数据比如driver要把读回的数据传给sequence走的则是另一条路driver通过rsp_port.put()或者analysis_port发送responsesequence通过get_response()来接收。注意这里有个关键点UVM的sequence_item传输机制里finish_item之后sequence并不一定自动知道driver处理完了只有调用了get_responsesequence才会阻塞等待driver的回复。这个机制本身是异步解耦的设计意图是让sequence不用每发一笔都死等driver可以流水线式地处理多个outstanding事务。但解耦也意味着任何一个环节漏了整条链就会静默卡死。尤其是“只发8个包”这个现象很多时候是生成transaction的sequence虽然一直在循环但循环里每8笔之后依赖一个response的返回值来判断下一步动作。driver没有回responsesequence就一直wait在接受response的位置上表现就是只能发8笔。1.2 不回response时谁先卡死、卡在哪要定位卡死位置第一件事是分清楚现在是“driver没有发送response”还是“sequence没有接收response”。这两个位置的表现完全不一样排查手段也不同。如果问题出在driver侧常见原因是driver用get_next_item拿到item后驱动完接口直接调用item_done但从来没有执行rsp_port.put()或者seq_item_port.put_response()。这种情况下sequence里的get_response永远等不到东西。如果问题出在sequence侧常见原因是sequence压根没有调用get_response或者调用的时机不对——比如在start_item前面就调了get_response此时上一笔的response还没产生sequence就提前跑到一条空的响应上后面的请求自然乱掉。我建议的定位套路是在sequence的循环里、driver的get_next_item后面、driver的item_done前面分别加一条uvm_info打印打上item的ID和当前时间戳。如果能看到driver打印了“get item 7”但sequence那边“send item 8”之后没有后续而driver也没有“get item 8”说明sequencer的仲裁队列已经没有新item了——是sequence被阻塞。接着看sequence阻塞在哪一行如果是finsh_item之后卡住说明它在等response如果是start_item卡住说明sequencer没有把授权发回来。一个更隐蔽的坑是response的匹配。UVM里driver发response时默认会把transaction的sequence_id和sequence关联起来但如果driver在发送response前做了clone却没有保留原transaction的sequence_id那response就找不到对应的sequence会一直挂在sequencer的response queue里没人认领。这个问题的表现和“不回response”几乎一样但错误源头完全不同。查的时候一定要看打印里response的sequence_id是不是和request一致。1.3 快速定位与修复响应链路的套路修复这类问题我一般按三步走。第一步在driver里确认是否发送了response。如果协议本身不需要回response那更省事sequence侧直接不调用get_response把等待逻辑去掉即可。第二步如果协议需要回response就必须确保driver在item_done之前或之后把response放回rsp_port。常见模板是virtual task run_phase(uvm_phase phase); forever begin seq_item_port.get_next_item(req); drive_one_packet(req); rsp new(rsp); rsp.copy(req); rsp.set_id_info(req); seq_item_port.item_done(rsp); end endtask第三步sequence侧明确接收response。如果发出去的item不求返回值那就不调用get_response并发需求一定要有个机制去拿response。repeat(count) begin uvm_do(req) uvm_info(SEQ, $sformatf(send item %0d, req.id), UVM_MEDIUM) end repeat(count) begin get_response(rsp); uvm_info(SEQ, $sformatf(get rsp %0d, rsp.id), UVM_MEDIUM) end注意response的接收频率和发送频率最好一致否则sequence_rsp队列会越积越多内存占用上去之后经常跑几个小时莫名其妙变慢根因就是这里漏了get_response。2. 寄存器模型三值desired、mirrored、actual到底谁是谁寄存器模型是UVM里另一个让很多人头疼的地方。尤其是“镜像值”这个概念刚接触时特别抽象。很多人写寄存器测试就是reg_block.reg_a.write(status, data)写完就完事直到某天发现用寄存器模型读回来的值和波形上DUT的输出对不上才开始怀疑寄存器模型内部那套缓存机制到底在干嘛。2.1 三个值的定义和生命周期UVM寄存器模型里每个寄存器字段维护了三个值搞清楚这三个值大部分寄存器模型的坑就解掉一半。desired value你期望硬件寄存器变成的值。调用write任务时传入的data会先被写入desired value然后再通过总线操作映射到DUT。mirrored valueUVM认为此刻硬件寄存器里的值。它是在前门访问或后门访问后由寄存器模型自动更新的一块影子缓存。actual valueDUT内部真实寄存器此刻的值。这个值只能通过总线读操作或后门peek获得UVM本身并不知道除非你去读。写操作的意义是“让actual变成desired”读操作的意义是“让mirrored尽量逼近actual”。这三者的关系我习惯用对账来类比desired是财务账上计划要花的钱mirrored是财务账上已经记账的余额actual是银行账户里真实的余额。记账记得好不好决定了你对账时能不能发现问题——寄存器模型的作用就是帮你做这套自动对账。前门访问时UVM通过adapter把寄存器操作转换成总线transaction。写操作会走一个“预测”流程把更新的值同步到mirrored value读操作也会用读回的数据去更新mirrored value。这个自动同步依赖两个前提adapter的reg2bus和bus2reg实现正确以及predict机制是打开的。任何一个前提不满足镜像值就会失真。2.2 什么情况下镜像值会“骗人”实际项目里镜像值不可信的场面太多了。首当其冲的是硬件自带清零或自动翻转的寄存器。比如一个中断状态寄存器读一次硬件就自动清零。你用寄存器模型读它UVM会把读到的1和0都更新进mirrored value从模型视角看状态位是0但DUT里中断信号可能还在pending。这种场景下依靠mirrored value做判断一定会误判。另一种高发场景是后门访问与预测机制不匹配。peek和poke是UVM提供的后门访问方式直接操作DUT内部信号不经过总线协议。问题是poke写完之后默认不会自动更新mirrored valuepeek读完之后同样不会更新除非你显式去调用预测相关的方法。很多人以为“既然能直接看到寄存器镜像值肯定也是准的”这是误解。后门操作绕过adapter的同时也绕过了UVM的自动预测链路。还有一种更隐蔽的情况多个sequence并发写同一个寄存器。寄存器模型的自动预测基于每次操作时的最新desired value如果两个sequence各自持有自己的寄存器句柄A写0、B写1最终镜像值到底是多少取决于predict被调用的顺序。你以为写1成功了其实可能是写0后发起的predict把它覆盖了。值写操作后读操作后后门poke后后门peek后desired value更新为写入值不变不变不变mirrored value自动预测更新更新为读回值默认不更新默认不更新actual value取决于DUT可通过读回值推断更新可获取最新值2.3 mirror、poke、peek的正确使用姿势解决镜像值脏数据常见手段是按需同步。如果你要基于寄存器模型判断硬件当前状态不要直接用mirrored value下结论主动调用reg.mirror(status)发起一次总线读操作把镜像值强制刷新一遍。trivial但很多人图省事不去调。如果目标是等待某个硬件自动清零的中断寄存器那更别用mirrored value直接在sequence里循环执行前门读比较actual值。我这边的推荐模板是do begin reg_inst.read(status, read_data); end while (read_data MASK);如果是后门访问场景用peek读回最新硬件值比用mirrored value靠谱得多。用poke做配置写入时如果后续还有前门读操作依赖这个配置值建议在poke之后调用一次predict方法把期望值同步给镜像避免前门读引发多余的事务。还有一点经验寄存器模型里Xpredict选项要谨慎对待。默认情况下如果总线读回的数据中有X态predict会拒绝更新mirrored value保持旧值。这在某些仿真阶段是好事但如果是做X态传播检查反而会掩盖问题。要根据项目X态策略来决定要不要关闭Xpredict。3. Linux环境下从零搭一个UVM验证工程很多人在Windows上或者个人环境的IDE里写UVM写得很顺一换到公司的Linux服务器上就各种编译不过。倒不是SystemVerilog代码有问题而是UVM库的编译流程、环境变量、文件后缀、命令行参数这些“工程化细节”没接上。UVM本身是一个库不是一个独立的可执行文件你得先把它编进仿真器里你的testbench才能用。3.1 编译顺序和环境变量错一个就全错常规的Linux仿真环境里UVM库的编译顺序大概是这样的先把UVM库源码uvm_pkg.sv、uvm_macros.svh等和你的DUT文件、testbench顶层文件一起交给仿真器编译。但有几个顺序问题是新手最容易踩的。第一个问题是include路径。UVM源码里大量使用include uvm_macros.svh这类相对引用如果你的编译命令里没有加incdir$UVM_HOME/src仿真器根本找不到这些宏定义文件。我见过最离谱的情况是把UVM源码全部复制到自己的项目目录里硬编结果版本混杂宏重复定义报错信息完全看不懂。正解是把UVM_HOME作为环境变量维护起来编译命令里统一引用。第二个问题是编译粒度。UVM库建议作为独立编译单元先编一次编完生成一个编译产物后续每次跑用例直接复用而不是每个testbench都重新编译一遍UVM源码。这能省掉大量编译时间。很多商业仿真器提供UVM的预编译库直接通过-uvm开关或类似选项引入比自己编源码省心很多。第三个问题是timescale。SystemVerilog文件里如果没有合理的timescale声明UVM里很多时间相关的语义会变得不可预测。UVM库源码本身有时序控制逻辑如果编译时timescale缺失仿真器会按照默认timescale处理极易出现sequence里延迟和真实时间对不上的问题。我建议在testbench顶层文件里统一声明timescale 1ns / 1ps并确保所有编译文件在编译命令行中的顺序是库文件在前、DUT文件次之、testbench顶层文件最后。常见的Makefile核心片段大概是这个风格UVM_HOME ? /path/to/uvm-1.2 VLOG_OPTS -sverilog incdir$(UVM_HOME)/src UVM_SRC $(UVM_HOME)/src/uvm_pkg.sv DUT_SRC rtl/module_a.sv rtl/module_b.sv TB_SRC tb/top_tb.sv compile: vlogan $(VLOG_OPTS) $(UVM_SRC) $(DUT_SRC) $(TB_SRC) vcs -debug_accessall -timescale1ns/1ps -o simv $(VLOGAN_OUTPUT)3.2 命令行启动test的常见坑UVM用例的启动方式在Linux命令行下有一个高频坑很多人直接用UVM_TESTNAMEmy_test来指定测试用例结果仿真器跑的却是默认test或者干脆报了“test not found”之类的错误。原因通常是UVM库版本或仿真器对uvm_root的初始化时机处理不一样导致从命令行传入的testname没有被正确读取到。正确做法是分两步确认。第一步确认你的my_test类已经通过uvm_component_utils注册并且继承自uvm_test或者uvm_component。第二步确认仿真器的UVM支持开关能正确传递命令行参数。不同仿真器的开关略有差异但通过plusarg方式读UVM_TESTNAME是UVM的标准行为只要UVM库编译正确就能生效。验证是否生效最快的方法是在test的build_phase第一行加一个uvm_info打印打出自己的类名。如果命令行传了UVM_TESTNAMEmy_test但打印的还是default_test那就是参数传递链路断了。这时检查仿真器编译时是否真正把UVM库编进去、有没有和其他同名类混淆基本能定位。还有一个经常被忽略的坑是phase超时。命令行启动test没问题但仿真跑一会儿就报phase timeout很多人第一反应是改timeout参数但根因往往是test里某个组件在run_phase里没有正常结束比如driver的forever循环没退干净。这个和时间参数无关是设计缺陷。启动用例后先看清楚是“跑不完”还是“超时”对症下药。3.3 调试技巧日志、波形、断点怎么配合Linux下没有图形化IDE很多人不适应。我的习惯是三层配合第一层用uvm_info的verbosity控制日志粒度第二层用波形文件定位信号级问题第三层用仿真器的交互式断点做精准调试。日志层面UVM_VERBOSITY可以精确控制打印量。排查问题时用UVM_VERBOSITYUVM_DEBUG把sequence、driver的transaction流完整打出来跑回归时用UVM_VERBOSITYUVM_LOW减少日志量。不同仿真器的宏名可能略有不同但UVM_VERBOSITY这个plusarg是一致的。波形层面UVM的transaction级信息在fsdb或vpd里默认不一定完整特别是sequence和driver之间的握手上有时候需要额外加uvm_transaction_recorder或者自定义的transaction monitor才能看到sequence_id和transaction流。如果波形里看不到sequence的item流直接看信号波形会非常痛苦。我建议在环境的scoreboard里挂一个transaction monitor把sequence发出的每一次请求和driver返回的每一次response都记录下来这样波形里既能看信号又能对照transaction。断点层面仿真器的交互模式里可以针对SystemVerilog对象的字段设置条件断点比如当某个transaction的地址等于特定值时停下来。这个能力在处理偶发bug时尤其有用。跑回归发现1000次用例挂了3次用随机种子复现后在关键write操作处加条件断点逐步缩小范围比暴力加打印高效得多。4. 复盘几个典型的“uvm八股”问答UVM相关的面试题在圈子里流传得很广很多问题初看是背诵题实际做项目时都能找到对应场景。这一节把几个高频问答整理出来不是给答案而是讲这些机制在实战里到底怎么用。4.1 uvm_do到底帮你做了什么uvm_do宏是UVM里最常用的sequence宏很多新手把它当成“发一个transaction”的神器但不知道它背后做了什么。宏展开后大致包含创建item对象调用start_item请求sequencer授权随机化item调用finish_item把item交给driver。这个流程看起来简单但宏的展开是有顺序依赖的——比如start_item之后如果不做随机化操作item的约束就没有生效。更深层的机制是uvm_do宏默认会把当前sequence的sequence_id、sequencer句柄等信息绑定到item上这样sequencer才知道该把response路由给谁。如果你不用宏手动create_item和start_item忘了设置sequence_id那后续的response关联就会出问题。这也是为什么我建议新手优先用uvm_do等真正理解机制后再手写start_item/finish_item。4.2 phase与objection的关系UVM的phase机制是控制仿真相位的objection则是phase退出的门闩。一个最常见的场景run_phase里创建了一个sequence执行uvm_do宏发送transaction。如果没有在begin阶段raise_objectionsequence还没跑完run_phase就可能因为已经没有其他objection被撤掉而直接结束导致sequence中途夭折。原理是UVM的phase调度器在每个phase结束时会检查当前phase是否还有objection挂着。没有任何组件raise objection时phase就会继续推进到下一阶段。所以正确的做法是在run_phase进入时raise在sequence执行完毕后drop。UVM 1.2之后保留common phaserun_phase和12个小phase的并行机制如果你的driver在run_phase里做循环而sequence在小phase里发送激励两者要避免互相干扰。简单说raise_objection只是一个“告诉调度器我还在干活”的标记不是越早raise越好关键是在你真正干活的这段时间里始终有人举着手。4.3 config_db和interface绑定的边界问题config_db传参是UVM里使用频率最高的功能之一但很多人用着用着就会遇到“路径错了拿不到值”的问题。最典型的是通过config_db传递virtual interface。virtual interface本身只是一个句柄并不包含时间尺度或物理信息必须在顶层testbench里先实例化interface再赋值给virtual interface变量最后通过config_db的set操作传给UVM组件。set和get的路径要严格对应UVM的路径字符串支持通配符比如uvm_config_db#(virtual my_if)::set(null, uvm_test_top.env.*, vif, vif)get的时候也要用匹配的路径。这里有一个容易踩的坑set操作必须在build_phase之前执行否则组件在build_phase里get的时候数据库里还没有对应的条目。在testbench顶层里set通常是在initial块里要确保这个initial块在UVM环境的build_phase触发前已经跑完。config_db传对象时也有类似的时序问题。如果你在test里build_phase里set一个配置对象给agentagent在build_phase里get的时候由于父组件的build_phase先执行所以顺序是安全的。但如果set和get发生在同一个build_phase里而且父子顺序不对就可能拿到空指针。排查这类问题我会在get之后立刻判断是否为null并打印信息用UVM的uvm_config_db自带调试宏输出整个数据库的内容能省去很多猜谜时间。这几个机制问题不算难但每一个在真实项目里都制造过不止一台“看起来跑得好好的结果某天突然崩了”的事故。理解了背后的设计逻辑面试回答是小事更重要的是你可以自己推导出调试方向。最后再分享一个我自己在处理UVM问题时的习惯一旦出现疑似“死锁”或“卡死”的现象不要急着加超时或者增大FIFO深度先用最短的用例、最少的transaction数复现再把打印粒度调到DEBUG级别把sequence、sequencer、driver三个角色的行为日志放到一起对比。大多数UVM的“灵异事件”最后都能归因到某一个对象各自为政——sequence以为自己发出去了driver以为没人给活干sequencer夹在中间一脸无辜。如果这篇笔记里有一个机制能让你少走弯路我觉得核心是把UVM的握手协议当成通信协议本身来读恭喜你已经摸到了门槛。

相关新闻

基于Java的公交车实时监控系统:架构设计与避坑指南

基于Java的公交车实时监控系统:架构设计与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 5:50:03 阅读更多 →
Claude Code卡顿真相:Spinner是本地执行栈的阻塞信号灯

Claude Code卡顿真相:Spinner是本地执行栈的阻塞信号灯

1. 从“转圈圈”到“无响应”:Claude Code卡顿不是Bug,是状态信号被误读你点下“Run”按钮,光标悬停三秒,界面右下角那个小小的Spinner图标开始旋转——然后它就再也没停下来。你等了15秒,20秒,最后只能强制…

2026/10/4 5:50:03 阅读更多 →
OpenRIG开源驾驶舱:亲手搭建贴合身体的模拟赛车座舱

OpenRIG开源驾驶舱:亲手搭建贴合身体的模拟赛车座舱

模拟赛车圈子里绕不开的一个词就是“rig”——驾驶舱。很多朋友从手柄沙发起步,玩到一定阶段就想换一套正经座舱,但一看市售成品价格,立刻又缩回去了。普通入门级驾驶舱两三千,带显示器支架和座椅滑轨的中端款四五千起步&#xff…

2026/10/4 5:49:03 阅读更多 →

最新新闻

滑动t检验原理详解与Matlab实现:时序突变点检测实战指南

滑动t检验原理详解与Matlab实现:时序突变点检测实战指南

先说清楚这东西是干什么的。滑动t检验是气象、水文、环境这类时序数据分析里非常常用的突变检验方法,核心思路很简单:把一段序列按时间顺序开两个窗口,比较这两个窗口的均值差异是否显著,如果某个时刻前后两段数据的均值出现了远超…

2026/10/4 6:18:21 阅读更多 →
从认知镜像到真理探寻器——贾子认知免疫理论视域下生成式人工智能的底层缺陷、权重秩序与治理重建

从认知镜像到真理探寻器——贾子认知免疫理论视域下生成式人工智能的底层缺陷、权重秩序与治理重建

从认知镜像到真理探寻器 ——贾子认知免疫理论视域下生成式人工智能的底层缺陷、权重秩序与治理重建 摘要 当前生成式人工智能被广泛描述为具有“惊人能力”的新型智能系统。然而,代码生成、数学计算、长文本写作、多模态处理和工具调用等表层能力,不…

2026/10/4 6:18:21 阅读更多 →
分治算法实战:最邻近点对问题的O(n log n)解法与优化

分治算法实战:最邻近点对问题的O(n log n)解法与优化

1. 为什么这个问题值得专门写一篇:从暴力法到分治法的效率鸿沟最邻近点对问题(Closest-Pair Problem)大概是计算几何领域里最“看着简单、做起来却不那么简单”的问题之一。给你平面上散落的 n 个点,找出距离最近的那两个点。你先…

2026/10/4 6:18:21 阅读更多 →
入门数据结构:一维数组

入门数据结构:一维数组

概述 本文以C语言作为示例语言,手把手教导小白数组的特性与应用 核心概念 数组:一块连续的内存,用来存放多个相同类型的数据。 下标:也叫索引,就是用来表示“数组中第几个元素”的编号。通常写在[]中来表示数组中第一个…

2026/10/4 6:18:20 阅读更多 →
AI生成内容交付前的五道审核关卡与纠错流程

AI生成内容交付前的五道审核关卡与纠错流程

1. 为什么“AI生成直接发”是个危险动作1.1 客户交付场景下,AI内容的风险到底在哪先说一个我亲身踩过的坑。去年帮一个做企业培训的客户赶一批课程文案,二十多篇稿子,我用大模型批量生成后只做了简单通读就打包发了过去。结果第三天客户那边反…

2026/10/4 6:18:20 阅读更多 →
AI Agent时代:计算、推理与数据必须重新整合的云架构

AI Agent时代:计算、推理与数据必须重新整合的云架构

1. AI Agent 时代,云为什么必须“重新整合”1.1 从一个真实场景说起:Agent 把云的短板全暴露了去年下半年我帮一个团队调一套客服 Agent,模型用的是开源 70B 量化版,部署在云主机上。单轮对话测试时延 800ms,看着还行。…

2026/10/4 6:17:20 阅读更多 →

日新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →