Repository navigation
zh getting started reference model
目标:减少手算长序列的负担,并把已经反复出现的创建、启动、清理集中到测试环境里。 这一步只新增两个概念:参考模型和 pytest fixture。
下面是 examples/getting_started/test_accumulator.py 中本节新增的部分;前面章节的定义继续保留:
class AccumulatorModel:
def __init__(self):
self.total = 0
def accept(self, operand):
self.total = (self.total + operand) % 256
return self.totalclass 定义一种对象。调用 AccumulatorModel() 创建它,__init__ 设置初始状态。
self 表示这个对象自身;self.total 是模型自己的累加值。
accept(operand) 按规格更新它,并返回这笔输入的期望响应。
模型不读取 DUT,不等待时钟,也不包含 Driver;它可以在普通 Python 中单独运行:
from examples.getting_started.test_accumulator import AccumulatorModel
model = AccumulatorModel()
assert model.accept(250) == 250
assert model.accept(10) == 4在环境启动前调用 agent.connect(model),Agent 就会在输入实际被接受后推进模型。
模型按接受顺序更新,不按响应到达顺序更新。请求还在提交队列里时,不应提前修改模型。
用例连接模型后可以只写 send(3),不再逐笔填写 expected。
下面是 examples/getting_started/test_accumulator.py 中本节新增的部分;前面章节的定义继续保留:
import pytest_asyncio
@pytest_asyncio.fixture
async def accumulator():
dut = TutorialDut()
agent = make_agent(dut)
agent.connect(AccumulatorModel())
try:
async with Execution(dut.backend, agents=[agent]):
yield agent
finally:
dut.close()
@pytest.mark.asyncio
async def test_model_checks_a_sequence(accumulator):
for operand in [3, 5, 7]:
await accumulator.send(operand)
await accumulator.finish(timeout_cycles=10, observe_cycles=1)
@pytest.mark.asyncio
async def test_model_checks_wraparound(accumulator):
for operand in [250, 10]:
await accumulator.send(operand)
await accumulator.finish(timeout_cycles=10, observe_cycles=1)python3 -m pytest -v examples/getting_started/test_accumulator.py -k test_model_checks-k test_model_checks 选择名称包含这段文字的两个测试;其他用例显示为 deselected。
预期 2 passed。第一条用例自动检查 3、8、15,第二条检查 250、4。
第二条不会从上一条的 15 开始,因为 fixture 默认每个测试重新执行一次。
@pytest_asyncio.fixture 把 accumulator() 登记为环境准备函数。测试形参也叫
accumulator,pytest 就会先运行这个 fixture,把 yield agent 里的对象传给测试。
因此测试里的 accumulator.send(...) 就是在调用刚才创建的 Agent。
创建 DUT、模型和 Agent
↓
进入 Execution
↓
yield agent → 执行一条测试 → 测试结束或抛出异常
↓
退出 Execution,再 dut.close()
yield 在这里是把环境暂时交给测试,等测试结束后再继续执行清理代码。
finish 保留在用例中,是因为每个场景需要的排空预算和观察长度可能不同。
实例不能关闭后重启;每个测试新建环境是本教程采用的方式。
临时删掉模型里的 % 256,重新运行两个用例。第一条仍通过,第二条应报告期望 260、
实际 4。此时有错的是模型;DUT 仍遵循 8 位规则。恢复取余后两条都通过。
模型正确性也需要用手算的短例子验证,不能因为它叫 reference 就默认绝对正确。 教学 DUT 内部通过输入历史求和,模型通过逐笔更新状态实现;两边没有互相调用。
内容由 CI 自动同步;请编辑主仓库文档。 Automatically synced by CI; edit the source documentation.
- 首页
- 教程
- 操作指南
- 参考
- 原理说明
- Home
-
Tutorials
- Learning path
- 0. Prepare your environment
- 1. Your first PASS and FAIL
- 2. Inputs and clocks
- 3. More cases and boundaries
- 4. Extract a Driver
- 5. Delayed output and a Monitor
- 6. Assemble an Agent
- 7. Models and the test environment
- 8. Pipelines, batches, and cancellation
- 9. Understand failures
- 10. Functional coverage
- Optional: out-of-order responses
- Optional: native clocks and project DUTs
-
How-to guides
- Find your task
- Simulation and events
- Verification components
- Coverage and regressions
- Migration and maintenance
- Runnable examples
- Reference
- Explanation