Skip to content

Commit 34cfd29

Browse files
authored
Fix mainpipe agent bug and enhance verification coverage (#mainpipe) (#191)
LGTM
1 parent 826dd7e commit 34cfd29

4 files changed

Lines changed: 599 additions & 152 deletions

File tree

ut_frontend/icache/mainpipe/MainPipe模块验证报告.md

Lines changed: 96 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
| 验证对象 | MainPipe模块 |
88
| 验证人员 | Gui-Yue |
99
| 验证时间 | 2025-9 |
10-
| 报告版本 | V0.1 |
10+
| 报告版本 | V0.2 |
1111
| 验证框架 | Toffee测试框架 |
1212

1313
## 2. 验证对象介绍
@@ -121,7 +121,8 @@ MainPipe 在 S0 阶段依据 WayLookup 返回的命中信息、ITLB 结果以及
121121
- 功能点CP11.2 不访问 DataArray(Way 未命中): Way 未命中时仍会产生 toIData.valid,但 waymask 全零表示数据无效,命中逻辑拒绝本次结果。
122122
- 功能点CP11.3 不访问 DataArray(ITLB 查询失败): ITLB 查询失败时保持访问节奏,toIData.valid 仍为 1,同时向后级传递 ITLB 异常用于后续合并。
123123
- 功能点CP11.4 不访问 DataArray(写忙阻塞): DataArray 正在写忙(toIData.last.ready=0)时阻塞 s0_fire/fetch_req_ready,防止流水推进。
124-
- 测试用例:TC12 test_cp11_dataarray_access — 组合驱动 WayLookup、Fetch 与 DataArray ready,覆盖四种访问分支并核对 toIData/s0_fire 行为。
124+
- 功能点CP11.5 Way 3命中访问: waymask_0=0x8(Way 3命中)时流水线正常推进到S2,s2_waymasks_0_3寄存器被正确赋值。
125+
- 测试用例:TC12 test_cp11_dataarray_access — 组合驱动 WayLookup、Fetch 与 DataArray ready,覆盖五种访问分支并核对 toIData/s0_fire 行为。
125126

126127
### 3.2 Meta ECC 校验 (CP12)
127128
S1 阶段对 WayLookup 带回的 meta 与 ECC 校验码做奇偶校验,确保命中表项的元数据可靠。
@@ -149,6 +150,7 @@ S1 阶段将物理地址送入 PMP 判断执行权限、MMIO 属性,并在下
149150
功能点CP14.2 仅 ITLB 异常: 仅 ITLB 异常时输出与 s1_itlb_exception 对齐。
150151
功能点CP14.3 仅 PMP 异常: 仅 PMP 异常时输出与 s1_pmp_exception 对齐。
151152
功能点CP14.4 ITLB 与 PMP 同时异常: ITLB 与 PMP 并发时,优先保留 ITLB 异常编码。
153+
功能点CP14.5 增强信号覆盖: 跨行地址下驱动 port1 ITLB异常、backendException、itlb_pbmt非零值、waymask_1=0x8(Way 3)、isForVSnonLeafPTE等信号路径。
152154
测试用例:TC15 test_cp14_exception_merge — 设置不同异常组合,观察合并结果与优先级。
153155

154156
### 3.5 MSHR 匹配和数据选择 (CP15)
@@ -161,7 +163,7 @@ S1 阶段优先匹配 MSHR 返回的数据,避免重复访问 SRAM 并处理 c
161163
### 3.6 Data ECC 校验 (CP16)
162164
S2 对数据路径做 ECC 校验,决定是否上报 BEU 并标记 s2_data_corrupt。
163165
功能点CP16.1 无 Data ECC 错误: 数据正确且来源 SRAM 时 s2_data_corrupt 维持假。
164-
功能点CP16.2 单 Bank ECC 错误: 单 bank ECC 错误触发 s2_data_corrupt 与错误上报。
166+
功能点CP16.2 单 Bank ECC 错误: 单 bank ECC 错误触发 s2_data_corrupt 与错误上报,包括 bank 0 基本场景、跨行场景以及 bank 6 特定场景(覆盖 s2_bank_corrupt_6 评估路径)
165167
功能点CP16.3 多 Bank ECC 错误: 多 bank ECC 错误同样触发错误上报并记录全部损坏 bank。
166168
功能点CP16.4 ECC 功能关闭: ecc_enable 关闭时忽略所有 Data ECC 错误。
167169
测试用例:TC17 test_cp16_data_ecc_check — 注入单/多 bank 错误及 ecc_enable 关闭场景,验证上报路径。
@@ -187,17 +189,19 @@ S2 阶段持续监控与 MSHR 的匹配关系,决定 s2_datas 的来源及命
187189
功能点CP19.4 重复请求屏蔽: s2_has_send 防止重复请求,fire 后拉高阻止再次发送。
188190
功能点CP19.5 仅 ITLB/PMP 异常: 仅 ITLB/PMP 异常时保留原异常,不新增 AF。
189191
功能点CP19.6 仅 L2 异常: 仅 L2 corrupt 时输出 AF 异常。
190-
功能点CP19.7 ITLB+L2 同步异常: ITLB 与 L2 同时存在时保持 ITLB 优先。
192+
功能点CP19.7 ITLB+L2 同步异常: ITLB 与 L2 同时存在时保持 ITLB 优先。通过 respStall 控制 s1_fire 使 s2_l2_corrupt 可被置位。
191193
功能点CP19.8 S2 取指完成: 所有端口 s2_should_fetch 为 0 时标记取指完成(s2_fetch_finish)。
192194
测试用例:TC20 test_cp19_miss_request_logic — 覆盖 Miss/异常组合,确认仲裁、去重及异常合并逻辑。
195+
测试用例:TC20b test_cp19_7_itlb_l2_both_priority — 独立DUT实例测试ITLB+L2同时异常场景,避免流水线残留状态干扰。
193196

194197
### 3.10 响应 IFU (CP20)
195198
S2 在数据准备完毕且未被 respStall 阻塞时向 IFU 返回命中数据或异常信息。
196199
功能点CP20.1 正常命中返回: 正常命中时 toIFU.valid 与数据字段正确输出,异常位清零。
197200
功能点CP20.2 异常路径返回: 发生 ITLB/PMP/L2 异常时按端口填充 exception/pmp_mmio/itlb_pbmt。
198201
功能点CP20.3 跨行取指响应: 跨行请求时 doubleline=1,并携带第二路数据及异常状态。
199202
功能点CP20.4 RespStall 阻塞: respStall 拉高时 s2_fire/toIFU.valid 维持低,保留当前状态。
200-
测试用例:TC21 test_cp20_response_ifu — 模拟命中、异常、跨行与 respStall,检查 IFU 接口打包结果。
203+
功能点CP20.5 多地址偏移 bankSel 覆盖: 遍历 startAddr[5:3]=0~7 的8种地址偏移,覆盖 difftest 输出中各 bankSel 分支路径。
204+
测试用例:TC21 test_cp20_response_ifu — 模拟命中、异常、跨行、respStall与多地址偏移,检查 IFU 接口打包结果。
201205

202206
### 3.11 L2 Corrupt 报告 (CP21)
203207
当 L2 补回数据标记 corrupt 时,S2 需额外通过 io.errors(i) 上报,区分单路与双路场景。
@@ -270,6 +274,7 @@ S2 在数据准备完毕且未被 respStall 阻塞时向 IFU 返回命中数据
270274
| TC18 | test_cp17_metaarray_flush | 验证CP17 MetaArray冲刷功能 |
271275
| TC19 | test_cp18_s2_mshr_match_data_update | 验证CP18 S2阶段MSHR匹配与数据更新功能 |
272276
| TC20 | test_cp19_miss_request_logic | 验证CP19 Miss请求发送逻辑和异常合并功能 |
277+
| TC20b | test_cp19_7_itlb_l2_both_priority | 验证CP19.7 ITLB+L2同时异常场景(独立DUT实例) |
273278
| TC21 | test_cp20_response_ifu | 验证CP20 响应IFU功能 |
274279
| TC22 | test_cp21_l2_corrupt_report | 验证CP21 L2 Corrupt报告功能 |
275280
| TC23 | test_cp22_flush_mechanism | 验证CP22 流水线刷新机制功能 |
@@ -310,43 +315,85 @@ mainpipe/
310315
## 7. 测试结果分析
311316

312317
### 7.1 测试通过率
313-
- **总测试用例数**: 23
314-
- **通过用例数**: 23
318+
- **总测试用例数**: 24
319+
- **通过用例数**: 24
315320
- **失败用例数**: 0
316321
- **通过率**: 100%
317322

318323
### 7.2 覆盖率分析
319324

320325
#### 7.2.1 行覆盖率
321326
根据覆盖率报告分析:
322-
- **总体覆盖率**: 80.7% (1378/1708行)
323-
- **ICacheMainPipe.v**: 82.1% (906/1104行)
324-
- **ICacheMainPipe_top.sv**: 76.6% (431/563行)
327+
- **ICacheMainPipe.v**: 80.0% (904/1130行)
328+
- **ICacheMainPipe_top.sv**: 26.8% (151/563行)
325329

326330
#### 7.2.2 未覆盖代码分析
327-
未覆盖的19.3%代码主要包括:
328331

329-
**Assertion错误路径 (主要原因)**
330-
- RTL中设计的assertion检查语句未被触发
331-
- 例如:违反时序约束、非法状态组合的断言
332-
- 这些assertion是为了检测设计错误,正常功能测试不会触发
332+
##### ICacheMainPipe.v 未覆盖行分类(共226行)
333+
334+
ICacheMainPipe.v 中所有可覆盖的正常RTL逻辑行已全部覆盖。剩余226行未覆盖代码可分为两类:
335+
336+
**1. Assertion 错误路径(208行)**
337+
338+
| 行号范围 | 行数 | 描述 |
339+
|----------|------|------|
340+
| 788-797 | 10 | vSetIdx一致性断言(ftq与wayLookup不匹配时触发) |
341+
| 831-852 | 22 | bankSel计数断言 |
342+
| 882-903 | 22 | difftest bankSel计数断言(bank 1) |
343+
| 936-957 | 22 | difftest bankSel计数断言(bank 2) |
344+
| 990-1011 | 22 | difftest bankSel计数断言(bank 3) |
345+
| 1044-1065 | 22 | difftest bankSel计数断言(bank 4) |
346+
| 1098-1119 | 22 | difftest bankSel计数断言(bank 5) |
347+
| 1152-1173 | 22 | difftest bankSel计数断言(bank 6) |
348+
| 1206-1227 | 22 | difftest bankSel计数断言(bank 7) |
349+
| 1260-1281 | 22 | difftest bankSel计数断言(bank 7续) |
350+
351+
这些行位于 `ASSERT_VERBOSE_COND_` / `STOP_COND_` 保护的 assertion 块内,仅在RTL设计违规时触发。正常功能测试不会也不应该触发这些断言路径,属于设计自检代码。
352+
353+
**2. RTL生成工具产生的结构性不可达代码(18行)**
354+
355+
| 行号 | 信号名 | 不可达条件 |
356+
|------|--------|-----------|
357+
| 454 | `s2_bankSel_bankSel_13` | `bankIdxHigh[6:3] > 4'hC` |
358+
| 455 | `s2_bankSel_bankSel_14` | `bankIdxHigh[6:3] > 4'hD` |
359+
| 593 | `bankSel_bankSel_5_13` | `bankIdxHigh[6:3] > 4'hC` |
360+
| 602 | `bankSel_bankSel_6_14` | `bankIdxHigh[6:3] > 4'hD` |
361+
| 629-630 | `bankSel_bankSel_13/14` | `bankIdxHigh[6:3] > 4'hC/D` |
362+
| 650-651 | `bankSel_bankSel_1_13/14` | `bankIdxHigh[6:3] > 4'hC/D` |
363+
| 671-672 | `bankSel_bankSel_2_13/14` | `bankIdxHigh[6:3] > 4'hC/D` |
364+
| 693-694 | `bankSel_bankSel_3_13/14` | `bankIdxHigh[6:3] > 4'hC/D` |
365+
| 714-715 | `bankSel_bankSel_4_13/14` | `bankIdxHigh[6:3] > 4'hC/D` |
366+
| 737 | `bankSel_bankSel_5_14` | `bankIdxHigh[6:3] > 4'hD` |
367+
| 759 | `bankSel_bankSel_6_13` | `bankIdxHigh[6:3] > 4'hC` |
368+
| 783-784 | `bankSel_bankSel_7_13/14` | `bankIdxHigh[6:3] > 4'hC/D` |
369+
370+
**不可达原因分析:**
371+
372+
这18行均为 `bankSel_*_13``bankSel_*_14` 信号,其条件要求 `_bankSel_bankIdxHigh_T_*[6:3] > 12``> 13`。根据RTL计算链:
373+
374+
```verilog
375+
wire [6:0] _GEN = {1'h0, s2_req_vaddr_0[5:0]}; // 7-bit, 范围 0~63
376+
wire [6:0] _s2_bankSel_bankIdxHigh_T_1 = 7'(_GEN + 7'h20); // 范围 32~95
377+
// [6:3] 提取: 最小值 = 0100000[6:3] = 4, 最大值 = 1011111[6:3] = 11
378+
```
379+
380+
- `vaddr[5:0]` 为6位地址偏移,范围 0~63
381+
- 加上常数32后,`bankIdxHigh` 范围 32~95
382+
-`[6:3]` 位后,数值范围为 **4~11**
383+
- bankSel_13 要求 `> 12`,bankSel_14 要求 `> 13`
384+
- **最大值11永远无法满足 > 12 的条件**
333385

334-
**异常处理分支**
335-
- 极端异常情况的处理逻辑
336-
- 多重错误同时发生的处理路径
337-
- 硬件故障检测的错误恢复代码
386+
这是 CIRCT firtool(版本 1.62.1)在将 Chisel/FIRRTL 转换为 Verilog 时产生的冗余逻辑。RTL生成工具为 bank 0~14 统一生成了完整的选择器逻辑,但未对6位地址偏移宽度做常量传播优化,导致 bank 13和14的选择条件成为死代码。这属于RTL生成工具的已知局限,不是验证遗漏。
338387

339-
**初始化代码路径**
340-
- 部分复位初始化序列
341-
- 调试模式相关的初始化代码
388+
##### ICacheMainPipe_top.sv 未覆盖行分析
342389

343-
**说明**:未覆盖代码大多属于错误检测和异常处理,这些代码在正常功能验证中不应被执行
390+
ICacheMainPipe_top.sv 中大量未覆盖行为 DPI-C 自动生成的 `get_*/set_*` 信号访问函数。这些函数仅在外部通过 DPI-C 接口读写特定信号时被调用,测试框架未直接使用 DPI-C 访问的信号对应的 getter/setter 不会被执行,属于框架生成的桩函数代码
344391

345392
#### 7.2.3 功能覆盖率
346393
- **总体功能覆盖率**: 100%
347-
- **覆盖点总数**: 22 (CP11-CP22)
348-
- **已覆盖点数**: 22
349-
- **API覆盖组数量**: 8
394+
- **覆盖点总数**: 60 (CP11-CP22,共12个覆盖组)
395+
- **已覆盖点数**: 60
396+
- **所有24个测试用例均已通过mark_function进行反标映射**
350397

351398
### 7.3 覆盖率详细分析
352399
功能覆盖率达到100%,说明所有定义的功能点都被充分测试。
@@ -421,16 +468,30 @@ mainpipe/
421468

422469
#### 7.2.4 覆盖率统计总结
423470

424-
- **总覆盖点数**: 60个 (CP11-CP22)
425-
- **已覆盖数**: 59个
426-
- **功能覆盖率**: 98.33%
471+
- **功能覆盖点总数**: 60个 (CP11-CP22)
472+
- **已覆盖数**: 60个
473+
- **功能覆盖率**: 100%
474+
- **ICacheMainPipe.v 可覆盖行覆盖率**: 100%(排除208行assertion块和18行RTL工具死代码后,所有正常逻辑行已覆盖)
427475

428476
---
429477

430478
## 8. 缺陷分析
431479

432480
### 8.1 发现缺陷
433-
测试过程中未发现功能性缺陷,所有测试用例均通过。
481+
482+
#### 8.1.1 Agent代码属性名Bug(已修复)
483+
**文件**: `agent/mainpipe_agent.py` 第541-542行
484+
485+
**问题**: `monitor_s2_mshr_match_status()` 方法中使用了含非法字符(点号)的Python属性名 `self._debug_mshr_toffee.infoed_detail`,导致 AttributeError,被 try/except 捕获后返回空字典 `{}`,使 CP18 测试中 `s2_MSHR_hits_1` 始终为 False。
486+
487+
**修复**: 将属性名改为合法的 `self._debug_mshr_infoed_detail`
488+
489+
#### 8.1.2 RTL生成工具冗余代码(RTL侧问题)
490+
**工具**: CIRCT firtool-1.62.1
491+
492+
**问题**: bankSel 逻辑为 bank 0~14 统一生成选择器,但由于 `vaddr[5:0]` 仅6位宽,`bankIdxHigh[6:3]` 最大值为11,bank 13/14 的选择条件 `> 12` / `> 13` 永远无法满足。共产生18行不可达死代码。
493+
494+
**影响**: 不影响功能正确性,仅影响行覆盖率统计。建议RTL团队在后续版本中优化 firtool 的常量传播。
434495

435496
### 8.2 潜在风险点
436497
- 需要持续监控覆盖率报告,确保代码覆盖率满足要求
@@ -440,8 +501,11 @@ mainpipe/
440501

441502
### 9.1 验证完成度
442503
- √ 所有规划的功能点均已验证(CP11-CP22)
443-
- √ 功能覆盖率达到98.33%
444-
- √ 所有测试用例通过
504+
- √ 功能覆盖率达到100%(60/60 bins)
505+
- √ 所有24个测试用例通过
506+
- √ 所有24个测试用例均已完成反标(mark_function)映射
507+
- √ ICacheMainPipe.v 可覆盖正常逻辑行覆盖率达到100%
508+
- √ 不可覆盖行已分析归因(208行assertion块 + 18行RTL工具死代码)
445509

446510
### 9.2 模块质量评估
447511
MainPipe模块验证充分,功能实现正确,质量良好。模块在各种测试场景下表现稳定,满足设计要求。

ut_frontend/icache/mainpipe/agent/mainpipe_agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,8 @@ async def monitor_s2_mshr_match_status(self) -> dict:
538538
signal = self.dut.GetInternalSignal(f"ICacheMainPipe_top.ICacheMainPipe.s2_data_is_from_MSHR_{i}", use_vpi=False)
539539
s2_data_is_from_MSHR.append(signal.value if signal else None)
540540

541-
if not hasattr(self, '_debug_mshr_toffee.infoed_detail'):
542-
self._debug_mshr_toffee.infoed_detail = True
541+
if not hasattr(self, '_debug_mshr_infoed_detail'):
542+
self._debug_mshr_infoed_detail = True
543543

544544
return {
545545
"s2_MSHR_hits_1": s2_MSHR_hits_1.value,

0 commit comments

Comments
 (0)