2. 回归平台需求分析与架构设计

回归平台不是把一批仿真命令塞进脚本循环,而是把验证团队每天重复、易错、难以追踪的工作,抽象成可配置、可观测、可扩展的工程系统。需求分析的第一步,是识别真实痛点:夜间回归跑完后,工程师往往面对的是散落在各处的日志、无法复现的随机种子、被覆盖的编译产物、以及“到底哪些用例失败了、为什么失败”的模糊结论。这些痛点决定了平台必须解决四类问题:任务如何被可靠地提交与调度、结果如何被结构化地采集与判定、失败如何被快速定位与复现、资源与许可证如何被公平且高效地使用。

从这些痛点出发,功能需求可以归纳为:用例注册与标签管理、编译与仿真任务的依赖编排、多工具(VCS、Verdi、覆盖率工具等)的调用封装、随机种子与参数快照、日志与波形产物归档、失败分类与重跑、覆盖率合并与报告、以及面向不同角色的查询与通知。非功能需求同样关键:平台需要支持数十到数百个并发作业,单次回归的调度开销应远小于仿真本身;任务状态必须持久化,进程崩溃后不丢失;接口要稳定,便于后续接入 CI/CD;权限与审计要能区分“谁提交、谁重跑、谁修改了用例集”。

在架构上,推荐采用分层设计,把“用户意图”和“执行细节”解耦。最上层是交互层,提供命令行、Web 页面或 API,负责接收回归请求、展示结果;第二层是编排层,负责把一次回归拆解为编译、仿真、覆盖率收集等任务,并维护依赖关系;第三层是执行层,由调度器把任务分配到具体计算节点,调用 EDA 工具;最底层是资源与数据层,管理许可证、存储、数据库和日志归档。模块边界要清晰:用例管理模块只关心“有哪些用例、标签是什么”,不关心仿真器怎么启动;调度模块只关心“哪个任务在哪个节点上跑”,不关心日志里具体报什么错;结果分析模块只消费结构化结果,不直接解析原始仿真输出。

回归平台分层架构与模块边界 交互层 CLI / Web / API 回归请求提交 结果看板 / 通知 权限与审计 编排层 用例注册与标签 test_id / tags / seed 依赖编排 compile → sim → cov 任务拆分与队列 优先级 / 重跑策略 参数快照 seed / plusargs 执行层 调度器 LSF / Slurm / 本地 工具封装 VCS / Verdi / 覆盖率 计算节点 CPU / 内存 / 许可证 日志采集 stdout / 波形 / 报告 数据与资源层 结果数据库 产物存储 许可证池 审计日志 失败反馈与重跑 模块边界清晰,层间通过稳定接口通信

这张图强调的不是“从上到下依次调用”这么简单,而是每一层只暴露必要的接口。例如编排层向执行层提交任务时,传递的是标准化的任务描述:用例 ID、编译产物路径、仿真参数、期望的退出码和超时时间。执行层返回的也是结构化结果:状态、耗时、日志路径、覆盖率文件路径。这样,当团队从 LSF 切换到 Slurm,或者从 VCS 切换到其他仿真器时,只需要替换执行层的适配器,编排层和交互层几乎不需要改动。

需求分析中容易被忽略的是“失败分类”和“重跑策略”。一个成熟的回归平台不会把所有非零退出码都当成同一种失败。它至少应区分:编译失败、仿真超时、断言失败、覆盖率不达标、环境或许可证问题。不同类别对应不同的处理路径:编译失败通常直接阻断后续仿真;超时可能需要调整超时阈值或检查死锁;断言失败需要保留种子和波形;许可证问题则应触发排队重试而不是标记用例失败。这些判断条件应在需求阶段就明确,而不是等到平台上线后再打补丁。

下面给出一份简化的需求与模块边界检查表,可作为架构评审时的输入。表中字段均为示例,实际项目应根据团队规模、工具链和合规要求调整。

需求类别 具体需求 对应模块 验收判断依据
功能 支持按标签筛选用例并提交回归 用例管理 + 编排 给定标签集,生成的作业列表与预期一致
功能 记录每次运行的种子与 plusargs 参数快照 任意历史任务可还原完整命令行
功能 失败用例自动分类并支持一键重跑 结果分析 + 调度 分类准确率可统计,重跑不重复编译
非功能 单次回归调度开销小于总仿真时间的 5% 调度器 压测 200 并发作业时调度延迟可接受
非功能 任务状态持久化,进程重启不丢失 数据库 模拟调度器崩溃后恢复,状态一致
非功能 接口稳定,支持后续接入 CI/CD API 层 提供版本化 REST 接口与回调事件

在模块边界划分上,建议遵循“数据所有权单一”原则。用例元数据由用例管理模块唯一维护,其他模块只读;任务状态由调度模块唯一写入,结果分析模块只读;日志和波形文件由执行层写入对象存储,数据库只保存路径和索引。这样做的直接好处是:当需要排查“为什么某个用例被标记为通过但覆盖率没合并”时,可以沿着数据流快速定位是调度没有触发覆盖率任务,还是结果分析没有正确读取覆盖率文件,而不是在多个模块的私有状态之间来回猜测。

架构设计阶段不必追求一次到位。可以先定义最小可用闭环:提交回归 → 调度仿真 → 采集结果 → 展示失败列表。这个闭环跑通后,再逐步加入覆盖率合并、失败分类、许可证池和权限审计。每增加一个模块,都检查它是否破坏了已有的模块边界。

最后需要强调的是,回归平台的架构设计必须为“变化”留出空间。验证环境会变、工具版本会变、用例集会膨胀、团队角色会调整。因此,接口要版本化,配置要外部化,任务描述要可序列化。一个在需求阶段就明确“哪些是稳定契约、哪些是可变实现”的平台,才能在后续的自动化与回归工程中持续演进,而不是每换一次工具就重写一遍脚本。