forked from XS-MLVP/UnityChipForXiangShan
Compare commits
9 Commits
main
...
pr-lzl-ifu
| Author | SHA1 | Date |
|---|---|---|
|
|
ebb698c251 | |
|
|
5ace2441e6 | |
|
|
ec09eb24dc | |
|
|
3825f86420 | |
|
|
8b2d55fc00 | |
|
|
4928ddd8f6 | |
|
|
c7cbe0d38d | |
|
|
f44db511d1 | |
|
|
3cad0d6bd0 |
|
|
@ -1,7 +1,7 @@
|
|||
# FrontendTrigger 单元验证
|
||||
|
||||
## 测试目标
|
||||
|
||||
| 序号 | 功能 | 名称 | 描述 |
|
||||
|------|------|------|------|
|
||||
测试目标是验证FrontendTrigger子模块的功能。
|
||||
|
||||
FrontendTrigger的功能分为两部分:断点设置和断点触发。
|
||||
|
|
@ -71,4 +71,6 @@ TBD
|
|||
|
||||
参考模型
|
||||
|
||||
文档:测试流程
|
||||
文档:测试流程
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
from .frontend_trigger_agent import FrontendTriggerAgent,BreakpointInfo, BreakpointReq
|
||||
from .frontend_trigger_agent import FrontendTriggerAgent,BreakpointInfo
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +1,85 @@
|
|||
from toffee import Agent, driver_method
|
||||
from importlib.metadata import requires
|
||||
from toffee import Agent, driver_method, monitor_method
|
||||
|
||||
from comm import info
|
||||
from ..bundle import FrontendTriggerBundle
|
||||
import difflib
|
||||
|
||||
# 设置断点的控制数据类
|
||||
class BreakpointReq():
|
||||
data = 0
|
||||
chain = False
|
||||
matchType = 0
|
||||
select = 0
|
||||
from toffee.triggers import *
|
||||
from toffee.model import *
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
|
||||
# 断点信息,一部分来自内部信号
|
||||
class BreakpointInfo():
|
||||
|
||||
@dataclass
|
||||
class BreakpointUpdateInfo:
|
||||
matchType: int # 2 bits, 0:等于 2: 大于等于 3: 小于
|
||||
select: bool
|
||||
action: int # 4 bits
|
||||
chain: bool
|
||||
tdata2: int # 64 bits
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
matchType: int = 0,
|
||||
select: bool = False,
|
||||
action: int = 0,
|
||||
chain: bool = False,
|
||||
tdata2: int = 0,
|
||||
):
|
||||
self.matchType = matchType
|
||||
self.select = select
|
||||
self.action = action
|
||||
self.chain = chain
|
||||
self.tdata2 = tdata2
|
||||
|
||||
def __str__(self):
|
||||
return f"matchType: {self.matchType}; select: {self.select}; action: {self.action}; chain: {self.chain}; tdata2: {self.tdata2:x}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class BreakpointFlags:
|
||||
tEnableVec: List[bool] # 4 elements, each is a boolean
|
||||
debugMode: bool
|
||||
triggerCanRaiseBpExp: bool
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
tEnableVec: List[bool] = [False] * 4,
|
||||
debugMode: bool = False,
|
||||
triggerCanRaiseBpExp: bool = False,
|
||||
):
|
||||
self.tEnableVec = tEnableVec
|
||||
self.debugMode = debugMode
|
||||
self.triggerCanRaiseBpExp = triggerCanRaiseBpExp
|
||||
|
||||
def __str__(self):
|
||||
return f"tEnableVec: {self.tEnableVec}; debugMode: {self.debugMode}; triggerCanRaiseBpExp: {self.triggerCanRaiseBpExp}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class BreakpointInfo:
|
||||
timing = 0
|
||||
tdata2 = 0
|
||||
tdata2 = 0
|
||||
|
||||
chain = False
|
||||
matchType = 0
|
||||
select = 0
|
||||
action = 0
|
||||
|
||||
def __str__(self):
|
||||
return f"timing: {self.timing}; tdata2: {self.tdata2}; chain: {self.chain}; matchType: {self.matchType}; select: {self.select}; action: {self.action}"
|
||||
return f"timing: {self.timing}; tdata2: {self.tdata2:x}; chain: {self.chain}; matchType: {self.matchType}; select: {self.select}; action: {self.action}"
|
||||
|
||||
|
||||
class FrontendTriggerAgent(Agent):
|
||||
def __init__(self, bundle:FrontendTriggerBundle):
|
||||
def __init__(self, bundle: FrontendTriggerBundle):
|
||||
super().__init__(bundle)
|
||||
self.bundle = bundle
|
||||
self.old_pcs = [0] * 16
|
||||
self.old_bp_flags = BreakpointFlags()
|
||||
self.cycle = int(0)
|
||||
|
||||
@driver_method()
|
||||
async def reset(self):
|
||||
self.bundle.reset.value = 1
|
||||
await self.bundle.step()
|
||||
|
|
@ -34,42 +88,155 @@ class FrontendTriggerAgent(Agent):
|
|||
|
||||
# 查看tdata_vec内部信号!从而查看断点是否正确设置
|
||||
@driver_method()
|
||||
async def set_breakpoint(self, pos: int, req: BreakpointReq, _raise:bool = True, enable:bool=True) -> list[BreakpointInfo]:
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._addr.value = pos
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._tdata2.value = req.data
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._chain.value = req.chain
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._matchType.value = req.matchType
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._select.value = req.select
|
||||
getattr(self.bundle.io._frontendTrigger._tEnableVec, f"_{pos}").value = enable
|
||||
self.bundle.io._frontendTrigger._triggerCanRaiseBpExp.value = _raise
|
||||
async def set_breakpoint_update(
|
||||
self,
|
||||
addr: int,
|
||||
bp_update: BreakpointUpdateInfo,
|
||||
bp_flags: Optional[BreakpointFlags] = None,
|
||||
):
|
||||
|
||||
assert addr < 4, "pos must be less than 4"
|
||||
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._addr.value = addr
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._tdata2.value = (
|
||||
bp_update.tdata2
|
||||
)
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._chain.value = (
|
||||
bp_update.chain
|
||||
)
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._matchType.value = (
|
||||
bp_update.matchType
|
||||
)
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._select.value = (
|
||||
bp_update.select
|
||||
)
|
||||
self.bundle.io._frontendTrigger._tUpdate._bits._tdata._action.value = (
|
||||
bp_update.action
|
||||
)
|
||||
|
||||
if bp_flags is not None:
|
||||
for i in range(4):
|
||||
getattr(self.bundle.io._frontendTrigger._tEnableVec, f"_{i}").value = (
|
||||
bp_flags.tEnableVec[i]
|
||||
)
|
||||
self.bundle.io._frontendTrigger._debugMode.value = bp_flags.debugMode
|
||||
self.bundle.io._frontendTrigger._triggerCanRaiseBpExp.value = (
|
||||
bp_flags.triggerCanRaiseBpExp
|
||||
)
|
||||
self.bundle.io._frontendTrigger._tUpdate._valid.value = True
|
||||
await self.bundle.step(2)
|
||||
|
||||
res = []
|
||||
|
||||
for i in range(4):
|
||||
bp_res = BreakpointInfo()
|
||||
bp_res.timing = getattr(self.bundle.FrontendTrigger._tdataVec, f"_{i}")._timing.value
|
||||
bp_res.tdata2 = getattr(self.bundle.FrontendTrigger._tdataVec, f"_{i}")._tdata2.value
|
||||
bp_res.chain = getattr(self.bundle.FrontendTrigger._tdataVec, f"_{i}")._chain.value
|
||||
bp_res.matchType = getattr(self.bundle.FrontendTrigger._tdataVec, f"_{i}")._matchType.value
|
||||
bp_res.select = getattr(self.bundle.FrontendTrigger._tdataVec, f"_{i}")._select.value
|
||||
bp_res.action = getattr(self.bundle.FrontendTrigger._tdataVec, f"_{i}")._action.value
|
||||
res.append(bp_res)
|
||||
return res
|
||||
|
||||
# param: pcs: 16 x pc
|
||||
# return: triggered?s: 16 x triggered
|
||||
@driver_method()
|
||||
async def check(self, pcs: list[int]) -> list[int]:
|
||||
num_instrs = 16
|
||||
for i in range(num_instrs):
|
||||
getattr(self.bundle.io._pc, f"_{i}").value = pcs[i]
|
||||
await self.bundle.step()
|
||||
self.bundle.io._frontendTrigger._tUpdate._valid.value = False
|
||||
await self.bundle.step()
|
||||
|
||||
@driver_method()
|
||||
async def set_breakpoint_flags(
|
||||
self,
|
||||
bp_flags: BreakpointFlags,
|
||||
):
|
||||
for i in range(4):
|
||||
getattr(self.bundle.io._frontendTrigger._tEnableVec, f"_{i}").value = (
|
||||
bp_flags.tEnableVec[i]
|
||||
)
|
||||
self.bundle.io._frontendTrigger._debugMode.value = bp_flags.debugMode
|
||||
self.bundle.io._frontendTrigger._triggerCanRaiseBpExp.value = (
|
||||
bp_flags.triggerCanRaiseBpExp
|
||||
)
|
||||
await self.bundle.step(1)
|
||||
|
||||
@monitor_method()
|
||||
async def monitor_breakpoint_update(self):
|
||||
if self.bundle.io._frontendTrigger._tUpdate._valid.value:
|
||||
await self.bundle.step(1)
|
||||
return self.collect_triggered()
|
||||
|
||||
@monitor_method()
|
||||
async def monitor_breakpoint_flags(self):
|
||||
cur_bp_flags = BreakpointFlags()
|
||||
cur_bp_flags.tEnableVec = [
|
||||
getattr(self.bundle.io._frontendTrigger._tEnableVec, f"_{i}").value
|
||||
for i in range(4)
|
||||
]
|
||||
cur_bp_flags.debugMode = self.bundle.io._frontendTrigger._debugMode.value
|
||||
cur_bp_flags.triggerCanRaiseBpExp = (
|
||||
self.bundle.io._frontendTrigger._triggerCanRaiseBpExp.value
|
||||
)
|
||||
|
||||
bp_flags_changed = cur_bp_flags != self.old_bp_flags
|
||||
|
||||
if bp_flags_changed:
|
||||
info(f"bp_flags changed: {self.old_bp_flags} -> {cur_bp_flags}")
|
||||
|
||||
self.old_bp_flags = cur_bp_flags
|
||||
|
||||
if bp_flags_changed:
|
||||
return self.collect_triggered()
|
||||
|
||||
def collect_breakpoint_info(self) -> list[BreakpointInfo]:
|
||||
res = []
|
||||
for i in range(4):
|
||||
bp_res = BreakpointInfo()
|
||||
bp_res.timing = getattr(
|
||||
self.bundle.FrontendTrigger._tdataVec, f"_{i}"
|
||||
)._timing.value
|
||||
bp_res.tdata2 = getattr(
|
||||
self.bundle.FrontendTrigger._tdataVec, f"_{i}"
|
||||
)._tdata2.value
|
||||
bp_res.chain = getattr(
|
||||
self.bundle.FrontendTrigger._tdataVec, f"_{i}"
|
||||
)._chain.value
|
||||
bp_res.matchType = getattr(
|
||||
self.bundle.FrontendTrigger._tdataVec, f"_{i}"
|
||||
)._matchType.value
|
||||
bp_res.select = getattr(
|
||||
self.bundle.FrontendTrigger._tdataVec, f"_{i}"
|
||||
)._select.value
|
||||
bp_res.action = getattr(
|
||||
self.bundle.FrontendTrigger._tdataVec, f"_{i}"
|
||||
)._action.value
|
||||
res.append(bp_res)
|
||||
return res
|
||||
|
||||
@monitor_method()
|
||||
async def monitor_pcs_changed(self):
|
||||
# Fetch current PC values
|
||||
cur_pcs = [getattr(self.bundle.io._pc, f"_{i}").value for i in range(16)]
|
||||
|
||||
pcs_changed = cur_pcs != self.old_pcs
|
||||
|
||||
self.old_pcs = cur_pcs
|
||||
if pcs_changed:
|
||||
cur_triggered = self.collect_triggered()
|
||||
return cur_triggered
|
||||
|
||||
def collect_triggered(self) -> list[int]:
|
||||
ret = []
|
||||
|
||||
for i in range(num_instrs):
|
||||
for i in range(16):
|
||||
ret.append(getattr(self.bundle.io._triggered, f"_{i}").value)
|
||||
return ret
|
||||
|
||||
return ret
|
||||
# param: pcs: 16 x pc
|
||||
@driver_method()
|
||||
async def set_pcs(self, pcs: list[int]) -> list[int]:
|
||||
# 输入验证
|
||||
assert len(pcs) == 16, "pcs must contain exactly 16 elements"
|
||||
assert pcs[0] >= 0, "The first element of pcs cannot be negative"
|
||||
for i in range(1, 16):
|
||||
assert (
|
||||
pcs[i] == pcs[i - 1] + 2
|
||||
), f"pcs[{i}] ({pcs[i]}) is not exactly 2 greater than pcs[{i - 1}] ({pcs[i - 1]})"
|
||||
|
||||
num_instrs = 16
|
||||
for i in range(num_instrs):
|
||||
cur_pc = getattr(self.bundle.io._pc, f"_{i}")
|
||||
cur_pc.value = pcs[i]
|
||||
await self.bundle.step()
|
||||
|
||||
def get_old_pcs(self) -> list[int]:
|
||||
return self.old_pcs
|
||||
|
||||
@driver_method()
|
||||
async def send_cycle(self, new_cycle: int):
|
||||
self.cycle = new_cycle
|
||||
await self.bundle.step()
|
||||
# BUG: driver_method 有返回值时,不应该用于 ref model 的比对
|
||||
# return self.cycle + 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# FrontendTrigger 单元验证
|
||||
|
||||
|
||||
使用了 toffee 测试框架对 FrontendTrigger 模块进行单元验证。
|
||||
并且基于 toffee 中的类 UVM 接口,编写了一系列测试函数来验证 FrontendTrigger 模块的功能。测试根目录为 `ut_frontend/ifu/frontend_trigger`。
|
||||
|
||||
## 文件说明
|
||||
|
||||
|
||||
| 文件名 | 描述 |
|
||||
| -------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `doc.md` | 本文件,包含测试概要、测试点、测试函数和功能覆盖点等信息。 |
|
||||
| `agent/frontend_trigger_agent.py` | 定义了 FrontendTrigger 的 agent 类,包含 driver、monitor 等方法。 |
|
||||
| `test/frontend_trigger_common_test.py` | 定义了一些常用通用的测试函数,用于验证 FrontendTrigger 模块的基本功能。 |
|
||||
| `test/frontend_trigger_ref.py` | 定义了参考模型,用于验证 FrontendTrigger 模块的行为是否符合预期。 |
|
||||
| `test/test_bug_examples.py` | 出现 bug 的测试用例 |
|
||||
| `test/test_normal_match.py` | 单个断点并且匹配类型为等于、大于等于、小于的测试用例。 |
|
||||
| `test/test_normal_no_match.py` | 单个断点,但一些标志位不满足的测试用例,例如 tselect=1 或 enable=0 等。 |
|
||||
| `test/test_chain_match.py` | 链式断点的测试用例,测试链式断点的触发情况。 |
|
||||
| `test/test_chain_select_no_match.py` | 链式断点的测试用例,测试链式断点在 select 条件不满足时的触发情况。 |
|
||||
| `test/test_chain_enable_no_match.py` | 链式断点的测试用例,测试链式断点在 enable 条件不满足时的触发情况。 |
|
||||
|
||||
|
||||
|
||||
## 测试点汇总
|
||||
|
||||
| 序号 | 功能 | 名称 | 描述 |
|
||||
| ----- | -------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| 1.1 | 断点设置和检查 | select1判定 | 给定tdata1的select位为1,随机构造其它输入,检查断点是否没有触发 |
|
||||
| 1.2.1 | 断点设置和检查 | select0关系匹配判定 | 给定tdata1的select位为0,构造PC与tdata2数据的关系同tdata2的match位匹配的输入,检查断点是否触发 |
|
||||
| 1.2.2 | 断点设置和检查 | select0关系不匹配判定 | 给定tdata1的select位为0,构造PC与tdata2数据的关系同tdata2的match位不匹配的输入,检查断点是否触发 |
|
||||
| 2.1 | 链式断点 | chain位测试 | 对每个trigger,在满足PC断点触发条件的情况下,设置chain位,检查断点是否一定不触发 |
|
||||
| 2.2.1 | 链式断点 | 未命中测试 | 对两个trigger,仅设置前一个trigger的chain位,设置后一个trigger命中而前一个未命中,检查后一个trigger是否一定不触发 |
|
||||
| 2.2.2 | 链式断点 | 命中测试 | 对两个trigger,仅设置前一个trigger的chain位,检查后一个trigger是否触发 |
|
||||
|
||||
## 测试函数汇总
|
||||
|
||||
| 测试函数 | 测试点功能 | 包含测试点 |
|
||||
| --------------------------- | --------------------------------------------------------------------------- | ------------ |
|
||||
| test_tselect1_no_match | 测试 tselect=1 时,不应该触发任何断点 | 1.1 |
|
||||
| test_enable0_no_match | 测试 enable=0 时,不应该触发任何断点 | 无 |
|
||||
| test_chain_no_match | 测试 chain 为 True 时,该断点不应该触发 | 2.1 |
|
||||
| test_match_eq | 测试 matchType=0 (等于) 的单个断点触发情况 | 1.2.1, 1.2.2 |
|
||||
| test_match_ge | 测试 matchType=2 (大于等于) 的单个断点触发情况 | 1.2.1, 1.2.2 |
|
||||
| test_match_lt | 测试 matchType=3 (小于) 的单个断点触发情况 | 1.2.1, 1.2.2 |
|
||||
| test_chain2_match | 测试点:链式断点个数为 2 时,触发情况测试 | 2.2.2 |
|
||||
| test_chain3_match | 测试点:链式断点个数为 3 时,触发情况测试 | 2.2.2 |
|
||||
| test_chain4_match | 测试点:链式断点个数为 4 时,触发情况测试 | 2.2.2 |
|
||||
| test_chain2_enable_no_match | 测试点:链式断点个数为 2 时,且随机一个 enable 条件不满足,不应该触链式断点 | 2.2.1 |
|
||||
| test_chain3_enable_no_match | 测试点:链式断点个数为 3 时,且随机一个 enable 条件不满足,不应该触链式断点 | 2.2.1 |
|
||||
| test_chain4_enable_no_match | 测试点:链式断点个数为 4 时,且随机一个 enable 条件不满足,不应该触链式断点 | 2.2.1 |
|
||||
| test_chain2_select_no_match | 测试点:链式断点个数为 2 时,且随机一个 select 条件不满足,不应该触链式断点 | 2.2.1 |
|
||||
| test_chain3_select_no_match | 测试点:链式断点个数为 3 时,且随机一个 select 条件不满足,不应该触链式断点 | 2.2.1 |
|
||||
| test_chain4_select_no_match | 测试点:链式断点个数为 4 时,且随机一个 select 条件不满足,不应该触链式断点 | 2.2.1 |
|
||||
|
||||
## 功能覆盖点汇总
|
||||
|
||||
| 功能点类别 | 功能点名称 | 功能点描述 | 可能的值 |
|
||||
| --------------------- | --------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------- |
|
||||
| **断点触发情况** | PC0_TRIGGERED ~ PC15_TRIGGERED | 断点0-15的触发状态 | BKPT_EXCPT: 未触发(io_triggered_i=0)<br>DEBUG_MODE: 已触发(io_triggered_i=1) |
|
||||
| **断点设置-匹配类型** | TRI0_MATCH_TYPE ~ TRI3_MATCH_TYPE | 断点0-3的匹配类型 | EQ: 等于(matchType=0)<br>GE: 大于等于(matchType=2)<br>LT: 小于(matchType=3) |
|
||||
| **断点设置-选择标志** | TRI0_SELECT ~ TRI3_SELECT | 断点0-3的选择设置 | SELECT_0: select=0<br>SELECT_1: select=1 |
|
||||
| **断点设置-动作类型** | TRI0_ACTION ~ TRI3_ACTION | 断点0-3的动作设置 | ACTION_0: action=0<br>ACTION_1: action=1 |
|
||||
| **断点设置-链式标志** | TRI0_CHAIN ~ TRI3_CHAIN | 断点0-3的链式设置 | CHAIN_0: chain=0<br>CHAIN_1: chain=1 |
|
||||
| **断点设置-地址数据** | TRI0_tdata2 ~ TRI3_tdata2 | 断点0-3的地址设置 | tdata2_0x{范围起始地址}: 地址在[range_start, range_end)范围内<br>注:地址范围按get_mask_one(50)÷1024的步长划分 |
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import toffee_test
|
||||
from .frontend_trigger_fixture import frontend_trigger_env
|
||||
from ..env import FrontendTriggerEnv
|
||||
from ..agent import BreakpointReq
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_smoke(frontend_trigger_env: FrontendTriggerEnv):
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
bp_req = BreakpointReq()
|
||||
bp_req.chain = False
|
||||
bp_req.data = 121213242
|
||||
bp_req.matchType = 0
|
||||
bp_req.select = 0
|
||||
|
||||
bp_infos = await frontend_trigger_env.agent.set_breakpoint(0, bp_req)
|
||||
# bp_infos = await frontend_trigger_env.agent.set_breakpoint(2, bp_req)
|
||||
for i in range(4):
|
||||
print(bp_infos[i])
|
||||
|
||||
start=121213230
|
||||
pcs = [start+i*2 for i in range(16)]
|
||||
|
||||
print(await frontend_trigger_env.agent.check(pcs))
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
from itertools import islice
|
||||
import random
|
||||
from typing import List, Literal
|
||||
from ut_frontend.ifu.frontend_trigger.agent.frontend_trigger_agent import (
|
||||
BreakpointFlags,
|
||||
BreakpointUpdateInfo,
|
||||
FrontendTriggerAgent,
|
||||
)
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import (
|
||||
bound_pair_generator,
|
||||
chain_bound_generator,
|
||||
gen_pcs,
|
||||
get_mask_one,
|
||||
to_even,
|
||||
)
|
||||
|
||||
|
||||
async def ticks_task(agent: FrontendTriggerAgent, max_ticks=None):
|
||||
"""
|
||||
手动对时钟信号进行计数, 并且用于驱动 refmodel
|
||||
"""
|
||||
counter = 0
|
||||
while max_ticks is None or counter < max_ticks:
|
||||
await agent.send_cycle(counter)
|
||||
counter += 1
|
||||
|
||||
|
||||
async def send_exit(agent: FrontendTriggerAgent):
|
||||
"""
|
||||
当测试结束时,通知 refmodel 停止仿真(用 reset driver)
|
||||
"""
|
||||
await agent.reset()
|
||||
|
||||
|
||||
async def ftrigger_common_task(
|
||||
agent: FrontendTriggerAgent,
|
||||
bp_update_gen,
|
||||
bp_flags_gen,
|
||||
pc_gen,
|
||||
max_task_loop=100,
|
||||
max_pcs_loop_per_task=200,
|
||||
):
|
||||
"""
|
||||
通用的单个断点触发测试任务,用于测试断点触发逻辑
|
||||
"""
|
||||
task_count = 0
|
||||
trigger_info_list: list[BreakpointUpdateInfo] = [] # 存储断点更新信息的列表
|
||||
|
||||
while task_count < max_task_loop:
|
||||
task_count += 1
|
||||
trigger_info_list.clear()
|
||||
# 生成触发PC列表
|
||||
trigger_pc_list = gen_pcs([next(pc_gen)])
|
||||
trigger_pc_sample = random.sample(trigger_pc_list, 4)
|
||||
# 配置每个断点的更新信息
|
||||
for i in range(4):
|
||||
bp_update = next(bp_update_gen)
|
||||
bp_update.tdata2 = trigger_pc_sample[i]
|
||||
trigger_info_list.append(bp_update)
|
||||
await agent.set_breakpoint_update(i, bp_update)
|
||||
# 设置断点标志
|
||||
await agent.set_breakpoint_flags(next(bp_flags_gen))
|
||||
|
||||
# 随机生成PC值并验证触发逻辑
|
||||
for _ in range(max_pcs_loop_per_task):
|
||||
trigger_pcs = [x.tdata2 for x in trigger_info_list]
|
||||
sample_count = random.randint(0, 4)
|
||||
trigger_pcs_sample = [next(pc_gen)]
|
||||
if sample_count > 0:
|
||||
trigger_pcs_sample = random.sample(trigger_pcs, sample_count)
|
||||
|
||||
rand_pcs = gen_pcs(trigger_pcs_sample)
|
||||
assert len(rand_pcs) == 16, "rand_pcs 的长度必须为 16"
|
||||
|
||||
if rand_pcs == agent.get_old_pcs():
|
||||
continue
|
||||
|
||||
await agent.set_pcs(rand_pcs)
|
||||
|
||||
|
||||
async def ftrigger_chain_task_match(
|
||||
agent: FrontendTriggerAgent,
|
||||
chained_bp_update_gen_list,
|
||||
bp_flags_gen,
|
||||
pc_gen,
|
||||
bound_types: List[Literal[">=", "==", "<"]],
|
||||
max_task_loop=10,
|
||||
):
|
||||
"""
|
||||
测试链式断点触发逻辑,对于不同的链式断点配置,会遍历 0-3 的起始地址
|
||||
"""
|
||||
task_count = 0
|
||||
chain_cnt = len(chained_bp_update_gen_list)
|
||||
match_type_map = {">=": 2, "==": 0, "<": 3}
|
||||
while task_count < max_task_loop:
|
||||
task_count += 1
|
||||
|
||||
# 生成 pcs
|
||||
pcs_list = gen_pcs([next(pc_gen)]) # pcs_list 相邻元素之间差 2
|
||||
cur_task_bp_flags = next(bp_flags_gen) # tEnableVec 没有用到
|
||||
pc_sample = random.choice(pcs_list)
|
||||
chained_bound_gen = chain_bound_generator(
|
||||
input_int=pc_sample,
|
||||
bound_types=bound_types,
|
||||
count=chain_cnt,
|
||||
min_value=0,
|
||||
max_value=get_mask_one(50),
|
||||
)
|
||||
|
||||
# 生成 20 个 unique 的 bound, 不足 20 也没关系
|
||||
chained_bound_vec_list = [next(chained_bound_gen) for _ in range(10)]
|
||||
# Process each bound vector from the generated list
|
||||
for cur_bound_vec in chained_bound_vec_list:
|
||||
# Try chain positions at each valid starting address
|
||||
for start_addr in range(4 - chain_cnt + 1):
|
||||
# Reset and set breakpoint enables for current chain
|
||||
cur_task_bp_flags.tEnableVec = [False] * 4
|
||||
for i in range(chain_cnt):
|
||||
cur_task_bp_flags.tEnableVec[start_addr + i] = True
|
||||
|
||||
# Configure all breakpoints in the chain at once
|
||||
for i, cur_bound in enumerate(cur_bound_vec):
|
||||
cur_bp_update = next(chained_bp_update_gen_list[i])
|
||||
cur_bp_update.tdata2 = cur_bound[1]
|
||||
cur_bp_update.matchType = match_type_map[cur_bound[0]] # match_type
|
||||
|
||||
await agent.set_breakpoint_update(
|
||||
start_addr + i, cur_bp_update, bp_flags=cur_task_bp_flags
|
||||
)
|
||||
|
||||
# Validate trigger logic with current PC list
|
||||
await agent.set_pcs(pcs_list)
|
||||
|
||||
|
||||
async def ftrigger_chain_task_select_no_match(
|
||||
agent: FrontendTriggerAgent,
|
||||
chained_bp_update_gen_list,
|
||||
bp_flags_gen,
|
||||
pc_gen,
|
||||
bound_types: List[Literal[">=", "==", "<"]],
|
||||
max_task_loop=10,
|
||||
):
|
||||
"""
|
||||
测试链式断点触发逻辑,对于不同的链式断点配置,会遍历 0-3 的起始地址
|
||||
但会随机将 select 设置为 True 或 False,来模拟 select 条件不满足的情况
|
||||
"""
|
||||
|
||||
task_count = 0
|
||||
chain_cnt = len(chained_bp_update_gen_list)
|
||||
match_type_map = {">=": 2, "==": 0, "<": 3}
|
||||
while task_count < max_task_loop:
|
||||
task_count += 1
|
||||
|
||||
# 生成 pcs
|
||||
pcs_list = gen_pcs([next(pc_gen)]) # pcs_list 相邻元素之间差 2
|
||||
cur_task_bp_flags = next(bp_flags_gen) # tEnableVec 没有用到
|
||||
pc_sample = random.choice(pcs_list)
|
||||
chained_bound_gen = chain_bound_generator(
|
||||
input_int=pc_sample,
|
||||
bound_types=bound_types,
|
||||
count=chain_cnt,
|
||||
min_value=0,
|
||||
max_value=get_mask_one(50),
|
||||
)
|
||||
|
||||
# 生成 20 个 unique 的 bound, 不足 20 也没关系
|
||||
chained_bound_vec_list = [next(chained_bound_gen) for _ in range(10)]
|
||||
# Process each bound vector from the generated list
|
||||
for cur_bound_vec in chained_bound_vec_list:
|
||||
# Try chain positions at each valid starting address
|
||||
for start_addr in range(4 - chain_cnt + 1):
|
||||
# Reset and set breakpoint enables for current chain
|
||||
cur_task_bp_flags.tEnableVec = [False] * 4
|
||||
for i in range(chain_cnt):
|
||||
cur_task_bp_flags.tEnableVec[start_addr + i] = True
|
||||
|
||||
# Configure all breakpoints in the chain at once
|
||||
for i, cur_bound in enumerate(cur_bound_vec):
|
||||
cur_bp_update = next(chained_bp_update_gen_list[i])
|
||||
cur_bp_update.tdata2 = cur_bound[1]
|
||||
cur_bp_update.matchType = match_type_map[cur_bound[0]] # match_type
|
||||
cur_bp_update.select = random.randint(0, 1) # 随机选择 select
|
||||
|
||||
await agent.set_breakpoint_update(
|
||||
start_addr + i, cur_bp_update, bp_flags=cur_task_bp_flags
|
||||
)
|
||||
|
||||
# Validate trigger logic with current PC list
|
||||
await agent.set_pcs(pcs_list)
|
||||
|
||||
|
||||
async def ftrigger_chain_task_enable_no_match(
|
||||
agent: FrontendTriggerAgent,
|
||||
chained_bp_update_gen_list,
|
||||
bp_flags_gen,
|
||||
pc_gen,
|
||||
bound_types: List[Literal[">=", "==", "<"]],
|
||||
max_task_loop=10,
|
||||
):
|
||||
"""
|
||||
测试链式断点触发逻辑,对于不同的链式断点配置,会遍历 0-3 的起始地址
|
||||
但会随机将 enable 设置为 True 或 False,来模拟 enable 条件不满足的情况
|
||||
"""
|
||||
task_count = 0
|
||||
chain_cnt = len(chained_bp_update_gen_list)
|
||||
match_type_map = {">=": 2, "==": 0, "<": 3}
|
||||
while task_count < max_task_loop:
|
||||
task_count += 1
|
||||
|
||||
# 生成 pcs
|
||||
pcs_list = gen_pcs([next(pc_gen)]) # pcs_list 相邻元素之间差 2
|
||||
cur_task_bp_flags = next(bp_flags_gen) # tEnableVec 没有用到
|
||||
pc_sample = random.choice(pcs_list)
|
||||
chained_bound_gen = chain_bound_generator(
|
||||
input_int=pc_sample,
|
||||
bound_types=bound_types,
|
||||
count=chain_cnt,
|
||||
min_value=0,
|
||||
max_value=get_mask_one(50),
|
||||
)
|
||||
|
||||
# 生成 20 个 unique 的 bound, 不足 20 也没关系
|
||||
chained_bound_vec_list = [next(chained_bound_gen) for _ in range(10)]
|
||||
# Process each bound vector from the generated list
|
||||
for cur_bound_vec in chained_bound_vec_list:
|
||||
# Try chain positions at each valid starting address
|
||||
for start_addr in range(4 - chain_cnt + 1):
|
||||
# Reset and set breakpoint enables for current chain
|
||||
cur_task_bp_flags.tEnableVec = [False] * 4
|
||||
for i in range(chain_cnt):
|
||||
cur_task_bp_flags.tEnableVec[start_addr + i] = random.choice(
|
||||
[True, False]
|
||||
)
|
||||
|
||||
# Configure all breakpoints in the chain at once
|
||||
for i, cur_bound in enumerate(cur_bound_vec):
|
||||
cur_bp_update = next(chained_bp_update_gen_list[i])
|
||||
cur_bp_update.tdata2 = cur_bound[1]
|
||||
cur_bp_update.matchType = match_type_map[cur_bound[0]] # match_type
|
||||
|
||||
await agent.set_breakpoint_update(
|
||||
start_addr + i, cur_bp_update, bp_flags=cur_task_bp_flags
|
||||
)
|
||||
|
||||
# Validate trigger logic with current PC list
|
||||
await agent.set_pcs(pcs_list)
|
||||
|
|
@ -1,20 +1,164 @@
|
|||
import toffee_test
|
||||
import toffee
|
||||
from comm.functions import module_name_with
|
||||
from dut.FrontendTrigger import DUTFrontendTrigger
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_ref import (
|
||||
BpRefModel,
|
||||
)
|
||||
from comm.functions import UT_FCOV, module_name_with
|
||||
import toffee.funcov as fc
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import get_mask_one
|
||||
|
||||
|
||||
from ..env import FrontendTriggerEnv
|
||||
|
||||
|
||||
gr = fc.CovGroup(UT_FCOV("../../TOFFEE"), disable_sample_when_point_hinted=False)
|
||||
|
||||
|
||||
def init_frontend_trigger_funcov(dut: DUTFrontendTrigger, g: fc.CovGroup):
|
||||
"""Add watch points to the RVCExpander module to collect function coverage information"""
|
||||
|
||||
# 断点触发情况
|
||||
for i in range(16):
|
||||
g.add_watch_point(
|
||||
dut,
|
||||
{
|
||||
"BKPT_EXCPT": lambda d: getattr(dut, f"io_triggered_{i}").value == 0,
|
||||
"DEBUG_MODE": lambda d: getattr(dut, f"io_triggered_{i}").value == 1,
|
||||
},
|
||||
name=f"PC{i}_TRIGGERED",
|
||||
)
|
||||
|
||||
# 断点设置情况 matchType
|
||||
for i in range(4):
|
||||
g.add_watch_point(
|
||||
dut,
|
||||
{
|
||||
"EQ": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_matchType"
|
||||
).value
|
||||
== 0,
|
||||
"GE": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_matchType"
|
||||
).value
|
||||
== 2,
|
||||
"LT": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_matchType"
|
||||
).value
|
||||
== 3,
|
||||
},
|
||||
name=f"TRI{i}_MATCH_TYPE",
|
||||
)
|
||||
# 断点设置情况 select
|
||||
for i in range(4):
|
||||
g.add_watch_point(
|
||||
dut,
|
||||
{
|
||||
"SELECT_0": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_select"
|
||||
).value
|
||||
== 0,
|
||||
"SELECT_1": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_select"
|
||||
).value
|
||||
== 1,
|
||||
},
|
||||
name=f"TRI{i}_SELECT",
|
||||
)
|
||||
# 断点设置情况 action
|
||||
for i in range(4):
|
||||
g.add_watch_point(
|
||||
dut,
|
||||
{
|
||||
"ACTION_0": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_action"
|
||||
).value
|
||||
== 0,
|
||||
"ACTION_1": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_action"
|
||||
).value
|
||||
== 1,
|
||||
},
|
||||
name=f"TRI{i}_ACTION",
|
||||
)
|
||||
# 断点设置情况 chain
|
||||
for i in range(4):
|
||||
g.add_watch_point(
|
||||
dut,
|
||||
{
|
||||
"CHAIN_0": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_chain"
|
||||
).value
|
||||
== 0,
|
||||
"CHAIN_1": lambda d: getattr(
|
||||
dut, f"FrontendTrigger_tdataVec_{i}_chain"
|
||||
).value
|
||||
== 1,
|
||||
},
|
||||
name=f"TRI{i}_CHAIN",
|
||||
)
|
||||
# 断点设置情况 tdata2
|
||||
|
||||
tdata2_range_list = []
|
||||
step = get_mask_one(50) // 1024 # 区间过大速度就慢
|
||||
for pc_range in range(0, get_mask_one(50), step):
|
||||
tdata2_range_list.append(
|
||||
(
|
||||
"tdata2_0x{:x}".format(pc_range),
|
||||
pc_range,
|
||||
pc_range + step,
|
||||
)
|
||||
)
|
||||
|
||||
for i in range(4):
|
||||
cur_lambda_dict = {}
|
||||
for tdata2_range in tdata2_range_list:
|
||||
cur_lambda_dict[tdata2_range[0]] = lambda d, tdata2_range=tdata2_range: (
|
||||
getattr(dut, f"FrontendTrigger_tdataVec_{i}_tdata2").value
|
||||
>= tdata2_range[1]
|
||||
and getattr(dut, f"FrontendTrigger_tdataVec_{i}_tdata2").value
|
||||
< tdata2_range[2]
|
||||
)
|
||||
g.add_watch_point(
|
||||
dut,
|
||||
cur_lambda_dict,
|
||||
name=f"TRI{i}_tdata2",
|
||||
)
|
||||
|
||||
# # Reverse mark function coverage to the check point
|
||||
# for i in range(16):
|
||||
# g.mark_function(
|
||||
# f"PC{i}_TRIGGERED",
|
||||
# func=[
|
||||
# module_name_with("test_match_eq", "./test_normal_match"),
|
||||
# module_name_with("test_match_ge", "./test_normal_match"),
|
||||
# module_name_with("test_match_lt", "./test_normal_match"),
|
||||
# ],
|
||||
# bin_name=["BKPT_EXCPT", "DEBUG_MODE"],
|
||||
# )
|
||||
|
||||
|
||||
@toffee_test.fixture
|
||||
async def frontend_trigger_env(toffee_request: toffee_test.ToffeeRequest):
|
||||
|
||||
toffee.setup_logging(toffee.WARNING)
|
||||
toffee.setup_logging(toffee.INFO, log_file="toffee.log")
|
||||
dut = toffee_request.create_dut(DUTFrontendTrigger)
|
||||
# toffee_request.add_cov_groups(pred_checker_cover_point(dut))
|
||||
dut.InitClock("clock")
|
||||
toffee.start_clock(dut)
|
||||
|
||||
init_frontend_trigger_funcov(dut, gr)
|
||||
toffee_request.add_cov_groups([gr])
|
||||
|
||||
env = FrontendTriggerEnv(dut)
|
||||
env.attach(BpRefModel())
|
||||
|
||||
# await env.agent.reset()
|
||||
yield env
|
||||
import asyncio
|
||||
|
||||
cur_loop = asyncio.get_event_loop()
|
||||
for task in asyncio.all_tasks(cur_loop):
|
||||
if task.get_name() == "__clock_loop":
|
||||
|
|
@ -22,4 +166,4 @@ async def frontend_trigger_env(toffee_request: toffee_test.ToffeeRequest):
|
|||
try:
|
||||
await task
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
break
|
||||
|
|
|
|||
|
|
@ -0,0 +1,359 @@
|
|||
from toffee.logger import *
|
||||
from toffee.triggers import *
|
||||
from toffee.model import *
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.agent.frontend_trigger_agent import (
|
||||
BreakpointFlags,
|
||||
BreakpointUpdateInfo,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RefTriggerReg:
|
||||
tdata2: int
|
||||
chain: bool
|
||||
timing: bool
|
||||
matchType: int
|
||||
select: int
|
||||
action: int
|
||||
|
||||
def __init__(self):
|
||||
self.tdata2 = 0
|
||||
self.chain = False
|
||||
self.timing = False
|
||||
self.matchType = 0
|
||||
self.select = 0
|
||||
self.action = 0
|
||||
|
||||
def __str__(self):
|
||||
return f"tdata2: {self.tdata2}; chain: {self.chain}; timing: {self.timing}; matchType: {self.matchType}; select: {self.select}; action: {self.action}"
|
||||
|
||||
|
||||
class BpRefImpl:
|
||||
def __init__(self):
|
||||
# bp_flags
|
||||
self.bp_flags = BreakpointFlags()
|
||||
|
||||
# trigger_regs
|
||||
self.trigger_addr2idx = [0, 1, 2, 3]
|
||||
self.trigger_idx2addr = {0: 0, 1: 1, 2: 2, 3: 3}
|
||||
self.trigger_regs = [RefTriggerReg() for _ in self.trigger_addr2idx]
|
||||
|
||||
# pcs
|
||||
self.pcs = [0] * 16
|
||||
|
||||
@staticmethod
|
||||
def ref_match_cmp(pc: int, trigger_reg: int, match_type: int) -> bool:
|
||||
if match_type == 0:
|
||||
# equal
|
||||
return pc == trigger_reg
|
||||
elif match_type == 2:
|
||||
# greater or equal
|
||||
return pc >= trigger_reg
|
||||
elif match_type == 3:
|
||||
# less than
|
||||
return pc < trigger_reg
|
||||
else:
|
||||
raise ValueError(f"Invalid match type:{match_type}")
|
||||
|
||||
def ref_update_trigger_regs(self, addr: int, bp_update: BreakpointUpdateInfo):
|
||||
assert addr < 4, "pos must be less than 4"
|
||||
|
||||
self.trigger_regs[addr].tdata2 = bp_update.tdata2
|
||||
self.trigger_regs[addr].chain = bp_update.chain
|
||||
self.trigger_regs[addr].timing = False
|
||||
self.trigger_regs[addr].matchType = bp_update.matchType
|
||||
self.trigger_regs[addr].select = bp_update.select
|
||||
self.trigger_regs[addr].action = bp_update.action
|
||||
|
||||
def ref_update_bp_flags(self, bp_flags: BreakpointFlags):
|
||||
self.bp_flags = bp_flags
|
||||
|
||||
def ref_update_pcs(self, pcs: list[int]):
|
||||
# len(pcs) == 16
|
||||
assert len(pcs) == 16, "pcs length must be 16"
|
||||
self.pcs = pcs
|
||||
|
||||
def ref_check_trigger(self) -> list[int]:
|
||||
# 16 * 4 的矩阵,记录每个pc在每个trigger上的触发情况(不检查 chain)
|
||||
pc_trigger_matrix = self.get_trigger_matrix()
|
||||
|
||||
final_pc_trigger_list = []
|
||||
for pc_idx, pc_trigger_list in enumerate(pc_trigger_matrix):
|
||||
# if pc_trigger_list == [15, 0, 0, 15] and pc_idx == 8:
|
||||
# print("debug")
|
||||
# print(f"pc_idx: {pc_idx}, pc_trigger_list: {pc_trigger_list}")
|
||||
final_action = self.get_priority_action(pc_trigger_list)
|
||||
final_pc_trigger_list.append(final_action)
|
||||
|
||||
assert (
|
||||
len(final_pc_trigger_list) == 16
|
||||
), "final_pc_trigger_list length must be 16"
|
||||
return final_pc_trigger_list
|
||||
|
||||
def is_trigger_enabled(self, trigger_idx: int) -> bool:
|
||||
trigger_addr = self.trigger_idx2addr[trigger_idx]
|
||||
return (
|
||||
# enable
|
||||
self.bp_flags.tEnableVec[trigger_addr]
|
||||
# select must be 0
|
||||
and self.trigger_regs[trigger_addr].select == 0
|
||||
# debugMode must be False
|
||||
and self.bp_flags.debugMode == False
|
||||
)
|
||||
|
||||
def get_action_from_trigger(self, trigger_idx: int) -> int:
|
||||
"""
|
||||
Args:
|
||||
trigger_idx (int): trigger 在 spec 中的索引
|
||||
"""
|
||||
trigger_addr = self.trigger_idx2addr[trigger_idx]
|
||||
if (
|
||||
self.trigger_regs[trigger_addr].action == 0
|
||||
and self.bp_flags.triggerCanRaiseBpExp
|
||||
):
|
||||
return 0
|
||||
elif self.trigger_regs[trigger_addr].action == 1:
|
||||
return 1
|
||||
else:
|
||||
return 15
|
||||
|
||||
def get_trigger_matrix(self) -> list[list[int]]:
|
||||
# 初始化每个pc的触发情况矩阵(二维列表)
|
||||
# More than one triggers can hit at the same time, but only fire one.
|
||||
# We select the first hit trigger to fire.
|
||||
num_pcs = 16
|
||||
num_triggers = 4
|
||||
|
||||
# 16 * 4 的二维矩阵
|
||||
pc_trigger_matrix = [[15] * num_triggers for _ in range(num_pcs)]
|
||||
|
||||
for t_reg_idx, t_reg in zip(self.trigger_addr2idx, self.trigger_regs):
|
||||
t_reg_addr = self.trigger_idx2addr[t_reg_idx]
|
||||
if not self.is_trigger_enabled(t_reg_idx):
|
||||
continue
|
||||
|
||||
for pc_idx, pc in enumerate(self.pcs):
|
||||
if self.ref_match_cmp(pc, t_reg.tdata2, t_reg.matchType):
|
||||
# 记录触发状态到矩阵
|
||||
cur_action = self.get_action_from_trigger(t_reg_idx)
|
||||
pc_trigger_matrix[pc_idx][t_reg_addr] = cur_action
|
||||
|
||||
return pc_trigger_matrix
|
||||
|
||||
# def get_priority_action(self, pc_trigger_list: list[int]) -> int:
|
||||
# """
|
||||
# 从一个pc在每个trigger上的触发情况中获取优先级最高的触发动作, 并且处理chain trigger 的情况
|
||||
|
||||
# More than one triggers can hit at the same time, but only fire one.
|
||||
# We select the first hit trigger to fire.
|
||||
# Args:
|
||||
# pc_trigger_list (list[int]): 一个pc在每个trigger上的触发情况
|
||||
|
||||
# Returns:
|
||||
# int: 优先级最高的触发动作
|
||||
# """
|
||||
# tmp_chain_group = []
|
||||
# for t_addr, t_action in enumerate(pc_trigger_list):
|
||||
# cur_t_idx = self.trigger_addr2idx[t_addr]
|
||||
# cur_chain = self.trigger_regs[t_addr].chain
|
||||
# cur_timing = self.trigger_regs[t_addr].timing
|
||||
# cur_action = t_action
|
||||
|
||||
# if len(tmp_chain_group) == 0 or tmp_chain_group[-1]["t_idx"] == (
|
||||
# cur_t_idx - 1
|
||||
# ):
|
||||
# # 1. 第一个trigger没有前一个trigger
|
||||
# # 2. 当前trigger 的 idx 是前一个trigger 的 idx - 1, 可能是chain
|
||||
# tmp_chain_group.append(
|
||||
# {
|
||||
# "chain": cur_chain,
|
||||
# "timing": cur_timing,
|
||||
# "action": cur_action,
|
||||
# "t_idx": cur_t_idx,
|
||||
# }
|
||||
# )
|
||||
# else:
|
||||
# # 3. 当前trigger 的 idx 不是前一个trigger 的 idx - 1, 不是chain
|
||||
# # (a) 清空当前的 chain group, chain 设置为 True 必然不触发
|
||||
# # (b) 将当前trigger加入新的 chain group
|
||||
# tmp_chain_group.clear()
|
||||
# tmp_chain_group.append(
|
||||
# {
|
||||
# "chain": cur_chain,
|
||||
# "timing": cur_timing,
|
||||
# "action": cur_action,
|
||||
# "t_idx": cur_t_idx,
|
||||
# }
|
||||
# )
|
||||
|
||||
# # 如果当前trigger不是chain
|
||||
# # 1. 如果当前chain group中的trigger数量大于1, 是 chain 的最后一个
|
||||
# # 2. 如果当前chain group中的trigger数量等于1, 是单独的一个 trigger
|
||||
# if tmp_chain_group[-1]["chain"] == False:
|
||||
# # chain trigger 的 timing 必须相同
|
||||
# all_timing_equal = all(
|
||||
# [
|
||||
# x["timing"] == tmp_chain_group[0]["timing"]
|
||||
# for x in tmp_chain_group
|
||||
# ]
|
||||
# )
|
||||
# # chain trigger 需要所有的 trigger 都 match
|
||||
# all_action_match = all([x["action"] != 15 for x in tmp_chain_group])
|
||||
# if all_timing_equal and all_action_match:
|
||||
# return tmp_chain_group[-1]["action"]
|
||||
|
||||
# tmp_chain_group.clear()
|
||||
|
||||
# return 15
|
||||
|
||||
def get_priority_action(self, pc_trigger_list: list[int]) -> int:
|
||||
tmp_chain_group = []
|
||||
for t_addr, t_action in enumerate(pc_trigger_list):
|
||||
# check enable
|
||||
if not self.is_trigger_enabled(t_addr):
|
||||
continue
|
||||
|
||||
cur_t_idx = self.trigger_addr2idx[t_addr]
|
||||
cur_chain = self.trigger_regs[t_addr].chain
|
||||
cur_timing = self.trigger_regs[t_addr].timing
|
||||
cur_action = t_action
|
||||
|
||||
# 确定当前触发器是否可加入现有链组
|
||||
if tmp_chain_group:
|
||||
last_entry = tmp_chain_group[-1]
|
||||
# 检查索引连续性和时序一致性
|
||||
if (
|
||||
cur_t_idx != last_entry["t_idx"] + 1
|
||||
or cur_timing != tmp_chain_group[0]["timing"]
|
||||
):
|
||||
tmp_chain_group.clear()
|
||||
|
||||
# 将当前触发器加入链组(无论是否清空后)
|
||||
tmp_chain_group.append(
|
||||
{
|
||||
"chain": cur_chain,
|
||||
"action": cur_action,
|
||||
"t_idx": cur_t_idx,
|
||||
"timing": cur_timing,
|
||||
}
|
||||
)
|
||||
|
||||
# 处理非链式触发器作为链尾的情况
|
||||
if not cur_chain:
|
||||
# 所有动作有效时触发
|
||||
if all(x["action"] != 15 for x in tmp_chain_group):
|
||||
return cur_action
|
||||
tmp_chain_group.clear()
|
||||
|
||||
# 所有触发器检查完毕仍未找到有效动作
|
||||
return 15
|
||||
|
||||
|
||||
class BpRefModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# 初始化BpRefImpl实例
|
||||
self.impl = BpRefImpl()
|
||||
|
||||
# cycle驱动端口
|
||||
self.cycle_driver = DriverPort(agent_name="agent", driver_name="send_cycle",maxsize=-1)
|
||||
|
||||
# reset 端口
|
||||
self.reset_driver = DriverPort(agent_name="agent", driver_name="reset",maxsize=-1)
|
||||
|
||||
# 驱动端口
|
||||
self.bp_update_driver = DriverPort(
|
||||
agent_name="agent", driver_name="set_breakpoint_update",maxsize=-1
|
||||
)
|
||||
self.bp_flags_driver = DriverPort(
|
||||
agent_name="agent", driver_name="set_breakpoint_flags",maxsize=-1
|
||||
)
|
||||
self.pcs_driver = DriverPort(agent_name="agent", driver_name="set_pcs",maxsize=-1)
|
||||
|
||||
# 监视端口
|
||||
self.bp_update_monitor = MonitorPort(
|
||||
agent_name="agent", monitor_name="monitor_breakpoint_update",maxsize=-1
|
||||
)
|
||||
self.bp_flags_monitor = MonitorPort(
|
||||
agent_name="agent", monitor_name="monitor_breakpoint_flags",maxsize=-1
|
||||
)
|
||||
self.pcs_monitor = MonitorPort(
|
||||
agent_name="agent", monitor_name="monitor_pcs_changed",maxsize=-1
|
||||
)
|
||||
|
||||
async def get_bp_update_driv(self):
|
||||
dict_res = await self.bp_update_driver()
|
||||
addr: int = dict_res["addr"]
|
||||
bp_update: BreakpointUpdateInfo = dict_res["bp_update"]
|
||||
bp_flags: Optional[BreakpointFlags] = dict_res["bp_flags"]
|
||||
return addr, bp_update, bp_flags
|
||||
|
||||
async def get_bp_flags_driv(self) -> BreakpointFlags:
|
||||
dict_res = await self.bp_flags_driver()
|
||||
# 确保类型正确
|
||||
assert isinstance(dict_res, BreakpointFlags), "bp_flags type error"
|
||||
return dict_res
|
||||
|
||||
async def get_pcs_driv(self) -> list[int]:
|
||||
dict_res = await self.pcs_driver()
|
||||
# print(f'get_pcs_driv: {dict_res}')
|
||||
return dict_res
|
||||
|
||||
async def main(self):
|
||||
|
||||
await self.reset_driver()
|
||||
info("reset ok")
|
||||
while True:
|
||||
cur_cycle = await self.cycle_driver()
|
||||
|
||||
# 处理断点更新
|
||||
if not self.bp_update_driver.empty():
|
||||
addr, bp_update, bp_flags = await self.get_bp_update_driv()
|
||||
|
||||
self.impl.ref_update_trigger_regs(addr, bp_update)
|
||||
if bp_flags is not None:
|
||||
self.impl.ref_update_bp_flags(bp_flags)
|
||||
info(
|
||||
f"cycle[{cur_cycle}][bp_update] addr: {addr}, bp_update: {bp_update}, bp_flags: {bp_flags}"
|
||||
)
|
||||
trigger_res = self.impl.ref_check_trigger()
|
||||
info(f"cycle[{cur_cycle}]trigger_res: {trigger_res}")
|
||||
|
||||
await self.bp_update_monitor.put(trigger_res)
|
||||
|
||||
# 处理标志更新
|
||||
if not self.bp_flags_driver.empty():
|
||||
bp_flags = await self.get_bp_flags_driv()
|
||||
self.impl.ref_update_bp_flags(bp_flags)
|
||||
info(f"cycle[{cur_cycle}][bp_flags] {bp_flags}")
|
||||
trigger_res = self.impl.ref_check_trigger()
|
||||
info(f"cycle[{cur_cycle}]trigger_res: {trigger_res}")
|
||||
await self.bp_flags_monitor.put(trigger_res)
|
||||
|
||||
# 处理PCs更新
|
||||
if not self.pcs_driver.empty():
|
||||
pcs = await self.get_pcs_driv()
|
||||
old_pcs = self.impl.pcs
|
||||
old_pcs_hex = [hex(pc) for pc in old_pcs]
|
||||
pcs_hex = [hex(pc) for pc in pcs]
|
||||
|
||||
info(f"cycle[{cur_cycle}]old_pcs: {old_pcs_hex}")
|
||||
info(f"cycle[{cur_cycle}]new_pcs: {pcs_hex}")
|
||||
|
||||
self.impl.ref_update_pcs(pcs)
|
||||
|
||||
trigger_res = self.impl.ref_check_trigger()
|
||||
info(f"cycle[{cur_cycle}]trigger_res: {trigger_res}")
|
||||
await self.pcs_monitor.put(trigger_res)
|
||||
|
||||
if not self.reset_driver.empty():
|
||||
await self.reset_driver()
|
||||
info(f"cycle[{cur_cycle}]ref exit")
|
||||
break
|
||||
|
||||
# 确保cycle驱动端口已清空
|
||||
assert self.cycle_driver.empty(), "cycle_driver is not empty"
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
import random
|
||||
from typing import Callable, Generator, List, Literal, Tuple
|
||||
from hypothesis import strategies as st
|
||||
from hypothesis.strategies import composite
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.agent.frontend_trigger_agent import (
|
||||
BreakpointFlags,
|
||||
BreakpointUpdateInfo,
|
||||
)
|
||||
|
||||
|
||||
def get_mask_one(length: int) -> int:
|
||||
# 生成一个长度为 length 的全 1 的二进制数,用来进行数据截断
|
||||
return (1 << length) - 1
|
||||
|
||||
|
||||
@composite
|
||||
def bp_update_strategy(draw, pc_width=50):
|
||||
# Generate a random pc value
|
||||
max_pc = get_mask_one(pc_width)
|
||||
pc = draw(st.integers(min_value=0, max_value=max_pc))
|
||||
action = draw(st.integers(min_value=0, max_value=1))
|
||||
tselect = draw(st.booleans())
|
||||
match_type = draw(st.sampled_from([0, 2, 3]))
|
||||
chain = draw(st.booleans())
|
||||
|
||||
bp_update = BreakpointUpdateInfo(
|
||||
action=action, tdata2=pc, select=tselect, matchType=match_type, chain=chain
|
||||
)
|
||||
|
||||
return bp_update
|
||||
|
||||
|
||||
@composite
|
||||
def bp_flags_strategy(draw):
|
||||
tEnableVec = draw(st.lists(st.booleans(), min_size=4, max_size=4))
|
||||
debugMode = draw(st.booleans())
|
||||
triggerCanRaiseBpExp = draw(st.booleans())
|
||||
|
||||
return BreakpointFlags(
|
||||
tEnableVec=tEnableVec,
|
||||
debugMode=debugMode,
|
||||
triggerCanRaiseBpExp=triggerCanRaiseBpExp,
|
||||
)
|
||||
|
||||
|
||||
def bp_update_generator(
|
||||
pc_width: int = 50,
|
||||
condition: Callable[[BreakpointUpdateInfo], bool] = lambda x: True,
|
||||
):
|
||||
"""生成器版本的断点更新信息生成器"""
|
||||
max_pc = get_mask_one(pc_width - 1)
|
||||
while True:
|
||||
# 生成随机pc值
|
||||
pc = random.randint(0, max_pc) << 1
|
||||
action = random.randint(0, 1)
|
||||
tselect = random.choice([True, False])
|
||||
match_type = random.choice([0, 2, 3])
|
||||
chain = random.choice([True, False])
|
||||
|
||||
bp_update = BreakpointUpdateInfo(
|
||||
action=action, tdata2=pc, select=tselect, matchType=match_type, chain=chain
|
||||
)
|
||||
|
||||
if condition(bp_update):
|
||||
yield bp_update
|
||||
|
||||
|
||||
def bp_flags_generator(
|
||||
condition: Callable[[BreakpointFlags], bool] = lambda x: True,
|
||||
) -> Generator[BreakpointFlags, None, None]:
|
||||
while True:
|
||||
tEnableVec = [random.choice([True, False]) for _ in range(4)]
|
||||
debugMode = random.choice([True, False])
|
||||
triggerCanRaiseBpExp = random.choice([True, False])
|
||||
|
||||
flags = BreakpointFlags(
|
||||
tEnableVec=tEnableVec,
|
||||
debugMode=debugMode,
|
||||
triggerCanRaiseBpExp=triggerCanRaiseBpExp,
|
||||
)
|
||||
|
||||
if condition(flags):
|
||||
yield flags
|
||||
|
||||
|
||||
def int_generator(
|
||||
min_value: int = 0,
|
||||
max_value: int = 0xFFFFFFFF,
|
||||
condition: Callable[[int], bool] = lambda x: True,
|
||||
) -> Generator[int, None, None]:
|
||||
while True:
|
||||
value = random.randint(0, max_value)
|
||||
if condition(value):
|
||||
yield value
|
||||
|
||||
|
||||
def gen_pcs(include_pc_list):
|
||||
# 确保 include_pc_list 中的每一项都是偶数,且不为负数
|
||||
if any(pc % 2 != 0 or pc < 0 for pc in include_pc_list):
|
||||
assert False, "include_pc_list 中的每一项必须是偶数且不为负数"
|
||||
|
||||
# 确保最大值和最小值的差不超过 30
|
||||
if max(include_pc_list) - min(include_pc_list) > 30:
|
||||
assert False, "include_pc_list 中的最大项和最小项的差不能超过 30"
|
||||
|
||||
# 计算所有可能的 start 值,使得 rand_pcs 包含 include_pc_list 中的每一项
|
||||
min_pc = min(include_pc_list)
|
||||
max_pc = max(include_pc_list)
|
||||
|
||||
# 计算 start 的范围
|
||||
start_min = max(0, max_pc - 2 * 15)
|
||||
start_max = min_pc
|
||||
|
||||
# 确保为偶数
|
||||
start = random.randint(start_min // 2, start_max // 2) * 2
|
||||
|
||||
# 生成包含 16 项的列表,每项递增 2
|
||||
rand_pcs = [start + 2 * i for i in range(16)]
|
||||
|
||||
# 验证 include_pc_list 中的每一项是否在列表中
|
||||
for pc in include_pc_list:
|
||||
assert (
|
||||
pc in rand_pcs
|
||||
), "生成的列表中未包含 include_pc_list 中的某一项,逻辑错误!"
|
||||
|
||||
return rand_pcs
|
||||
|
||||
|
||||
def int_with_condition_generator(
|
||||
cond_list: List[Tuple[Literal[">", "<", "=", ">=", "<="], int]],
|
||||
lower_spec: int = 0,
|
||||
upper_spec: int = int(1e9),
|
||||
) -> Generator[int, None, None]:
|
||||
"""
|
||||
生成满足所有条件的随机数。
|
||||
|
||||
Args:
|
||||
cond_list: 条件列表,每个条件是一个元组 (条件类型, 值)。
|
||||
条件类型可以是 ">", "<", "=", ">=", "<=" 中的一种。
|
||||
lower_spec: 指定的下界,在条件列表无解时使用,默认为 0。
|
||||
upper_spec: 指定的上界,在条件列表无解时使用,默认为 1e9。
|
||||
|
||||
Yields:
|
||||
生成器,产生满足所有条件的随机整数。
|
||||
如果条件列表无解,则 Yield None 一次,然后停止生成。
|
||||
"""
|
||||
lower_bound = -(10**9) # 初始下界设为负无穷大
|
||||
upper_bound = 10**9 # 初始上界设为正无穷大
|
||||
|
||||
for condition_type, value in cond_list:
|
||||
if condition_type == ">":
|
||||
lower_bound = max(lower_bound, value + 1)
|
||||
elif condition_type == "<":
|
||||
upper_bound = min(upper_bound, value - 1)
|
||||
elif condition_type == ">=":
|
||||
lower_bound = max(lower_bound, value)
|
||||
elif condition_type == "<=":
|
||||
upper_bound = min(upper_bound, value)
|
||||
elif condition_type == "=":
|
||||
lower_bound = max(lower_bound, value)
|
||||
upper_bound = min(upper_bound, value)
|
||||
else:
|
||||
raise ValueError(f"未知的条件类型: {condition_type}")
|
||||
|
||||
if lower_bound > upper_bound:
|
||||
print(
|
||||
"警告: 条件列表互相矛盾,无法找到满足所有条件的数字。将使用指定的上下界范围。"
|
||||
) # 增加警告信息
|
||||
lower_bound = lower_spec # 使用指定的上下界
|
||||
upper_bound = upper_spec
|
||||
if lower_bound > upper_bound: # 再次检查指定上下界是否有效
|
||||
print("警告: 指定的上下界也无效。无法生成随机数。")
|
||||
yield None # Yield None 表示无法生成
|
||||
return # 提前结束生成器
|
||||
|
||||
if lower_bound > upper_bound: # 最终再次检查,虽然理论上在循环内已经检查过
|
||||
print(
|
||||
"最终检查:条件列表互相矛盾,无法找到满足所有条件的数字。"
|
||||
) # 增加最终检查的警告
|
||||
yield None # Yield None 表示无法生成
|
||||
return # 提前结束生成器
|
||||
|
||||
while True:
|
||||
yield random.randint(int(lower_bound), int(upper_bound))
|
||||
|
||||
|
||||
def bound_pair_generator(input_int: int, bound_types: List[Literal[">=", "==", "<"]]):
|
||||
"""
|
||||
生成一个生成器,输出两个 bound,输入的 int 满足该 bound。
|
||||
bound 的类型有 >=, ==, < 这三种。
|
||||
|
||||
Args:
|
||||
input_int: 输入的整数,生成的 bound 需要满足这个整数。
|
||||
|
||||
Yields:
|
||||
生成器,每次 yield 一对 Bound (Tuple[BoundType, int]),
|
||||
其中 BoundType 是 '>=', '==', '<' 中的一种,int 是 bound 的值。
|
||||
"""
|
||||
|
||||
def _generate_bound_value(input_int: int, bound_type) -> int:
|
||||
"""
|
||||
根据 bound 类型生成合适的 bound 值,确保 input_int 满足该 bound。
|
||||
"""
|
||||
if bound_type == ">=":
|
||||
# bound 值应该小于等于 input_int,这样 input_int 才能满足 >= bound_value
|
||||
return random.randint(
|
||||
0, input_int
|
||||
) # 范围可以调整,这里使用 input_int - 5 到 input_int
|
||||
elif bound_type == "==":
|
||||
# bound 值必须等于 input_int
|
||||
return input_int
|
||||
elif bound_type == "<":
|
||||
# bound 值应该大于 input_int,这样 input_int 才能满足 < bound_value
|
||||
return random.randint(input_int + 1, input_int * 2) # 范围可以调整
|
||||
else:
|
||||
raise ValueError(f"未知的 bound 类型: {bound_type}")
|
||||
|
||||
while True:
|
||||
bound1_type = random.choice(bound_types)
|
||||
bound2_type = random.choice(bound_types)
|
||||
|
||||
bound1_value = _generate_bound_value(input_int, bound1_type)
|
||||
bound2_value = _generate_bound_value(input_int, bound2_type)
|
||||
|
||||
bound1 = (bound1_type, bound1_value)
|
||||
bound2 = (bound2_type, bound2_value)
|
||||
yield (bound1, bound2)
|
||||
|
||||
|
||||
def to_odd(x: int) -> int:
|
||||
"""
|
||||
将一个整数转换为奇数。
|
||||
"""
|
||||
return x | 1
|
||||
|
||||
|
||||
def to_even(x: int) -> int:
|
||||
"""
|
||||
将一个整数转换为偶数。
|
||||
"""
|
||||
return x & ~1
|
||||
|
||||
|
||||
def chain_bound_generator(
|
||||
input_int: int,
|
||||
bound_types: List[Literal[">=", "==", "<"]],
|
||||
count: int = 2,
|
||||
min_value=0,
|
||||
max_value=0xFFFFFFFF,
|
||||
):
|
||||
"""
|
||||
生成一个生成器,输出任意数量的 bound,输入的 int 满足这些 bound。
|
||||
bound 的类型有 >=, ==, < 这三种。
|
||||
|
||||
Args:
|
||||
input_int: 输入的整数,生成的 bound 需要满足这个整数。
|
||||
bound_types: 可用的 bound 类型列表。
|
||||
count: 每次生成的 bound 数量,默认为 2。
|
||||
|
||||
Yields:
|
||||
生成器,每次 yield count 个 Bound 的列表,
|
||||
其中每个 Bound 是 (BoundType, int) 形式的元组,
|
||||
BoundType 是 '>=', '==', '<' 中的一种,int 是 bound 的值。
|
||||
"""
|
||||
|
||||
if count < 2:
|
||||
raise ValueError("count 必须大于等于 2")
|
||||
if not bound_types:
|
||||
raise ValueError("bound_types 不能为空")
|
||||
if not all(bound_type in [">=", "==", "<"] for bound_type in bound_types):
|
||||
raise ValueError("bound_types 中包含了未知的 bound 类型")
|
||||
if min_value < 0:
|
||||
raise ValueError("min_value 必须大于等于 0")
|
||||
if min_value >= max_value:
|
||||
raise ValueError("min_value 必须小于 max_value")
|
||||
if input_int < min_value or input_int > max_value:
|
||||
raise ValueError("input_int 必须在 min_value 和 max_value 之间")
|
||||
|
||||
def _generate_bound_value(input_int: int, bound_type) -> int:
|
||||
"""
|
||||
根据 bound 类型生成合适的 bound 值,确保 input_int 满足该 bound。
|
||||
"""
|
||||
if bound_type == ">=":
|
||||
# bound 值应该小于等于 input_int,这样 input_int 才能满足 >= bound_value
|
||||
return random.randint(min_value, input_int)
|
||||
elif bound_type == "==":
|
||||
# bound 值必须等于 input_int
|
||||
return input_int
|
||||
elif bound_type == "<":
|
||||
# bound 值应该大于 input_int,这样 input_int 才能满足 < bound_value
|
||||
return random.randint(input_int + 1, max_value)
|
||||
else:
|
||||
raise ValueError(f"未知的 bound 类型: {bound_type}")
|
||||
|
||||
while True:
|
||||
bounds = []
|
||||
for _ in range(count):
|
||||
bound_type = random.choice(bound_types)
|
||||
bound_value = _generate_bound_value(input_int, bound_type)
|
||||
bounds.append((bound_type, bound_value))
|
||||
yield bounds
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import pytest
|
||||
import toffee_test
|
||||
from toffee import Executor
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.agent.frontend_trigger_agent import (
|
||||
BreakpointFlags,
|
||||
BreakpointUpdateInfo,
|
||||
)
|
||||
from ut_frontend.ifu.frontend_trigger.env.frontend_trigger_env import FrontendTriggerEnv
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_common_task import (
|
||||
send_exit,
|
||||
ticks_task,
|
||||
)
|
||||
|
||||
|
||||
from .frontend_trigger_fixture import frontend_trigger_env
|
||||
|
||||
|
||||
@pytest.mark.toffee_tags(["BUG"])
|
||||
@toffee_test.testcase
|
||||
async def test_bug_match_lt(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
当 matchType 为 3 时(小于), 断点比较逻辑出错
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
async def __smoke_task1():
|
||||
bp_update = BreakpointUpdateInfo()
|
||||
bp_update.chain = False
|
||||
bp_update.matchType = 3
|
||||
bp_update.select = 0
|
||||
bp_update.action = 0
|
||||
bp_update.tdata2 = 0xDEAD_BEE8
|
||||
|
||||
start = 0xDEAD_BEE4
|
||||
pcs = [start + i * 2 for i in range(16)]
|
||||
|
||||
bp_flags = BreakpointFlags()
|
||||
bp_flags.debugMode = False
|
||||
bp_flags.triggerCanRaiseBpExp = True
|
||||
bp_flags.tEnableVec = [True, False, False, False]
|
||||
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
0, bp_update, bp_flags=bp_flags
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
await frontend_trigger_env.agent.set_pcs(pcs)
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(__smoke_task1())
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
import toffee_test
|
||||
from toffee import Executor
|
||||
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.env.frontend_trigger_env import FrontendTriggerEnv
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_common_task import (
|
||||
ftrigger_chain_task_enable_no_match,
|
||||
ftrigger_chain_task_match,
|
||||
ticks_task,
|
||||
ftrigger_common_task,
|
||||
send_exit,
|
||||
)
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import (
|
||||
bp_flags_generator,
|
||||
bp_update_generator,
|
||||
get_mask_one,
|
||||
int_generator,
|
||||
)
|
||||
from .frontend_trigger_fixture import frontend_trigger_env
|
||||
|
||||
|
||||
max_test_loop = 100
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain2_enable_no_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 2 时,且随机一个 enable 条件不满足,不应该触链式断点
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_enable_no_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain3_enable_no_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 3 时,且随机一个 enable 条件不满足,不应该触链式断点
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
second_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_enable_no_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
second_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain4_enable_no_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 4 时,且随机一个 enable 条件不满足,不应该触链式断点
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
second_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
third_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_enable_no_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
second_chain_bp_update_gen,
|
||||
third_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
import toffee_test
|
||||
from toffee import Executor
|
||||
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.env.frontend_trigger_env import FrontendTriggerEnv
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_common_task import (
|
||||
ftrigger_chain_task_match,
|
||||
ticks_task,
|
||||
ftrigger_common_task,
|
||||
send_exit,
|
||||
)
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import (
|
||||
bp_flags_generator,
|
||||
bp_update_generator,
|
||||
get_mask_one,
|
||||
int_generator,
|
||||
)
|
||||
from .frontend_trigger_fixture import frontend_trigger_env
|
||||
|
||||
|
||||
max_test_loop = 100
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain2_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 2 时,触发情况测试
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain3_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 3 时,触发情况测试
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == True
|
||||
)
|
||||
|
||||
second_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
second_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain4_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 4 时,触发情况测试
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == True
|
||||
)
|
||||
|
||||
second_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == True
|
||||
)
|
||||
|
||||
third_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.select == 0 and x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
second_chain_bp_update_gen,
|
||||
third_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
import toffee_test
|
||||
from toffee import Executor
|
||||
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.env.frontend_trigger_env import FrontendTriggerEnv
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_common_task import (
|
||||
ftrigger_chain_task_select_no_match,
|
||||
ftrigger_chain_task_match,
|
||||
ticks_task,
|
||||
ftrigger_common_task,
|
||||
send_exit,
|
||||
)
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import (
|
||||
bp_flags_generator,
|
||||
bp_update_generator,
|
||||
get_mask_one,
|
||||
int_generator,
|
||||
)
|
||||
from .frontend_trigger_fixture import frontend_trigger_env
|
||||
|
||||
|
||||
max_test_loop = 100
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain2_select_no_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 2 时,且随机一个 select 条件不满足,不应该触链式断点
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_select_no_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain3_select_no_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 3 时,且随机一个 select 条件不满足,不应该触链式断点
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
second_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_select_no_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
second_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain4_select_no_match(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点:链式断点个数为 4 时,且随机一个 select 条件不满足,不应该触链式断点
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
first_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
second_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
third_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
last_chain_bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == False
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_chain_task_select_no_match(
|
||||
agent=frontend_trigger_env.agent,
|
||||
chained_bp_update_gen_list=[
|
||||
first_chain_bp_update_gen,
|
||||
second_chain_bp_update_gen,
|
||||
third_chain_bp_update_gen,
|
||||
last_chain_bp_update_gen,
|
||||
],
|
||||
bp_flags_gen=bp_flags_gen,
|
||||
pc_gen=pc_gen,
|
||||
bound_types=["==", ">="],
|
||||
max_task_loop=max_test_loop,
|
||||
)
|
||||
)
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
import toffee_test
|
||||
from toffee import Executor
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.agent.frontend_trigger_agent import (
|
||||
BreakpointFlags,
|
||||
BreakpointUpdateInfo,
|
||||
)
|
||||
from ut_frontend.ifu.frontend_trigger.env.frontend_trigger_env import FrontendTriggerEnv
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_common_task import (
|
||||
ticks_task,
|
||||
ftrigger_common_task,
|
||||
send_exit,
|
||||
)
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import (
|
||||
bp_flags_generator,
|
||||
bp_update_generator,
|
||||
get_mask_one,
|
||||
int_generator,
|
||||
)
|
||||
from .frontend_trigger_fixture import frontend_trigger_env
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain4_match_smoke(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试: 正常情况下, chain 的触发,4 连锁情况
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
# 创建生成器实例
|
||||
bp_update_chain_gen = bp_update_generator(
|
||||
pc_width=50,
|
||||
condition=lambda x: x.select == 0 and x.chain == True and x.matchType != 3,
|
||||
# and x.action == 0,
|
||||
)
|
||||
|
||||
bp_update_no_chain_gen = bp_update_generator(
|
||||
pc_width=50,
|
||||
condition=lambda x: x.select == 0 and x.chain == False and x.matchType != 3,
|
||||
)
|
||||
|
||||
async def __smoke_task1():
|
||||
bp_update1 = BreakpointUpdateInfo()
|
||||
bp_update1.chain = True
|
||||
bp_update1.matchType = 2 # 大于等于
|
||||
bp_update1.select = 0
|
||||
bp_update1.action = 0
|
||||
bp_update1.tdata2 = 0x1234_1234_5600
|
||||
|
||||
bp_update2 = BreakpointUpdateInfo()
|
||||
bp_update2.chain = True
|
||||
bp_update2.matchType = 2 # 大于等于
|
||||
bp_update2.select = 0
|
||||
bp_update2.action = 0
|
||||
bp_update2.tdata2 = 0x1234_1234_5610
|
||||
|
||||
bp_update3 = BreakpointUpdateInfo()
|
||||
bp_update3.chain = True
|
||||
bp_update3.matchType = 2 # 大于等于
|
||||
bp_update3.select = 0
|
||||
bp_update3.action = 0
|
||||
bp_update3.tdata2 = 0x1234_1234_5620
|
||||
|
||||
bp_update4 = BreakpointUpdateInfo()
|
||||
bp_update4.chain = False # 链式断点末尾
|
||||
bp_update4.matchType = 0 # 等于
|
||||
bp_update4.select = 0
|
||||
bp_update4.action = 0
|
||||
bp_update4.tdata2 = 0x1234_1234_5630
|
||||
|
||||
start = 0x1234_1234_5620
|
||||
pcs = [start + i * 2 for i in range(16)]
|
||||
|
||||
bp_flags = BreakpointFlags()
|
||||
bp_flags.debugMode = False
|
||||
bp_flags.triggerCanRaiseBpExp = True
|
||||
bp_flags.tEnableVec = [True, True, True, True]
|
||||
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
0, bp_update1, bp_flags=bp_flags
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
1, bp_update2, bp_flags=bp_flags
|
||||
)
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
2, bp_update3, bp_flags=bp_flags
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
3, bp_update4, bp_flags=bp_flags
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
await frontend_trigger_env.agent.set_pcs(pcs)
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(__smoke_task1())
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain3_match_smoke(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试: 正常情况下, chain 的触发,3 连锁情况
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
chain_cnt = 3
|
||||
|
||||
async def __smoke__chain3_task1():
|
||||
bp_update1 = BreakpointUpdateInfo()
|
||||
bp_update1.chain = True
|
||||
bp_update1.matchType = 2 # 大于等于
|
||||
bp_update1.select = 0
|
||||
bp_update1.action = 0
|
||||
bp_update1.tdata2 = 0x1234_1234_5600
|
||||
|
||||
bp_update2 = BreakpointUpdateInfo()
|
||||
bp_update2.chain = True
|
||||
bp_update2.matchType = 2 # 大于等于
|
||||
bp_update2.select = 0
|
||||
bp_update2.action = 0
|
||||
bp_update2.tdata2 = 0x1234_1234_5610
|
||||
|
||||
bp_update3 = BreakpointUpdateInfo()
|
||||
bp_update3.chain = False # 链式断点末尾
|
||||
bp_update3.matchType = 0 # 等于
|
||||
bp_update3.select = 0
|
||||
bp_update3.action = 0
|
||||
bp_update3.tdata2 = 0x1234_1234_5630
|
||||
|
||||
start = 0x1234_1234_5620
|
||||
pcs = [start + i * 2 for i in range(16)]
|
||||
|
||||
bp_flags = BreakpointFlags()
|
||||
bp_flags.debugMode = False
|
||||
bp_flags.triggerCanRaiseBpExp = True
|
||||
|
||||
|
||||
# 遍历所有可能的起始地址
|
||||
for start_addr in range(4 - chain_cnt + 1):
|
||||
# 只启动链式断点
|
||||
bp_flags.tEnableVec = [False] * 4
|
||||
for i in range(chain_cnt):
|
||||
bp_flags.tEnableVec[start_addr + i] = True
|
||||
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
start_addr, bp_update1, bp_flags=bp_flags
|
||||
)
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
start_addr + 1, bp_update2, bp_flags=bp_flags
|
||||
)
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
start_addr + 2, bp_update3, bp_flags=bp_flags
|
||||
)
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
await frontend_trigger_env.agent.set_pcs(pcs)
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(__smoke__chain3_task1())
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain2_match_smoke(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试: 正常情况下, chain 的触发,2 连锁情况
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
chain_cnt = 2
|
||||
|
||||
async def __smoke__chain3_task1():
|
||||
bp_update1 = BreakpointUpdateInfo()
|
||||
bp_update1.chain = True
|
||||
bp_update1.matchType = 2 # 大于等于
|
||||
bp_update1.select = 0
|
||||
bp_update1.action = 0
|
||||
bp_update1.tdata2 = 0x1234_1234_5600
|
||||
|
||||
|
||||
|
||||
bp_update2 = BreakpointUpdateInfo()
|
||||
bp_update2.chain = False # 链式断点末尾
|
||||
bp_update2.matchType = 0 # 等于
|
||||
bp_update2.select = 0
|
||||
bp_update2.action = 0
|
||||
bp_update2.tdata2 = 0x1234_1234_5630
|
||||
|
||||
start = 0x1234_1234_5620
|
||||
pcs = [start + i * 2 for i in range(16)]
|
||||
|
||||
bp_flags = BreakpointFlags()
|
||||
bp_flags.debugMode = False
|
||||
bp_flags.triggerCanRaiseBpExp = True
|
||||
|
||||
for start_addr in range(4 - chain_cnt + 1):
|
||||
# 只启动链式断点
|
||||
bp_flags.tEnableVec = [False] * 4
|
||||
for i in range(chain_cnt):
|
||||
bp_flags.tEnableVec[start_addr + i] = True
|
||||
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
start_addr, bp_update1, bp_flags=bp_flags
|
||||
)
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
start_addr + 1, bp_update2, bp_flags=bp_flags
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
await frontend_trigger_env.agent.set_pcs(pcs)
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(__smoke__chain3_task1())
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain_no_match_smoke(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试: 链式断点有一个不满足触发条件时, 不应该触发
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
async def __smoke_task1():
|
||||
bp_update1 = BreakpointUpdateInfo()
|
||||
bp_update1.chain = True
|
||||
bp_update1.matchType = 2
|
||||
bp_update1.select = 0
|
||||
bp_update1.action = 0
|
||||
bp_update1.tdata2 = 0x1234_1234_5600
|
||||
|
||||
bp_update2 = BreakpointUpdateInfo()
|
||||
bp_update2.chain = False
|
||||
bp_update2.matchType = 0
|
||||
bp_update2.select = 0
|
||||
bp_update2.action = 0
|
||||
bp_update2.tdata2 = 0x1234_1234_5530
|
||||
|
||||
start = 0x1234_1234_5530
|
||||
pcs = [start + i * 2 for i in range(16)]
|
||||
|
||||
bp_flags = BreakpointFlags()
|
||||
bp_flags.debugMode = False # TODO: 搞清楚这个参数的含义
|
||||
bp_flags.triggerCanRaiseBpExp = True
|
||||
bp_flags.tEnableVec = [True, True, True, True]
|
||||
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
0, bp_update1, bp_flags=bp_flags
|
||||
)
|
||||
await frontend_trigger_env.agent.set_breakpoint_update(
|
||||
1, bp_update2, bp_flags=bp_flags
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
await frontend_trigger_env.agent.set_pcs(pcs)
|
||||
await frontend_trigger_env.agent.bundle.step(2)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(__smoke_task1())
|
||||
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
import pytest
|
||||
import toffee_test
|
||||
from toffee import Executor
|
||||
|
||||
from comm.constants import TAG_LONG_TIME_RUN
|
||||
from ut_frontend.ifu.frontend_trigger.env.frontend_trigger_env import FrontendTriggerEnv
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_common_task import (
|
||||
ticks_task,
|
||||
ftrigger_common_task,
|
||||
send_exit,
|
||||
)
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import (
|
||||
bp_flags_generator,
|
||||
bp_update_generator,
|
||||
get_mask_one,
|
||||
int_generator,
|
||||
)
|
||||
|
||||
from .frontend_trigger_fixture import frontend_trigger_env
|
||||
|
||||
|
||||
# N = 1000
|
||||
# T = 1 << 20
|
||||
|
||||
|
||||
# # @pytest.mark.toffee_tags(TAG_LONG_TIME_RUN)
|
||||
# @pytest.mark.parametrize(
|
||||
# "pc_min,pc_max",
|
||||
# [(r * (T // N), (r + 1) * (T // N) if r < N else T) for r in range(N)],
|
||||
# )
|
||||
# @toffee_test.testcase
|
||||
# async def test_match_eq_new(
|
||||
# frontend_trigger_env: FrontendTriggerEnv, pc_min: int, pc_max: int
|
||||
# ):
|
||||
# await frontend_trigger_env.agent.reset()
|
||||
|
||||
# # 创建生成器实例
|
||||
# bp_update_gen = bp_update_generator(
|
||||
# pc_width=50,
|
||||
# condition=lambda x: x.matchType == 0 and x.select == 0 and x.chain == False,
|
||||
# )
|
||||
# bp_flags_gen = bp_flags_generator(
|
||||
# condition=lambda x: x.debugMode == False
|
||||
# and all(x.tEnableVec)
|
||||
# and x.triggerCanRaiseBpExp
|
||||
# )
|
||||
# pc_gen = int_generator(
|
||||
# min_value=pc_min, max_value=pc_max - 30, condition=lambda x: x & 1 == 0
|
||||
# )
|
||||
|
||||
# async with Executor(exit="any") as exec:
|
||||
# exec(ticks_task(frontend_trigger_env.agent))
|
||||
# exec(
|
||||
# ftrigger_common_task1(
|
||||
# frontend_trigger_env.agent, bp_update_gen, bp_flags_gen, pc_gen
|
||||
# )
|
||||
# )
|
||||
|
||||
# # 通知参考模型停止模拟
|
||||
# await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_match_eq(frontend_trigger_env: FrontendTriggerEnv):
|
||||
"""
|
||||
测试点: 测试 matchType=0 (等于) 的单个断点触发情况
|
||||
"""
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
# 创建生成器实例
|
||||
bp_update_gen = bp_update_generator(
|
||||
pc_width=50,
|
||||
condition=lambda x: x.matchType == 0 and x.select == 0 and x.chain == False,
|
||||
)
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False
|
||||
and all(x.tEnableVec)
|
||||
and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_common_task(
|
||||
frontend_trigger_env.agent, bp_update_gen, bp_flags_gen, pc_gen
|
||||
)
|
||||
)
|
||||
|
||||
# 通知参考模型停止模拟
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_match_ge(
|
||||
frontend_trigger_env: FrontendTriggerEnv,
|
||||
):
|
||||
"""
|
||||
测试点: 测试 matchType=2 (大于等于) 的单个断点触发情况
|
||||
"""
|
||||
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
# 创建生成器实例
|
||||
bp_update_gen = bp_update_generator(
|
||||
pc_width=50,
|
||||
condition=lambda x: x.matchType == 2 and x.select == 0 and x.chain == False,
|
||||
)
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False
|
||||
and all(x.tEnableVec)
|
||||
and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_common_task(
|
||||
frontend_trigger_env.agent, bp_update_gen, bp_flags_gen, pc_gen
|
||||
)
|
||||
)
|
||||
|
||||
# 通知参考模型停止模拟
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@pytest.mark.toffee_tags(["BUG"])
|
||||
@toffee_test.testcase
|
||||
async def test_match_lt(
|
||||
frontend_trigger_env: FrontendTriggerEnv,
|
||||
):
|
||||
"""
|
||||
测试点: 测试 matchType=3 (小于) 的单个断点触发情况
|
||||
"""
|
||||
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
# 创建生成器实例
|
||||
bp_update_gen = bp_update_generator(
|
||||
pc_width=50,
|
||||
condition=lambda x: x.matchType == 3 and x.select == 0 and x.chain == False,
|
||||
)
|
||||
bp_flags_gen = bp_flags_generator(
|
||||
condition=lambda x: x.debugMode == False
|
||||
and all(x.tEnableVec)
|
||||
and x.triggerCanRaiseBpExp
|
||||
)
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_common_task(
|
||||
frontend_trigger_env.agent, bp_update_gen, bp_flags_gen, pc_gen
|
||||
)
|
||||
)
|
||||
|
||||
# 通知参考模型停止模拟
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
import pytest
|
||||
import toffee_test
|
||||
from toffee import Executor
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.env.frontend_trigger_env import FrontendTriggerEnv
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_common_task import (
|
||||
ticks_task,
|
||||
ftrigger_common_task,
|
||||
send_exit,
|
||||
)
|
||||
|
||||
from ut_frontend.ifu.frontend_trigger.test.frontend_trigger_tools import (
|
||||
bp_flags_generator,
|
||||
bp_update_generator,
|
||||
get_mask_one,
|
||||
int_generator,
|
||||
)
|
||||
from .frontend_trigger_fixture import frontend_trigger_env, gr
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_tselect1_no_match(
|
||||
frontend_trigger_env: FrontendTriggerEnv,
|
||||
):
|
||||
"""
|
||||
测试点: 测试 tselect=1 时,不应该触发任何断点
|
||||
"""
|
||||
|
||||
bp_update_gen = bp_update_generator(pc_width=50, condition=lambda x: x.select == 1)
|
||||
bp_flags_gen = bp_flags_generator(condition=lambda x: all(x.tEnableVec))
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_common_task(
|
||||
frontend_trigger_env.agent, bp_update_gen, bp_flags_gen, pc_gen
|
||||
)
|
||||
)
|
||||
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_enable0_no_match(
|
||||
frontend_trigger_env: FrontendTriggerEnv,
|
||||
):
|
||||
"""
|
||||
测试点: 测试 `enable=0` 时,不应该触发任何断点
|
||||
"""
|
||||
bp_update_gen = bp_update_generator(pc_width=50)
|
||||
bp_flags_gen = bp_flags_generator(condition=lambda x: not any(x.tEnableVec))
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_common_task(
|
||||
frontend_trigger_env.agent, bp_update_gen, bp_flags_gen, pc_gen
|
||||
)
|
||||
)
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_chain_no_match(
|
||||
frontend_trigger_env: FrontendTriggerEnv,
|
||||
):
|
||||
"""
|
||||
测试点: 测试 `chain` 为 True 时,该断点不应该触发
|
||||
"""
|
||||
|
||||
bp_update_gen = bp_update_generator(
|
||||
pc_width=50, condition=lambda x: x.chain == True
|
||||
)
|
||||
|
||||
bp_flags_gen = bp_flags_generator()
|
||||
|
||||
pc_gen = int_generator(
|
||||
min_value=0, max_value=get_mask_one(50) - 30, condition=lambda x: x & 1 == 0
|
||||
)
|
||||
|
||||
await frontend_trigger_env.agent.reset()
|
||||
|
||||
async with Executor(exit="any") as exec:
|
||||
exec(ticks_task(frontend_trigger_env.agent))
|
||||
exec(
|
||||
ftrigger_common_task(
|
||||
frontend_trigger_env.agent, bp_update_gen, bp_flags_gen, pc_gen
|
||||
)
|
||||
)
|
||||
# notify the refmodel to stop the simulation
|
||||
await send_exit(frontend_trigger_env.agent)
|
||||
|
|
@ -1 +1,35 @@
|
|||
from .pred_checker_agent import PredCheckerAgent
|
||||
from toffee.agent import *
|
||||
from ..bundle import PredCheckerBundle
|
||||
from ... import PREDICT_WIDTH, RVC_LABEL, RET_LABEL, BRTYPE_LABEL
|
||||
|
||||
class PredCheckerAgent(Agent):
|
||||
def __init__(self, bundle: PredCheckerBundle):
|
||||
super().__init__(bundle)
|
||||
self.bundle = bundle
|
||||
|
||||
@driver_method()
|
||||
async def agent_pred_check(self, ftqValid, ftqOffBits, instrRange, instrValid, jumpOffset, pc, pds, tgt, fire):
|
||||
self.bundle.io._in._ftqOffset._valid.value = ftqValid
|
||||
self.bundle.io._in._ftqOffset._bits.value = ftqOffBits
|
||||
self.bundle.io._in._target.value = tgt
|
||||
self.bundle.io._in._fire_in.value = fire
|
||||
for i in range(PREDICT_WIDTH):
|
||||
getattr(self.bundle.io._in._pc, f'_{i}').value = pc[i]
|
||||
getattr(self.bundle.io._in._instrRange, f'_{i}').value = instrRange[i]
|
||||
getattr(self.bundle.io._in._instrValid, f'_{i}').value = instrValid[i]
|
||||
getattr(self.bundle.io._in._jumpOffset, f'_{i}').value = jumpOffset[i]
|
||||
|
||||
getattr(self.bundle.io._in._pds, f'_{i}')._isRVC.value = pds[i][RVC_LABEL]
|
||||
getattr(self.bundle.io._in._pds, f'_{i}')._brType.value = pds[i][BRTYPE_LABEL]
|
||||
getattr(self.bundle.io._in._pds, f'_{i}')._isRet.value = pds[i][RET_LABEL]
|
||||
|
||||
await self.bundle.step()
|
||||
stg1_fixedRange = [getattr(self.bundle.io._out._stage1Out._fixedRange, f'_{i}').value for i in range(PREDICT_WIDTH)]
|
||||
stg1_fixedTaken = [getattr(self.bundle.io._out._stage1Out._fixedTaken, f'_{i}').value for i in range(PREDICT_WIDTH)]
|
||||
#yield stg1_fixedRange, stg1_fixedTaken
|
||||
await self.bundle.step()
|
||||
stg2_fixedTarget = [getattr(self.bundle.io._out._stage2Out._fixedTarget, f'_{i}').value for i in range(PREDICT_WIDTH)]
|
||||
stg2_fixedMissPred = [getattr(self.bundle.io._out._stage2Out._fixedMissPred, f'_{i}').value for i in range(PREDICT_WIDTH)]
|
||||
stg2_jalTarget = [getattr(self.bundle.io._out._stage2Out._jalTarget, f'_{i}').value for i in range(PREDICT_WIDTH)]
|
||||
#yield stg2_fixedTarget, stg2_jalTarget, stg2_fixedMissPred
|
||||
return stg1_fixedRange, stg1_fixedTaken, stg2_fixedTarget, stg2_jalTarget, stg2_fixedMissPred
|
||||
|
|
@ -79,32 +79,10 @@ class _9Bundle(Bundle):
|
|||
_fixedRange = _0Bundle.from_prefix("_fixedRange")
|
||||
_fixedTaken = _0Bundle.from_prefix("_fixedTaken")
|
||||
|
||||
class singleFaultTypeBundle(Bundle):
|
||||
_value = Signal()
|
||||
|
||||
class faultTypesBundle(Bundle):
|
||||
_12 = singleFaultTypeBundle.from_prefix("_12")
|
||||
_1 = singleFaultTypeBundle.from_prefix("_1")
|
||||
_9 = singleFaultTypeBundle.from_prefix("_9")
|
||||
_15 = singleFaultTypeBundle.from_prefix("_15")
|
||||
_6 = singleFaultTypeBundle.from_prefix("_6")
|
||||
_5 = singleFaultTypeBundle.from_prefix("_5")
|
||||
_7 = singleFaultTypeBundle.from_prefix("_7")
|
||||
_3 = singleFaultTypeBundle.from_prefix("_3")
|
||||
_4 = singleFaultTypeBundle.from_prefix("_4")
|
||||
_2 = singleFaultTypeBundle.from_prefix("_2")
|
||||
_11 = singleFaultTypeBundle.from_prefix("_11")
|
||||
_8 = singleFaultTypeBundle.from_prefix("_8")
|
||||
_14 = singleFaultTypeBundle.from_prefix("_14")
|
||||
_13 = singleFaultTypeBundle.from_prefix("_13")
|
||||
_10 = singleFaultTypeBundle.from_prefix("_10")
|
||||
_0 = singleFaultTypeBundle.from_prefix("_0")
|
||||
|
||||
class _10Bundle(Bundle):
|
||||
_fixedTarget = _0Bundle.from_prefix("_fixedTarget")
|
||||
_fixedMissPred = _0Bundle.from_prefix("_fixedMissPred")
|
||||
_jalTarget = _0Bundle.from_prefix("_jalTarget")
|
||||
_faultType = faultTypesBundle.from_prefix("_faultType")
|
||||
|
||||
class _11Bundle(Bundle):
|
||||
_stage2Out = _10Bundle.from_prefix("_stage2Out")
|
||||
|
|
|
|||
|
|
@ -2,10 +2,14 @@ from toffee import Env
|
|||
from ..agent import PredCheckerAgent
|
||||
from ..bundle import PredCheckerBundle
|
||||
from dut.PredChecker import DUTPredChecker
|
||||
from .pred_checker_mdl import *
|
||||
|
||||
|
||||
class PredCheckerEnv(Env):
|
||||
|
||||
def __init__(self, dut:DUTPredChecker):
|
||||
super().__init__()
|
||||
self.predCheckerAgent = PredCheckerAgent(PredCheckerBundle.from_prefix("").bind(dut))
|
||||
self.predCheckerAgent = PredCheckerAgent(PredCheckerBundle.from_prefix("").bind(dut))
|
||||
self.mdl = PredCheckerModel()
|
||||
self.attach(self.mdl)
|
||||
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
from ... import PREDICT_WIDTH, RET_LABEL, RVC_LABEL, BRTYPE_LABEL
|
||||
from toffee.model import *
|
||||
from ..bundle import PredCheckerBundle
|
||||
'''PredChecker reference model'''
|
||||
|
||||
class PredCheckerModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.fixedRange = [0 for _ in range(PREDICT_WIDTH)]
|
||||
self.fixedTarget = [0 for _ in range(PREDICT_WIDTH)]
|
||||
self.fixedMisspred = [0 for _ in range(PREDICT_WIDTH)]
|
||||
self.fixedTarget = [0 for _ in range(PREDICT_WIDTH)]
|
||||
self.jalTarget = [0 for _ in range(PREDICT_WIDTH)]
|
||||
|
||||
@driver_hook(agent_name="predCheckerAgent", driver_name="agent_pred_check")
|
||||
def ref_pred_check(self, ftqValid, ftqOffbits, instrRange, instrValid, jumpOffset, pc, pds, tgt, fire):
|
||||
# Store input
|
||||
self.ftqValid = ftqValid
|
||||
self.ftqOffbits = ftqOffbits
|
||||
self.instrRange = instrRange
|
||||
self.instrValid = instrValid
|
||||
self.jumpOffset = jumpOffset
|
||||
self.pc = pc
|
||||
self.pds = pds
|
||||
self.tgt = tgt
|
||||
# Clear the previous result if it exists
|
||||
for i in range(PREDICT_WIDTH):
|
||||
if instrRange[i]:
|
||||
self.fixedRange[i] = 1
|
||||
else:
|
||||
self.fixedRange[i] = 0
|
||||
self.fixedTaken = [0 for i in range(PREDICT_WIDTH)]
|
||||
self.fixedMisspred = [0 for i in range(PREDICT_WIDTH)]
|
||||
self.fixedTarget = [0 for i in range(PREDICT_WIDTH)]
|
||||
self.jalTarget = [0 for i in range(PREDICT_WIDTH)]
|
||||
|
||||
# Generate fixedTarget and jalTarget
|
||||
for idx in range(PREDICT_WIDTH):
|
||||
if pds[idx][RVC_LABEL] or (not instrValid[idx]):
|
||||
self.fixedTarget[idx] = pc[idx] + 2
|
||||
self.jalTarget[idx] = pc[idx] + jumpOffset[idx]
|
||||
else:
|
||||
self.fixedTarget[idx] = pc[idx] + 4
|
||||
self.jalTarget[idx] = pc[idx] + jumpOffset[idx]
|
||||
# Overflow condition
|
||||
for i in range(PREDICT_WIDTH):
|
||||
if self.jalTarget[i] >= 2**50:
|
||||
self.jalTarget[i] = self.jalTarget[i] - 2**50
|
||||
|
||||
# Check missPred accroding to pds info
|
||||
cfi_idx = []
|
||||
for idx in range(PREDICT_WIDTH):
|
||||
# First determine whether this instruction is valid
|
||||
if instrValid[idx] and (pds[idx][RET_LABEL] or (pds[idx][BRTYPE_LABEL] > 0)):
|
||||
cfi_idx.extend([idx])
|
||||
|
||||
# if pds gave a valid instr info
|
||||
if len(cfi_idx) != 0:
|
||||
cfi_idx.sort()
|
||||
self.fixedTaken[cfi_idx[0]] = 1
|
||||
if ftqValid and (cfi_idx[0] != ftqOffbits):
|
||||
self.fixedRange = [0 for _ in range(PREDICT_WIDTH)]
|
||||
if(cfi_idx[0] < ftqOffbits): # Renew range
|
||||
self.fixedMisspred[cfi_idx[0]] = 1
|
||||
for i in range(cfi_idx[0] + 1):
|
||||
self.fixedRange[i] = 1
|
||||
else:
|
||||
self.fixedMisspred[ftqOffbits] = 1
|
||||
for i in range(ftqOffbits + 1):
|
||||
self.fixedRange[i] = 1
|
||||
for i in range(PREDICT_WIDTH):
|
||||
self.fixedTaken[i] = 0
|
||||
if(pds[cfi_idx[0]][BRTYPE_LABEL] == 3) and (not pds[cfi_idx[0]][RET_LABEL]):
|
||||
for i in range(PREDICT_WIDTH):
|
||||
if(instrRange[i]):
|
||||
self.fixedRange[i] = 1
|
||||
self.fixedTaken[cfi_idx[0]] = 1
|
||||
if not ftqValid:
|
||||
self.fixedRange = [1 for _ in range(cfi_idx[0] + 1)]
|
||||
self.fixedRange.extend([0 for _ in range(PREDICT_WIDTH - cfi_idx[0] - 1)])
|
||||
self.fixedMisspred[cfi_idx[0]] = 1
|
||||
# Target check for JAL and BR instr
|
||||
if (not pds[cfi_idx[0]][RET_LABEL]) and (pds[cfi_idx[0]][BRTYPE_LABEL] < 3):
|
||||
# Target fix includes 2 conditions:
|
||||
# 1. ftqOffbits is larger than valid CFI index number;
|
||||
# 2. ftqOffbits equal to valid CFI index, but tgt not equal to pc[x] + jumpOffset[x].
|
||||
pds_tgt = pc[cfi_idx[0]] + jumpOffset[cfi_idx[0]]
|
||||
if pds_tgt >= 2**50: # If target overflow
|
||||
pds_tgt = pds_tgt - 2**50
|
||||
if (self.instrRange[cfi_idx[0]] == 1) \
|
||||
and ((pds_tgt != tgt) or (cfi_idx[0] < ftqOffbits)) \
|
||||
or (not ftqValid):
|
||||
self.fixedTarget[cfi_idx[0]] = self.jalTarget[cfi_idx[0]]
|
||||
if cfi_idx[0] <= ftqOffbits:
|
||||
self.fixedMisspred[cfi_idx[0]] = 1
|
||||
else:
|
||||
# pds do not exist CFI but FTQ gave a jumping prediction
|
||||
if ftqValid:
|
||||
self.fixedMisspred[ftqOffbits] = 1
|
||||
|
||||
for i in range(PREDICT_WIDTH):
|
||||
if self.fixedTarget[i] >= 2**50:
|
||||
self.fixedTarget[i] = self.fixedTarget[i] - 2**50
|
||||
stg1_fixedRange = self.fixedRange
|
||||
stg1_fixedTaken = self.fixedTaken
|
||||
stg2_fixedTarget = self.fixedTarget
|
||||
stg2_jalTarget = self.jalTarget
|
||||
stg2_fixedMissPred = self.fixedMisspred
|
||||
|
||||
return stg1_fixedRange, stg1_fixedTaken, stg2_fixedTarget, stg2_jalTarget, stg2_fixedMissPred
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,498 @@
|
|||
from ... import PREDICT_WIDTH, RET_LABEL, RVC_LABEL, BRTYPE_LABEL
|
||||
import random
|
||||
|
||||
class pred_checker_sqr:
|
||||
latest_vec_pkt = None
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def gen_vec(self, PREDICT_WIDTH, vec_depth, caseId):
|
||||
vec_pkt = [self._gen_vec_single(PREDICT_WIDTH, caseId) for _ in range(vec_depth)]
|
||||
self.latest_vec_pkt = vec_pkt
|
||||
return vec_pkt
|
||||
|
||||
def _gen_vec_single(self, PREDICT_WIDTH, caseId):
|
||||
fire = True
|
||||
ftqValid = False
|
||||
ftqOffBits = random.randint(0, 15)
|
||||
instrRange = [False for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [False for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = [0 for _ in range(PREDICT_WIDTH)]
|
||||
tgt = 0
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
|
||||
# Pds has no JAL info; instrRange is False; instrValid is False;
|
||||
# Check if the pred_checker will report a JAL missed prediction
|
||||
if(caseId == 1):
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: random.choice([0]) } for i in range(PREDICT_WIDTH)]
|
||||
instrRange = [random.choice([True]) for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [random.choice([True]) for _ in range(PREDICT_WIDTH)]
|
||||
pc_0 = random.randint(0, 2**50 - 64)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
tgt = pc[PREDICT_WIDTH - 1] + 1
|
||||
|
||||
|
||||
# Pds has JAL info; insrRange&instrValid is corresponding to JAL info;
|
||||
# Check if the pred_checker will report a JAL missed prediction
|
||||
elif(caseId == 2):
|
||||
#print("Case 1.1.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
randOffset = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2}
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc[randOffset])
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 3):
|
||||
#print("Case 1.2.1: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
randOffset = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
ftqValid = False
|
||||
ftqOffBits = 0
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2}
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc[randOffset])
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
# Cause we are testing a wrong prediction, so tgt is not cared.
|
||||
tgt = pc[randOffset] + random.randint(0, 2**50 - pc[randOffset])
|
||||
|
||||
elif(caseId == 4):
|
||||
#print("Case 1.2.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
ftqOffBits = random.randint(1, 15)
|
||||
randOffset = random.randint(0, 14)
|
||||
while randOffset >= ftqOffBits:
|
||||
randOffset = random.randint(0, 14)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2}
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 21):
|
||||
#print("Case 2.1.1: generate test vector")
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: random.choice([0]) } for i in range(PREDICT_WIDTH)]
|
||||
instrRange = [random.choice([True]) for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [random.choice([True]) for _ in range(PREDICT_WIDTH)]
|
||||
pc_0 = random.randint(0, 2**50 - 64)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
tgt = pc[PREDICT_WIDTH - 1] + 1
|
||||
|
||||
elif(caseId == 22):
|
||||
#print("Case 2.1.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
randOffset = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: True, BRTYPE_LABEL: 3}
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc[randOffset])
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
elif(caseId == 23):
|
||||
#print("Case 2.2.1: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
randOffset = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
ftqValid = False
|
||||
ftqOffBits = 0
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: True, BRTYPE_LABEL: 3}
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc[randOffset] + random.randint(0, 2**50 - pc[randOffset])
|
||||
|
||||
elif(caseId == 24):
|
||||
#print("Case 2.2.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
ftqOffBits = random.randint(1, 15)
|
||||
randOffset = random.randint(0, 14)
|
||||
while randOffset >= ftqOffBits:
|
||||
randOffset = random.randint(0, 14)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: True, BRTYPE_LABEL: 3}
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc_0 + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 31):
|
||||
#print("Case 3.1.1: generate test vector")
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: random.choice([0]) } for i in range(PREDICT_WIDTH)]
|
||||
instrRange = [random.choice([True]) for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [random.choice([True]) for _ in range(PREDICT_WIDTH)]
|
||||
pc_0 = random.randint(0, 2**50 - 64)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
tgt = pc[PREDICT_WIDTH - 1] + 1
|
||||
|
||||
elif(caseId == 32):
|
||||
#print("Case 3.1.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
randOffset = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 3}
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc[randOffset])
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 33):
|
||||
#print("Case 3.2.1: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
randOffset = 12 #random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
ftqValid = False
|
||||
ftqOffBits = 0
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 3}
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc[randOffset] + random.randint(0, 2**50 - pc[randOffset])
|
||||
|
||||
elif(caseId == 34):
|
||||
#print("Case 3.2.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
ftqOffBits = random.randint(1, 15)
|
||||
randOffset = random.randint(0, 14)
|
||||
while randOffset >= ftqOffBits:
|
||||
randOffset = random.randint(0, 14)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 3}
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc_0 + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 41):
|
||||
#print("Case 4.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
randOffset = random.randint(0, 14)
|
||||
ftqOffBits = randOffset
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: False, RET_LABEL: True, BRTYPE_LABEL: 3}])
|
||||
instrRange = [True for _ in range(ftqOffBits + 1)]
|
||||
instrRange.extend([False for _ in range(PREDICT_WIDTH - 1 - ftqOffBits)])
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc_0 + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 42):
|
||||
#print("Case 4.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
randOffset = random.randint(0, 14)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: False, RET_LABEL: True, BRTYPE_LABEL: 3}])
|
||||
while ftqOffBits <= randOffset:
|
||||
ftqOffBits = random.randint(1, 15)
|
||||
instrRange = [True for _ in range(ftqOffBits + 1)]
|
||||
instrRange.extend([False for _ in range(PREDICT_WIDTH - 1 - ftqOffBits)])
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc_0 + 10086 # Cause we are testing a wrong prediction, so tgt is not cared.
|
||||
|
||||
elif(caseId == 43):
|
||||
#print("Case 4.3: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
randOffset = random.randint(1, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: False, RET_LABEL: True, BRTYPE_LABEL: 3}])
|
||||
while ftqOffBits >= randOffset:
|
||||
ftqOffBits = random.randint(0, 14)
|
||||
instrRange = [True for _ in range(ftqOffBits + 1)]
|
||||
instrRange.extend([False for _ in range(PREDICT_WIDTH - ftqOffBits - 1)])
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 51):
|
||||
#print("Case 5.1.1: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = False
|
||||
randOffset = random.randint(0, 15)
|
||||
ftqOffBits = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc_0 + 10086 # Cause we are testing no-jumping case, so tgt is not cared.
|
||||
|
||||
elif(caseId == 52):
|
||||
#print("Case 5.1.2: generate test vector")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
randOffset = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: False, RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: False, RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc[randOffset])
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 53):
|
||||
#print("Case 5.2")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
ftqOffBits = random.randint(0, 15)
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc_0 + 10086 # Cause the case has to generate a fault prediction, so tgt is not cared.
|
||||
|
||||
elif(caseId == 61):
|
||||
#print("Case 6.1.1")
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = False
|
||||
ftqOffBits = 0
|
||||
pds = [{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc_0 + 10086 # Cause the case has to generate no-jumping prediction, so tgt is not cared.
|
||||
|
||||
elif(caseId == 62):
|
||||
#print("Case 6.1.2")
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = False
|
||||
ftqOffBits = 0
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
instrValid[randOffset] = False
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
# randOffset_1: true jump instr location
|
||||
if randOffset != 15:
|
||||
randOffset_1 = random.randint(randOffset + 1, 15)
|
||||
pds[randOffset_1] = random.choice([{RVC_LABEL: random.choice([True, False]), RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 2}])
|
||||
#{RVC_LABEL: random.choice([True, False]), RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
jumpOffset[randOffset_1] = random.randint(0, 2**50 - pc_0 - 2**6)
|
||||
tgt = pc[randOffset_1] + jumpOffset[randOffset_1]
|
||||
else:
|
||||
tgt = pc[randOffset]
|
||||
|
||||
elif(caseId == 63):
|
||||
#print("Case 6.1.3")
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(0, 2**50 - 2**6)
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: random.choice([True, False]), RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(0, 2**50 - pc_0 - 2**6)
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 64):
|
||||
#print("Case 6.2")
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(0, 2**50 - 2 ** 6)
|
||||
ftqValid = True
|
||||
# randOffset: fault prediction location
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(randOffset + 1)] + [False for _ in range(PREDICT_WIDTH - randOffset - 1)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
instrValid[randOffset] = False
|
||||
pds = [{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0}
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
# randOffset_1: true jump instr location
|
||||
if randOffset != 15:
|
||||
randOffset_1 = random.randint(randOffset + 1, 15)
|
||||
pds[randOffset_1] = random.choice([{RVC_LABEL: random.choice([True, False]), RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
jumpOffset[randOffset_1] = random.randint(0, 2**50 - pc_0 - 2**6)
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 71):
|
||||
#print("Case 7.1.1")
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(0, 2**50 - 2 ** 6)
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(randOffset + 1)] + [False for _ in range(PREDICT_WIDTH - randOffset - 1)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0}
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 72):
|
||||
#print("Case 7.1.2")
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(0, 2**50 - 2 ** 6)
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(randOffset + 1)] + [False for _ in range(PREDICT_WIDTH - randOffset - 1)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: random.choice([True, False]), RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(4, 2**50 - pc_0)
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
|
||||
elif(caseId == 73):
|
||||
#print("Case 7.2")
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(0, 2**50 - 2 ** 6)
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(randOffset + 1)] + [False for _ in range(PREDICT_WIDTH - randOffset - 1)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: random.choice([True, False]), RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(4, 2**50 - pc_0)
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset] + 10086
|
||||
|
||||
elif(caseId == 81):
|
||||
#print("Case 8")
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(0, 2**50 - 2 ** 6)
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(randOffset + 1)] + [False for _ in range(PREDICT_WIDTH - randOffset - 1)]
|
||||
instrValid = [random.choice([True, False]) for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: random.choice([True, False]), RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
negJumpOffset = - 2**50
|
||||
while (negJumpOffset + pc_0 < 0):
|
||||
negJumpOffset = random.randint(-(2**50), -4)
|
||||
posJumpOffset = random.randint(4, 2**50 - pc[PREDICT_WIDTH - 1])
|
||||
jumpOffset[randOffset] = random.choice([negJumpOffset, posJumpOffset])
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
if tgt >= 2**50:
|
||||
tgt = tgt - 2**50
|
||||
|
||||
elif(caseId == 82):
|
||||
# Case 8 with additional target boundary test
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = random.randint(2**50 - 2 ** 8, 2**50 - 2**6 - 1) # boundary pc
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(randOffset + 1)] + [False for _ in range(PREDICT_WIDTH - randOffset - 1)]
|
||||
instrValid = [random.choice([True, False]) for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = random.choice([{RVC_LABEL: random.choice([True, False]), RET_LABEL: True, BRTYPE_LABEL: 3},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL: False, BRTYPE_LABEL: 2},
|
||||
{RVC_LABEL: random.choice([True, False]), RET_LABEL:False, BRTYPE_LABEL:1}])
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
negJumpOffset = - 2**50
|
||||
while (negJumpOffset + pc_0 < 0):
|
||||
negJumpOffset = random.randint(-(2**50), -4)
|
||||
posJumpOffset = random.randint(4, 2**50 - pc[PREDICT_WIDTH - 1])
|
||||
jumpOffset[randOffset] = random.choice([negJumpOffset, posJumpOffset])
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
if tgt >= 2**50:
|
||||
tgt = tgt - 2**50
|
||||
|
||||
elif(caseId == 83):
|
||||
# Case 8 with additional target boundary test: overflow
|
||||
randOffset = random.randint(0, 15)
|
||||
pc_0 = 2**50 - random.randint(1, 65) # boundary pc
|
||||
ftqValid = True
|
||||
ftqOffBits = randOffset
|
||||
instrRange = [True for _ in range(randOffset + 1)] + [False for _ in range(PREDICT_WIDTH - randOffset - 1)]
|
||||
instrValid = [True for _ in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 0} for _ in range(PREDICT_WIDTH)]
|
||||
pds[randOffset] = {RVC_LABEL: False, RET_LABEL: False, BRTYPE_LABEL: 2}
|
||||
pc = self._gen_pc_list(pc_0, pds)
|
||||
jumpOffset = [0 for _ in range(PREDICT_WIDTH)]
|
||||
jumpOffset[randOffset] = random.randint(66, 128)
|
||||
tgt = pc[randOffset] + jumpOffset[randOffset]
|
||||
if tgt >= 2**50:
|
||||
tgt = tgt - 2**50
|
||||
|
||||
|
||||
else:
|
||||
print(f"Invalid case number, caseId == {caseId}")
|
||||
assert caseId == -1, "caseId error"
|
||||
|
||||
vec = [ftqValid, ftqOffBits, instrRange, instrValid, jumpOffset, pc, pds, tgt, fire]
|
||||
#print("Generated test vector: ftqValid, ftqOffBits, instrRange, instrValid, jumpOffset, pc, pds, tgt, fire\n", vec)
|
||||
return vec
|
||||
|
||||
def _gen_pc_list(self, pc_0, pds_info):
|
||||
pc = [0 for i in range(PREDICT_WIDTH)]
|
||||
for i in range(PREDICT_WIDTH - 1):
|
||||
pc[0] = pc_0;
|
||||
if pds_info[i][RVC_LABEL] == False:
|
||||
pc[i + 1] = pc[i] + 4
|
||||
else:
|
||||
pc[i + 1] = pc[i] + 2
|
||||
return pc
|
||||
|
|
@ -1,25 +1,144 @@
|
|||
import toffee_test
|
||||
import toffee
|
||||
from operator import *
|
||||
from ..env import PredCheckerEnv
|
||||
from dut.PredChecker import DUTPredChecker
|
||||
import toffee.funcov as fc
|
||||
from toffee.funcov import CovGroup
|
||||
from comm.functions import UT_FCOV, module_name_with
|
||||
from ... import PREDICT_WIDTH, RET_LABEL, RVC_LABEL, BRTYPE_LABEL
|
||||
|
||||
def pred_checker_cover_point(pred_checker):
|
||||
g = CovGroup("predChecker addition function")
|
||||
# g.add_cover_point(pred_checker.io_out_stage1Out_fixedRange_0, {"io_stage1Out_fixedRange is 0": fc.Eq(0)}, name="stage1Out0 is 0")
|
||||
# moudle path is ut_frontend.ifu.pred_checker.test.pred_checker_dut
|
||||
gr = fc.CovGroup(UT_FCOV("../../../pred_checker"))
|
||||
|
||||
def init_pred_checker_funcov(dut:DUTPredChecker, g:fc.CovGroup, env:PredCheckerEnv):
|
||||
mdl = env.mdl
|
||||
# For function point 1 - JAL prediction error checking:
|
||||
# NO_JAL_FALSE_REPORT - 误检检查: False detection test
|
||||
for j in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut, {
|
||||
"JAL_PRED_VALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 1,
|
||||
"JAL_PRED_INVALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 0,
|
||||
f"JAL_INSTR_VALID_{j}": lambda dut: getattr(dut, f"io_in_instrValid_{j}").value == 1,
|
||||
f"JAL_INSTR_RANGE_{j}": lambda dut: sum(getattr(dut, f"io_in_instrRange_{i}").value for i in range(PREDICT_WIDTH)) == j,
|
||||
f"JAL_PRED_OFFSET_AT_{j}": lambda dut: getattr(dut, f"io_in_ftqOffset_bits").value == j,
|
||||
f"JAL_PDS_INFO_AT_{j}": lambda dut: getattr(dut, f"io_in_pds_{j}_brType").value == 2
|
||||
}, name=f"JAL_PRED_COV_{j}")
|
||||
|
||||
# For function point 2 - RET prediction error checking:
|
||||
for j in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut, {
|
||||
"RET_PRED_VALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 1,
|
||||
"RET_PRED_INVALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 0,
|
||||
f"RET_INSTR_VALID_{j}": lambda dut: getattr(dut, f"io_in_instrValid_{j}").value == 1,
|
||||
f"RET_INSTR_RANGE_{j}": lambda dut: sum(getattr(dut, f"io_in_instrRange_{i}").value for i in range(PREDICT_WIDTH)) == j,
|
||||
f"RET_PRED_OFFSET_AT_{j}": lambda dut: getattr(dut, f"io_in_ftqOffset_bits").value == j,
|
||||
f"RET_PDS_INFO_AT_{j}": lambda dut: getattr(dut, f"io_in_pds_{j}_brType").value == 3
|
||||
}, name=f"RET_PRED_COV_{j}")
|
||||
|
||||
# For function point 2 - RET prediction error checking:
|
||||
for j in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut, {
|
||||
"RET_PRED_VALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 1,
|
||||
"RET_PRED_INVALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 0,
|
||||
f"RET_INSTR_VALID_{j}": lambda dut: getattr(dut, f"io_in_instrValid_{j}").value == 1,
|
||||
f"RET_INSTR_RANGE_{j}": lambda dut: sum(getattr(dut, f"io_in_instrRange_{i}").value for i in range(PREDICT_WIDTH)) == j,
|
||||
f"RET_PRED_OFFSET_AT_{j}": lambda dut: getattr(dut, f"io_in_ftqOffset_bits").value == j,
|
||||
f"RET_PDS_INFO_AT_{j}": lambda dut: getattr(dut, f"io_in_pds_{j}_brType").value == 3
|
||||
}, name=f"JALR_PRED_COV_{j}")
|
||||
|
||||
# For function point 4 - Renewing instruction range:
|
||||
for j in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut, {
|
||||
f"RANGE_LENGTH_{j}_COV": lambda dut: sum(1 for i in range(PREDICT_WIDTH) if getattr(dut, f"io_in_instrRange_{i}").value == 1) == j
|
||||
}, name=f"RANGE_FIXING_COV_{j}")
|
||||
|
||||
# For function point 5 - Not-CFI instruction checking
|
||||
for j in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut,{
|
||||
"CFI_PRED_VALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 1,
|
||||
"CFI_PRED_INVALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 0,
|
||||
f"CFI_INSTR_VALID_{j}": lambda dut: getattr(dut, f"io_in_instrValid_{j}").value == 1,
|
||||
f"CFI_INSTR_RANGE_{j}": lambda dut: sum(getattr(dut, f"io_in_instrRange_{i}").value for i in range(PREDICT_WIDTH)) == j,
|
||||
f"CFI_PRED_OFFSET_AT_{j}": lambda dut: getattr(dut, f"io_in_ftqOffset_bits").value == j,
|
||||
f"CFI_PDS_INFO_AT_{j}": lambda dut: getattr(dut, f"io_in_pds_{j}_brType").value > 0
|
||||
}, name=f"CFI_PRED_COV_{j}")
|
||||
|
||||
# For function point 6 - Invalid instruction checking
|
||||
for j in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut,{
|
||||
"INV_PRED_VALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 1,
|
||||
"INV_PRED_INVALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 0,
|
||||
f"INV_INSTR_OFFSET_{j}": lambda dut: getattr(dut, f"io_in_instrValid_{j}").value == 0,
|
||||
f"INV_INSTR_RANGE_{j}": lambda dut: sum(getattr(dut, f"io_in_instrRange_{i}").value for i in range(PREDICT_WIDTH)) == j,
|
||||
f"INV_PRED_OFFSET_AT_{j}": lambda dut: getattr(dut, f"io_in_ftqOffset_bits").value == j,
|
||||
}, name=f"INV_PRED_COV_{j}")
|
||||
|
||||
# For function point 7 - Target error checking
|
||||
for j in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut,
|
||||
{
|
||||
"TGT_CFI_PRED_VALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 1,
|
||||
"TGT_CFI_PRED_INVALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 0,
|
||||
"TGT_CFI_INSTR_VALID": lambda dut: getattr(dut, f"io_in_instrValid_{j}").value == 1,
|
||||
f"TGT_CFI_INSTR_RANGE_{j}": lambda dut: sum(getattr(dut, f"io_in_instrRange_{i}").value for i in range(PREDICT_WIDTH)) == j,
|
||||
f"TGT_CFI_PRED_OFFSET_AT_{j}": lambda dut: getattr(dut, f"io_in_ftqOffset_bits").value == j,
|
||||
f"TGT_CFI_PDS_INFO_AT_{j}": lambda dut: getattr(dut, f"io_in_pds_{j}_brType").value > 0,
|
||||
f"TGT_CFI_JMPOFFSET_VAL_{j}": lambda dut: getattr(dut, f"io_in_jumpOffset_{j}").value > 0,
|
||||
f"TGT_CFI_TGT_VAL": lambda dut: getattr(dut, "io_in_target").value > 0,
|
||||
f"TGT_CFI_PC_VAL_{j}": lambda dut: getattr(dut, f"io_in_pc_{j}").value > 2**50 - 2**6 - 4
|
||||
},
|
||||
name=f"TGT_ERROR_COV_{j}",
|
||||
)
|
||||
|
||||
# For function point 8 - Random target checking
|
||||
for i in range(PREDICT_WIDTH):
|
||||
g.add_watch_point(dut,{
|
||||
"RAND_PRED_VALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 1,
|
||||
"RAND_PRED_INVALID": lambda dut: getattr(dut, "io_in_ftqOffset_valid").value == 0,
|
||||
"RAND_INSTR_VALID": lambda dut: getattr(dut, f"io_in_instrValid_{j}").value == 1,
|
||||
"RAND_INSTR_RANGE": lambda dut: sum(getattr(dut, f"io_in_instrRange_{i}").value for i in range(PREDICT_WIDTH)) == j,
|
||||
f"RAND_PRED_OFFSET_AT_{j}": lambda dut: getattr(dut, f"io_in_ftqOffset_bits").value == j,
|
||||
f"RAND_PDS_INFO_AT_{j}": lambda dut: getattr(dut, f"io_in_pds_{j}_brType").value > 0,
|
||||
f"RAND_JMPOFFSET_VAL_{j}": lambda dut: getattr(dut, f"io_in_jumpOffset_{j}").value > 0,
|
||||
f"RAND_TGT_VAL": lambda dut: getattr(dut, "io_in_target").value > 0,
|
||||
f"RAND_PC_VAL_{j}": lambda dut: getattr(dut, f"io_in_pc_{j}").value > 2**50 - 2**6 - 4
|
||||
#f"FIXED_TARGET_{i}_CORRECT": lambda dut: getattr(dut, f"io_out_stage2Out_fixedTarget_{i}").value == mdl.pc[i] + mdl.jumpOffset[i]
|
||||
# or getattr(dut, f"io_out_stage2Out_fixedTarget_{i}").value == mdl.pc[i] + mdl.jumpOffset[i] - 2**50
|
||||
# or getattr(dut, f"io_out_stage2Out_fixedTarget_{i}").value == mdl.pc[i] + 2
|
||||
# or getattr(dut, f"io_out_stage2Out_fixedTarget_{i}").value == mdl.pc[i] + 4,
|
||||
#f"JAL_TARGET_{i}_CORRECT": lambda dut: getattr(dut, f"io_out_stage2Out_jalTarget_{i}").value == mdl.pc[i] + mdl.jumpOffset[i]
|
||||
# or getattr(dut, f"io_out_stage2Out_jalTarget_{i}").value == mdl.pc[i] + mdl.jumpOffset[i] - 2**50,
|
||||
#f"FIXED_TARGET_{i}_BOUNDARY": lambda dut: getattr(dut, f"io_out_stage2Out_fixedTarget_{i}").value > 0x3_FFFF_FFFF_FFC0,
|
||||
#f"JAL_TARGET_{i}_BOUNDARY": lambda dut: getattr(dut, f"io_out_stage2Out_jalTarget_{i}").value > 0x3_FFFF_FFFF_FFC0
|
||||
},
|
||||
name=f"TARGET_{i}_COV")
|
||||
|
||||
# Reverse mark
|
||||
def _mark_name(name):
|
||||
return module_name_with(name, "../../test_predchecker")
|
||||
|
||||
|
||||
for i in range(PREDICT_WIDTH):
|
||||
g.mark_function(f"JAL_PRED_COV_{i}", _mark_name(["test_jal_chk_1_1_1", "test_jal_chk_1_1_2", "test_jal_chk_1_2_1", "test_jal_chk_1_2_2"]))
|
||||
g.mark_function(f"RET_PRED_COV_{i}", _mark_name(["test_ret_chk_2_1_1", "test_ret_chk_2_1_2", "test_ret_chk_2_2_1", "test_ret_chk_2_2_2"]))
|
||||
g.mark_function(f"JALR_PRED_COV_{i}", _mark_name(["test_jalr_chk_3_1_1", "test_jalr_chk_3_1_2", "test_jalr_chk_3_2_1", "test_jalr_chk_3_2_2"]))
|
||||
g.mark_function(f"RANGE_FIXING_COV_{i}", _mark_name(["test_renew_range_4_1", "test_renew_range_4_2", "test_renew_range_4_3"]))
|
||||
g.mark_function(f"CFI_PRED_COV_{i}", _mark_name(["test_not_cfi_chk_5_1_1", "test_not_cfi_chk_5_1_2", "test_not_cfi_chk_5_2"]))
|
||||
g.mark_function(f"INV_PRED_COV_{i}", _mark_name(["test_invalid_instr_chk_6_1_1","test_invalid_instr_chk_6_1_2", "test_invalid_instr_chk_6_1_3", "test_invalid_instr_chk_6_2" ]))
|
||||
g.mark_function(f"TGT_ERROR_COV_{i}", _mark_name(["test_tgt_chk_7_1_1", "test_tgt_chk_7_1_2", "test_tgt_chk_7_2"]))
|
||||
g.mark_function(f"TARGET_{i}_COV", _mark_name("test_rand_tgt_8"))
|
||||
|
||||
return g
|
||||
|
||||
|
||||
@toffee_test.fixture
|
||||
async def predchecker_env(toffee_request: toffee_test.ToffeeRequest):
|
||||
|
||||
toffee.setup_logging(toffee.WARNING)
|
||||
dut = toffee_request.create_dut(DUTPredChecker)
|
||||
toffee_request.add_cov_groups(pred_checker_cover_point(dut))
|
||||
dut.InitClock("clock")
|
||||
toffee.start_clock(dut)
|
||||
env = PredCheckerEnv(dut)
|
||||
toffee_request.add_cov_groups(init_pred_checker_funcov(dut, gr, env))
|
||||
yield env
|
||||
|
||||
import asyncio
|
||||
|
|
@ -30,4 +149,8 @@ async def predchecker_env(toffee_request: toffee_test.ToffeeRequest):
|
|||
try:
|
||||
await task
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
import toffee_test
|
||||
from ... import PREDICT_WIDTH, RET_LABEL, RVC_LABEL, BRTYPE_LABEL
|
||||
from dut.PredChecker import DUTPredChecker
|
||||
from .pred_checker_dut import predchecker_env
|
||||
# from pred_checker_dut import predchecker_env
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_fire(predchecker_env):
|
||||
valid = False
|
||||
bits = 0
|
||||
jumpOffset = [0 for i in range(PREDICT_WIDTH)]
|
||||
instrRange = [True for i in range(PREDICT_WIDTH)]
|
||||
instrValid = [True for i in range(PREDICT_WIDTH)] # all RVCs
|
||||
pc = [0 for i in range(PREDICT_WIDTH)]
|
||||
pds = [{RVC_LABEL: True, RET_LABEL: False, BRTYPE_LABEL: 0 } for i in range(PREDICT_WIDTH)]
|
||||
tgt = 0
|
||||
async for res in predchecker_env.predCheckerAgent.agent_pred_check(valid, bits, instrRange, instrValid, jumpOffset, pc, pds, tgt, True):
|
||||
print(res)
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
import toffee_test
|
||||
from ... import PREDICT_WIDTH, RET_LABEL, RVC_LABEL, BRTYPE_LABEL
|
||||
from dut.PredChecker import DUTPredChecker
|
||||
from .pred_checker_dut import predchecker_env
|
||||
from ..env.pred_checker_sqr import pred_checker_sqr
|
||||
import toffee.funcov as fc
|
||||
from comm.functions import UT_FCOV, module_name_with
|
||||
from toffee import *
|
||||
import os
|
||||
TEST_CYCLE = int(os.getenv("TEST_CYCLE", 100))
|
||||
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jal_chk_1_1_1(predchecker_env):
|
||||
print("Testing case 1.1.1")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 1)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jal_chk_1_1_2(predchecker_env):
|
||||
print("Testing case 1.1.2")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 2)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jal_chk_1_2_1(predchecker_env):
|
||||
print("Testing case 1.2.1")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 3)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jal_chk_1_2_2(predchecker_env):
|
||||
print("Testing case 1_2_2")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 4)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_ret_chk_2_1_1(predchecker_env):
|
||||
print("Testing case 2.1.1")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 21)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_ret_chk_2_1_2(predchecker_env):
|
||||
print("Testing case 2.1.1")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 22)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_ret_chk_2_2_1(predchecker_env):
|
||||
print("Testing case 2.2.1")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 23)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_ret_chk_2_2_2(predchecker_env):
|
||||
print("Testing case 2.2.2")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 24)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jalr_chk_3_1_1(predchecker_env):
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 31)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jalr_chk_3_1_2(predchecker_env):
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 32)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jalr_chk_3_2_1(predchecker_env):
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 33)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_jalr_chk_3_2_2(predchecker_env):
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 34)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_renew_range_4_1(predchecker_env):
|
||||
print("Test 4.1: If prediction is correct, check instrRange")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 41)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_renew_range_4_2(predchecker_env):
|
||||
print("Test 4.2: RET/JAL prediction fault, pds gave a narrower range")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 42)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_renew_range_4_3(predchecker_env):
|
||||
print("Test 4.3: No-CFI/Invalid prediction, fixing range to the first CFI instruction")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 43)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_not_cfi_chk_5_1_1(predchecker_env):
|
||||
print("Test case 5.1.1: Input do not exist CFI and FTQ hasn't given a jump prediction, check pred_checker report")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 51)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_not_cfi_chk_5_1_2(predchecker_env):
|
||||
print("Test case 5.1.2: Input a valid CFI and FTQ gave a correct jump prediction, check pred_checker report")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 52)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_not_cfi_chk_5_2(predchecker_env):
|
||||
print("Test case 5.2: Input no-exist CFI but FTQ gave a jump prediction, check pred_checker report")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 53)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_invalid_instr_chk_6_1_1(predchecker_env):
|
||||
print("Test case 6.1.1, pds gave no jump instruction info and FTQ gave no jump prediction, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 61)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_invalid_instr_chk_6_1_2(predchecker_env):
|
||||
print("Test case 6.1.2: pds gave an invalid instruction and FTQ gave no jump prediction, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 62)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_invalid_instr_chk_6_1_3(predchecker_env):
|
||||
print("Test 6.1.3: pds gave a jump instruction and FTQ gave a corrcet prediction, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 63)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_invalid_instr_chk_6_2(predchecker_env):
|
||||
print("Test 6.2, pds gave invalid instruction info but FTQ gave a jump prediction, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 64)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_tgt_chk_7_1_1(predchecker_env):
|
||||
print("Test case 7.1.1, pds has no jumping instruction and FTQ gave no jumping prediction, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 71)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_tgt_chk_7_1_2(predchecker_env):
|
||||
print("Test case 7.1.2, pds gave a jumping info and FTQ prediction is corresponding with it, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 72)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_tgt_chk_7_2(predchecker_env):
|
||||
print("Test 7.2, pds has jumping info but FTQ has error jumping target, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 73)
|
||||
for i in range(TEST_CYCLE):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_rand_tgt_8(predchecker_env):
|
||||
print("Test 8, random pds info, check result")
|
||||
sqr = pred_checker_sqr()
|
||||
vec_pkt = sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 81)
|
||||
vec_pkt.extend(sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 82))
|
||||
vec_pkt.extend(sqr.gen_vec(PREDICT_WIDTH, TEST_CYCLE, 83))
|
||||
for i in range(len(vec_pkt)):
|
||||
#print(*vec_pkt[i])
|
||||
res = await predchecker_env.predCheckerAgent.agent_pred_check(*vec_pkt[i])
|
||||
del sqr
|
||||
|
||||
|
|
@ -0,0 +1,363 @@
|
|||
from toffee.agent import *
|
||||
from ..bundle import TlbBundle
|
||||
from .itlb_trans import *
|
||||
from toffee import Executor
|
||||
from typing import List
|
||||
|
||||
class ItlbAgent(Agent):
|
||||
def __init__(self, bundle: TlbBundle):
|
||||
super().__init__(bundle)
|
||||
self.bundle = bundle
|
||||
self.drvReq0Flg = False
|
||||
self.drvReq1Flg = False
|
||||
self.drvReq2Flg = False
|
||||
|
||||
# drive signals into dut: Sfence signals
|
||||
async def drvSfence(self, cycles, sfenceBits, trSfence:ItlbTransSfence):
|
||||
print("drv sfence")
|
||||
for i in range(cycles):
|
||||
sfenceBits._rs1.value = trSfence.sfenceBitsRs1[i]
|
||||
sfenceBits._rs2.value = trSfence.sfenceBitsRs2[i]
|
||||
sfenceBits._addr.value = trSfence.sfenceBitsAddr[i]
|
||||
sfenceBits._id.value = trSfence.sfenceBitsId[i]
|
||||
sfenceBits._flushPipe.value = trSfence.sfenceBitsFlushPipe[i]
|
||||
sfenceBits._hv.value = trSfence.sfenceBitsHv[i]
|
||||
sfenceBits._hg.value = trSfence.sfenceBitsHg[i]
|
||||
await self.bundle.step()
|
||||
|
||||
# drive signals into dut: flush pip
|
||||
async def drvFlsPip(self, cycles, flushPipe, trFlsPip:ItlbTransFlsPipe):
|
||||
for i in range(cycles):
|
||||
#print("trDrvFls")
|
||||
flushPipe._0.value = trFlsPip.flushPipe0[i]
|
||||
flushPipe._1.value = trFlsPip.flushPipe1[i]
|
||||
flushPipe._2.value = trFlsPip.flushPipe2[i]
|
||||
await self.bundle.step()
|
||||
|
||||
# drive signals into dut: Csr signals
|
||||
def drvCsr(self, idx):
|
||||
csr = self.bundle.io._csr
|
||||
csr._satp._mode.value = self.trCsr.csrSatpMode[idx]
|
||||
csr._satp._asid.value = self.trCsr.csrSatpAsid[idx]
|
||||
csr._satp._changed.value = self.trCsr.csrSatpChanged[idx]
|
||||
csr._vsatp._mode.value = self.trCsr.csrVsatpMode[idx]
|
||||
csr._vsatp._asid.value = self.trCsr.csrVsatpAsid[idx]
|
||||
csr._vsatp._changed.value = self.trCsr.csrVsatpChanged[idx]
|
||||
csr._hgatp._mode.value = self.trCsr.csrHgatpMode[idx]
|
||||
csr._hgatp._vmid.value = self.trCsr.csrHgatpVmid[idx]
|
||||
csr._hgatp._changed.value = self.trCsr.csrHgatpChanged[idx]
|
||||
csr._priv._virt.value = self.trCsr.csrPrivVirt[idx]
|
||||
csr._priv._virt.value = self.trCsr.csrPrivImode[idx]
|
||||
#await self.bundle.step()
|
||||
|
||||
# drive signals: Requestor 0 or 1
|
||||
async def drvRequestor0(self, cycles, requestor, trReq:ItlbTransRqstReq):
|
||||
print("drvRequestor0")
|
||||
for i in range(cycles + 1):
|
||||
if(trReq.requestorReqBitsVaddr[i] != 0):
|
||||
print(f"i = {i}")
|
||||
print(f"Vaddr = {trReq.requestorReqBitsVaddr[i]}")
|
||||
requestor._req._valid.value = True
|
||||
requestor._req._bits_vaddr.value = trReq.requestorReqBitsVaddr[i]
|
||||
else:
|
||||
requestor._req._valid.value = False
|
||||
self.drvCsr(i)
|
||||
await self.bundle.step()
|
||||
requestor._req._valid.value = False
|
||||
self.drvReq0Flg = True
|
||||
|
||||
# drive signals: Requestor 0 or 1
|
||||
async def drvRequestor1(self, cycles, requestor, trReq:ItlbTransRqstReq):
|
||||
print("drvRequestor1")
|
||||
while(not self.drvReq0Flg):
|
||||
await self.bundle.step()
|
||||
for i in range(cycles + 1):
|
||||
if(trReq.requestorReqBitsVaddr[i] != 0):
|
||||
requestor._req._valid.value = True
|
||||
print(f"i = {i}")
|
||||
print(f"Vaddr = {trReq.requestorReqBitsVaddr[i]}")
|
||||
requestor._req._bits_vaddr.value = trReq.requestorReqBitsVaddr[i]
|
||||
else:
|
||||
requestor._req._valid.value = False
|
||||
self.drvCsr(i)
|
||||
await self.bundle.step()
|
||||
requestor._req._valid.value = False
|
||||
self.drvReq1Flg = True
|
||||
|
||||
# drive signals: requestor 2
|
||||
async def drvRequestor2(self, cycles, requestor, trReq:ItlbTransRqstReq):
|
||||
print("drvRequestor2")
|
||||
waitCycle = 0
|
||||
while(not self.drvReq1Flg):
|
||||
await self.bundle.step()
|
||||
print("drvReq1Flg is False")
|
||||
for i in range(cycles + 1):
|
||||
requestor._req._valid.value = False
|
||||
while(not requestor._req._ready.value):
|
||||
requestor._req._valid.value = False
|
||||
print(f"rqst2 blocked and waited {waitCycle} cycles")
|
||||
waitCycle += 1
|
||||
await self.bundle.step()
|
||||
# drive signals into dut: Requestor 2
|
||||
if(trReq.requestorReqBitsVaddr[i] != 0):
|
||||
print(f"i = {i}")
|
||||
print(f"Vaddr = {trReq.requestorReqBitsVaddr[i]}")
|
||||
requestor._req._valid.value = True
|
||||
requestor._req._bits_vaddr.value = trReq.requestorReqBitsVaddr[i]
|
||||
else:
|
||||
requestor._req._valid.value = False
|
||||
self.drvCsr(i)
|
||||
await self.bundle.step()
|
||||
requestor._req._valid.value = False
|
||||
self.drvReq2Flg = False
|
||||
|
||||
async def drvPtwResp(self, cycles, ptwResp, trPtwResp:ItlbTransPtwResp):
|
||||
for i in range(cycles):
|
||||
#print("trDrvPtwResp")
|
||||
ptwResp._valid.value = True
|
||||
ptwResp._bits._s2xlate.value = trPtwResp.s2xlate[i]
|
||||
ptwResp._bits._getGpa.value = trPtwResp.getgpa[i]
|
||||
ptwResp._bits._s1._entry._tag.value = trPtwResp.s1entrytag[i]
|
||||
ptwResp._bits._s1._entry._asid.value = trPtwResp.s1entryasid[i]
|
||||
ptwResp._bits._s1._entry._vmid.value = trPtwResp.s1entryvmid[i]
|
||||
ptwResp._bits._s1._entry._n.value = trPtwResp.s1entryn[i]
|
||||
ptwResp._bits._s1._entry._pbmt.value = trPtwResp.s1entrypbmt[i]
|
||||
ptwResp._bits._s1._entry._perm._d.value = trPtwResp.s1entrypermd[i]
|
||||
ptwResp._bits._s1._entry._perm._a.value = trPtwResp.s1entryperma[i]
|
||||
ptwResp._bits._s1._entry._perm._g.value = trPtwResp.s1entrypermg[i]
|
||||
ptwResp._bits._s1._entry._perm._u.value = trPtwResp.s1entrypermu[i]
|
||||
ptwResp._bits._s1._entry._perm._x.value = trPtwResp.s1entrypermx[i]
|
||||
ptwResp._bits._s1._entry._perm._w.value = trPtwResp.s1entrypermw[i]
|
||||
ptwResp._bits._s1._entry._perm._r.value = trPtwResp.s1entrypermr[i]
|
||||
ptwResp._bits._s1._entry._level.value = trPtwResp.s1entrylevel[i]
|
||||
ptwResp._bits._s1._entry._v.value = trPtwResp.s1entryv[i]
|
||||
ptwResp._bits._s1._entry._ppn.value = trPtwResp.s1entryppn[i]
|
||||
ptwResp._bits._s1._addr_low.value = trPtwResp.s1addrlow[i]
|
||||
ptwResp._bits._s1._ppn_low._0.value = trPtwResp.s1ppnlow0[i]
|
||||
ptwResp._bits._s1._ppn_low._1.value = trPtwResp.s1ppnlow1[i]
|
||||
ptwResp._bits._s1._ppn_low._2.value = trPtwResp.s1ppnlow2[i]
|
||||
ptwResp._bits._s1._ppn_low._3.value = trPtwResp.s1ppnlow3[i]
|
||||
ptwResp._bits._s1._ppn_low._4.value = trPtwResp.s1ppnlow4[i]
|
||||
ptwResp._bits._s1._ppn_low._5.value = trPtwResp.s1ppnlow5[i]
|
||||
ptwResp._bits._s1._ppn_low._6.value = trPtwResp.s1ppnlow6[i]
|
||||
ptwResp._bits._s1._ppn_low._7.value = trPtwResp.s1ppnlow7[i]
|
||||
ptwResp._bits._s1._valididx._0.value = trPtwResp.s1valididx0[i]
|
||||
ptwResp._bits._s1._valididx._1.value = trPtwResp.s1valididx1[i]
|
||||
ptwResp._bits._s1._valididx._2.value = trPtwResp.s1valididx2[i]
|
||||
ptwResp._bits._s1._valididx._3.value = trPtwResp.s1valididx3[i]
|
||||
ptwResp._bits._s1._valididx._4.value = trPtwResp.s1valididx4[i]
|
||||
ptwResp._bits._s1._valididx._5.value = trPtwResp.s1valididx5[i]
|
||||
ptwResp._bits._s1._valididx._6.value = trPtwResp.s1valididx6[i]
|
||||
ptwResp._bits._s1._valididx._7.value = trPtwResp.s1valididx7[i]
|
||||
ptwResp._bits._s1._pteidx._0.value = trPtwResp.s1pteidx0[i]
|
||||
ptwResp._bits._s1._pteidx._1.value = trPtwResp.s1pteidx1[i]
|
||||
ptwResp._bits._s1._pteidx._2.value = trPtwResp.s1pteidx2[i]
|
||||
ptwResp._bits._s1._pteidx._3.value = trPtwResp.s1pteidx3[i]
|
||||
ptwResp._bits._s1._pteidx._4.value = trPtwResp.s1pteidx4[i]
|
||||
ptwResp._bits._s1._pteidx._5.value = trPtwResp.s1pteidx5[i]
|
||||
ptwResp._bits._s1._pteidx._6.value = trPtwResp.s1pteidx6[i]
|
||||
ptwResp._bits._s1._pteidx._7.value = trPtwResp.s1pteidx7[i]
|
||||
ptwResp._bits._s1._pf.value = trPtwResp.s1pf[i]
|
||||
ptwResp._bits._s1._af.value = trPtwResp.s1af[i]
|
||||
await self.bundle.step()
|
||||
ptwResp._bits._s2._entry._tag.value = trPtwResp.s2entrytag[i]
|
||||
ptwResp._bits._s2._entry._vmid.value = trPtwResp.s2entryvmid[i]
|
||||
ptwResp._bits._s2._entry._n.value = trPtwResp.s2entryn[i]
|
||||
ptwResp._bits._s2._entry._pbmt.value = trPtwResp.s2entrypbmt[i]
|
||||
ptwResp._bits._s2._entry._ppn.value = trPtwResp.s2entryppn[i]
|
||||
ptwResp._bits._s2._entry._perm._d.value = trPtwResp.s2entrypermd[i]
|
||||
ptwResp._bits._s2._entry._perm._a.value = trPtwResp.s2entryperma[i]
|
||||
ptwResp._bits._s2._entry._perm._g.value = trPtwResp.s2entrypermg[i]
|
||||
ptwResp._bits._s2._entry._perm._u.value = trPtwResp.s2entrypermu[i]
|
||||
ptwResp._bits._s2._entry._perm._x.value = trPtwResp.s2entrypermx[i]
|
||||
ptwResp._bits._s2._entry._perm._w.value = trPtwResp.s2entrypermw[i]
|
||||
ptwResp._bits._s2._entry._perm._r.value = trPtwResp.s2entrypermr[i]
|
||||
ptwResp._bits._s2._entry._level.value = trPtwResp.s2entrylevel[i]
|
||||
ptwResp._bits._s2._gpf.value = trPtwResp.s2gpf[i]
|
||||
ptwResp._bits._s2._gaf.value = trPtwResp.s2gaf[i]
|
||||
await self.bundle.step()
|
||||
|
||||
# get signals: requestor 0 or 1
|
||||
async def monReqestor0(self, requestor, trResp:ItlbTransRqstResp):
|
||||
i = 0
|
||||
while(True):
|
||||
#print("trMonReq")
|
||||
if(i < trResp.validPktLen):
|
||||
trResp.requestorRespBitsPaddr[i] = requestor._resp_bits._paddr._0.value
|
||||
trResp.requestorRespBitsGpaddr[i] = requestor._resp_bits._gpaddr._0.value
|
||||
trResp.requestorRespBitsPbmt[i] = requestor._resp_bits._pbmt._0.value
|
||||
trResp.requestorRespBitsMiss[i] = requestor._resp_bits._miss.value
|
||||
trResp.requestorRespBitsIsForVSnonLeafPTE[i] = requestor._resp_bits._isForVSnonLeafPTE.value
|
||||
trResp.requestorRespBitsExcpGpfInstr[i] = requestor._resp_bits._excp._0._gpf_instr.value
|
||||
trResp.requestorRespBitsExcpPfInstr[i] = requestor._resp_bits._excp._0._pf_instr.value
|
||||
trResp.requestorRespBitsExcpAfInstr[i] = requestor._resp_bits._excp._0._af_instr.value
|
||||
i += 1
|
||||
await self.bundle.step()
|
||||
|
||||
# get signals: requestor 0 or 1
|
||||
async def monReqestor1(self, requestor, trResp:ItlbTransRqstResp):
|
||||
i = 0
|
||||
while(True):
|
||||
#print("trMonReq")
|
||||
if(i < trResp.validPktLen):
|
||||
trResp.requestorRespBitsPaddr[i] = requestor._resp_bits._paddr._0.value
|
||||
trResp.requestorRespBitsGpaddr[i] = requestor._resp_bits._gpaddr._0.value
|
||||
trResp.requestorRespBitsPbmt[i] = requestor._resp_bits._pbmt._0.value
|
||||
trResp.requestorRespBitsMiss[i] = requestor._resp_bits._miss.value
|
||||
trResp.requestorRespBitsIsForVSnonLeafPTE[i] = requestor._resp_bits._isForVSnonLeafPTE.value
|
||||
trResp.requestorRespBitsExcpGpfInstr[i] = requestor._resp_bits._excp._0._gpf_instr.value
|
||||
trResp.requestorRespBitsExcpPfInstr[i] = requestor._resp_bits._excp._0._pf_instr.value
|
||||
trResp.requestorRespBitsExcpAfInstr[i] = requestor._resp_bits._excp._0._af_instr.value
|
||||
i += 1
|
||||
await self.bundle.step()
|
||||
|
||||
|
||||
async def monRequestor2(self, requestor, trResp:ItlbTransRqstResp):
|
||||
i = 0
|
||||
while(True):
|
||||
#print("trMonReq2")
|
||||
requestor._resp._ready.value = True
|
||||
while(not requestor._resp._valid.value):
|
||||
await self.bundle.step()
|
||||
if(i < trResp.validPktLen):
|
||||
trResp.requestorRespBitsPaddr[i] = requestor._resp._bits._paddr._0.value
|
||||
trResp.requestorRespBitsGpaddr[i] = requestor._resp._bits._gpaddr._0.value
|
||||
trResp.requestorRespBitsPbmt[i] = requestor._resp._bits._pbmt._0.value
|
||||
trResp.requestorRespBitsIsForVSnonLeafPTE[i] = requestor._resp._bits._isForVSnonLeafPTE.value
|
||||
trResp.requestorRespBitsExcpGpfInstr[i] = requestor._resp._bits._excp._0._gpf_instr.value
|
||||
trResp.requestorRespBitsExcpPfInstr[i] = requestor._resp._bits._excp._0._pf_instr.value
|
||||
trResp.requestorRespBitsExcpAfInstr[i] = requestor._resp._bits._excp._0._af_instr.value
|
||||
i += 1
|
||||
await self.bundle.step()
|
||||
|
||||
async def monPtwReq0(self, ptwReq, trPtwReq:ItlbTransPtwReq):
|
||||
i = 0
|
||||
while(True):
|
||||
#print("trMonPtwReq")
|
||||
while(not ptwReq._valid.value):
|
||||
await self.bundle.step()
|
||||
if(i < trPtwReq.validPktLen):
|
||||
trPtwReq.reqBitsVpn[i] = ptwReq._bits._vpn.value
|
||||
trPtwReq.reqBitsGetGpa[i] = ptwReq._bits._getGpa.value
|
||||
trPtwReq.reqBitsS2Xlate[i] = ptwReq._bits._s2xlate.value
|
||||
i += 1
|
||||
await self.bundle.step()
|
||||
|
||||
async def monPtwReq1(self, ptwReq, trPtwReq:ItlbTransPtwReq):
|
||||
i = 0
|
||||
while(True):
|
||||
#print("trMonPtwReq")
|
||||
while(not ptwReq._valid.value):
|
||||
await self.bundle.step()
|
||||
if(i < trPtwReq.validPktLen):
|
||||
trPtwReq.reqBitsVpn[i] = ptwReq._bits._vpn.value
|
||||
trPtwReq.reqBitsGetGpa[i] = ptwReq._bits._getGpa.value
|
||||
trPtwReq.reqBitsS2Xlate[i] = ptwReq._bits._s2xlate.value
|
||||
i += 1
|
||||
await self.bundle.step()
|
||||
|
||||
async def monPtwReq2(self, ptwReq, trPtwReq:ItlbTransPtwReq):
|
||||
i = 0
|
||||
while(True):
|
||||
#print("trMonPtwReq2")
|
||||
ptwReq._ready.value = True
|
||||
while(not ptwReq._valid.value):
|
||||
await self.bundle.step()
|
||||
if(i < trPtwReq.validPktLen):
|
||||
trPtwReq.reqBitsVpn[i] = ptwReq._bits._vpn.value
|
||||
trPtwReq.reqBitsGetGpa[i] = ptwReq._bits._getGpa.value
|
||||
trPtwReq.reqBitsS2Xlate[i] = ptwReq._bits._s2xlate.value
|
||||
i += 1
|
||||
await self.bundle.step()
|
||||
|
||||
|
||||
async def delayCycle(self, cycles):
|
||||
print(f"Test clock cycles: {cycles}")
|
||||
await self.bundle.step(cycles)
|
||||
|
||||
# # driving signals with limited cycles
|
||||
# async def drv_lim_cycle(self, cycles, sfenceBits, csr, requestor0, requestor1, requestor2, flushPipe, ptwResp,
|
||||
# trSfence: ItlbTransSfence,
|
||||
# trCsr: ItlbTransCsr,
|
||||
# trRqstReq0: ItlbTransRqstReq, trRqstReq1: ItlbTransRqstReq, trRqstReq2: ItlbTransRqstReq,
|
||||
# trFlsPip: ItlbTransFlsPipe,
|
||||
# trPtwResp: ItlbTransPtwResp
|
||||
# ):
|
||||
# async with Executor(exit="any") as exec:
|
||||
# exec(self.drv_blocked(cycles, requestor2, ptwResp, trRqstReq2, ptwResp, trPtwResp))
|
||||
# exec(self.delayCycle(4*cycles))
|
||||
#
|
||||
# # driving signals with some blocking calls
|
||||
# async def drv_blocked(self, cycles, requestor2, ptwResp,
|
||||
# trRqstReq2: ItlbTransRqstReq,
|
||||
# trPtwResp: ItlbTransPtwResp
|
||||
# ):
|
||||
# async with Executor(exit="all") as exec:
|
||||
# exec(self.drvRequestor2(cycles, requestor2, trRqstReq2))
|
||||
# exec(self.drvPtwResp(cycles, ptwResp, trPtwResp))
|
||||
#
|
||||
# agent top func
|
||||
async def agent_itlb(self, cycles,
|
||||
trSfence: ItlbTransSfence,
|
||||
trCsr: ItlbTransCsr,
|
||||
trRqstReq0: ItlbTransRqstReq, trRqstReq1: ItlbTransRqstReq, trRqstReq2: ItlbTransRqstReq,
|
||||
trRqstResp0: ItlbTransRqstResp, trRqstResp1: ItlbTransRqstResp, trRqstResp2: ItlbTransRqstResp,
|
||||
trFlsPip: ItlbTransFlsPipe,
|
||||
trPtwReq0: ItlbTransPtwReq, trPtwReq1: ItlbTransPtwReq, trPtwReq2: ItlbTransPtwReq,
|
||||
trPtwResp: ItlbTransPtwResp
|
||||
):
|
||||
self.cycles = cycles
|
||||
|
||||
## bundle abbr
|
||||
# sfence
|
||||
sfenceBits = self.bundle.io._sfence._bits
|
||||
# csr
|
||||
csr = self.bundle.io._csr
|
||||
# requestor
|
||||
requestor0 = self.bundle.io._requestor._0
|
||||
requestor1 = self.bundle.io._requestor._1
|
||||
requestor2 = self.bundle.io._requestor._2
|
||||
# flushPipe
|
||||
flushPipe = self.bundle.io._flushPipe
|
||||
# ptw request
|
||||
ptwReq0 = self.bundle.io._ptw._req._0
|
||||
ptwReq1 = self.bundle.io._ptw._req._1
|
||||
ptwReq2 = self.bundle.io._ptw._req._2
|
||||
# ptw respond
|
||||
ptwResp = self.bundle.io._ptw._resp
|
||||
|
||||
self.trCsr = trCsr
|
||||
|
||||
# reset
|
||||
await self.bundle.step(1)
|
||||
self.bundle.reset.value = 1
|
||||
await self.bundle.step(2)
|
||||
self.bundle.reset.value = 0
|
||||
await self.bundle.step(8)
|
||||
|
||||
async with Executor(exit="none") as exec:
|
||||
# exec(self.drv_lim_cycle(cycles,
|
||||
# sfenceBits,csr,requestor0,requestor1,requestor2,flushPipe,ptwResp,
|
||||
# trSfence,
|
||||
# trCsr,
|
||||
# trRqstReq0,
|
||||
# trRqstReq1,
|
||||
# trRqstReq2,
|
||||
# trFlsPip,
|
||||
# trPtwResp
|
||||
# ))
|
||||
exec(self.drvSfence(cycles, sfenceBits, trSfence))
|
||||
exec(self.drvRequestor0(cycles, requestor0, trRqstReq0))
|
||||
exec(self.drvRequestor1(cycles, requestor1, trRqstReq1))
|
||||
exec(self.drvRequestor2(cycles, requestor2, trRqstReq1))
|
||||
exec(self.drvFlsPip(cycles, flushPipe, trFlsPip))
|
||||
exec(self.drvPtwResp(cycles, ptwResp, trPtwResp))
|
||||
exec(self.monReqestor0(requestor0, trRqstResp0))
|
||||
exec(self.monReqestor1(requestor1, trRqstResp1))
|
||||
exec(self.monRequestor2(requestor2, trRqstResp2))
|
||||
exec(self.monPtwReq0(ptwReq0, trPtwReq0))
|
||||
exec(self.monPtwReq1(ptwReq1, trPtwReq1))
|
||||
exec(self.monPtwReq2(ptwReq2, trPtwReq2))
|
||||
await self.bundle.step(4*cycles)
|
||||
|
||||
return 0
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
class baseTr():
|
||||
def __init__(self):
|
||||
self.startIdx = 0
|
||||
self.validPktLen = 0
|
||||
|
||||
# Trans packet for tlb
|
||||
class ItlbTransSfence(baseTr):
|
||||
def __init__(self, pktLen):
|
||||
super().__init__()
|
||||
self.validPktLen = pktLen
|
||||
self.sfenceBitsRs1 = [0] * pktLen
|
||||
self.sfenceBitsRs2 = [0] * pktLen
|
||||
self.sfenceBitsAddr = [0] * pktLen
|
||||
self.sfenceBitsId = [0] * pktLen
|
||||
self.sfenceBitsFlushPipe = [0] * pktLen
|
||||
self.sfenceBitsHv = [0] * pktLen
|
||||
self.sfenceBitsHg = [0] * pktLen
|
||||
|
||||
class ItlbTransCsr(baseTr):
|
||||
def __init__(self, pktLen):
|
||||
super().__init__()
|
||||
self.validPktLen = pktLen
|
||||
self.csrSatpMode = [0] * pktLen
|
||||
self.csrSatpAsid = [0] * pktLen
|
||||
self.csrSatpChanged = [0] * pktLen
|
||||
self.csrVsatpMode = [0] * pktLen
|
||||
self.csrVsatpAsid = [0] * pktLen
|
||||
self.csrVsatpChanged = [0] * pktLen
|
||||
self.csrHgatpMode = [0] * pktLen
|
||||
self.csrHgatpVmid = [0] * pktLen
|
||||
self.csrHgatpChanged = [0] * pktLen
|
||||
self.csrPrivVirt = [0] * pktLen
|
||||
self.csrPrivImode = [0] * pktLen
|
||||
|
||||
class ItlbTransRqstReq(baseTr):
|
||||
def __init__(self, pktLen):
|
||||
super().__init__()
|
||||
self.validPktLen = pktLen
|
||||
self.requestorReqBitsVaddr = [0] * pktLen
|
||||
|
||||
class ItlbTransRqstResp(baseTr):
|
||||
def __init__(self, pktLen):
|
||||
super().__init__()
|
||||
self.validPktLen = pktLen
|
||||
self.requestorRespBitsPaddr = [0] * pktLen
|
||||
self.requestorRespBitsGpaddr = [0] * pktLen
|
||||
self.requestorRespBitsPbmt = [0] * pktLen
|
||||
self.requestorRespBitsMiss = [0] * pktLen
|
||||
self.requestorRespBitsIsForVSnonLeafPTE = [0] * pktLen
|
||||
self.requestorRespBitsExcpGpfInstr = [0] * pktLen
|
||||
self.requestorRespBitsExcpPfInstr = [0] * pktLen
|
||||
self.requestorRespBitsExcpAfInstr = [0] * pktLen
|
||||
|
||||
class ItlbTransFlsPipe(baseTr):
|
||||
def __init__(self, pktLen):
|
||||
super().__init__()
|
||||
self.validPktLen = pktLen
|
||||
self.flushPipe0 = [0] * pktLen
|
||||
self.flushPipe1 = [0] * pktLen
|
||||
self.flushPipe2 = [0] * pktLen
|
||||
|
||||
class ItlbTransPtwReq(baseTr):
|
||||
def __init__(self, pktLen):
|
||||
super().__init__()
|
||||
self.validPktLen = pktLen
|
||||
self.reqBitsVpn = [0] * pktLen
|
||||
self.reqBitsS2Xlate = [0] * pktLen
|
||||
self.reqBitsGetGpa = [0] * pktLen
|
||||
|
||||
class ItlbTransPtwResp(baseTr):
|
||||
def __init__(self, pktLen):
|
||||
super().__init__()
|
||||
self.validPktLen = pktLen
|
||||
self.s2xlate = [0] * pktLen
|
||||
self.s1entrytag = [0] * pktLen
|
||||
self.s1entryasid = [0] * pktLen
|
||||
self.s1entryvmid = [0] * pktLen
|
||||
self.s1entryn = [0] * pktLen
|
||||
self.s1entrypbmt = [0] * pktLen
|
||||
self.s1entrypermd = [0] * pktLen
|
||||
self.s1entryperma = [0] * pktLen
|
||||
self.s1entrypermg = [0] * pktLen
|
||||
self.s1entrypermu = [0] * pktLen
|
||||
self.s1entrypermx = [0] * pktLen
|
||||
self.s1entrypermw = [0] * pktLen
|
||||
self.s1entrypermr = [0] * pktLen
|
||||
self.s1entrylevel = [0] * pktLen
|
||||
self.s1entryv = [0] * pktLen
|
||||
self.s1entryppn = [0] * pktLen
|
||||
self.s1addrlow = [0] * pktLen
|
||||
self.s1ppnlow0 = [0] * pktLen
|
||||
self.s1ppnlow1 = [0] * pktLen
|
||||
self.s1ppnlow2 = [0] * pktLen
|
||||
self.s1ppnlow3 = [0] * pktLen
|
||||
self.s1ppnlow4 = [0] * pktLen
|
||||
self.s1ppnlow5 = [0] * pktLen
|
||||
self.s1ppnlow6 = [0] * pktLen
|
||||
self.s1ppnlow7 = [0] * pktLen
|
||||
self.s1valididx0 = [0] * pktLen
|
||||
self.s1valididx1 = [0] * pktLen
|
||||
self.s1valididx2 = [0] * pktLen
|
||||
self.s1valididx3 = [0] * pktLen
|
||||
self.s1valididx4 = [0] * pktLen
|
||||
self.s1valididx5 = [0] * pktLen
|
||||
self.s1valididx6 = [0] * pktLen
|
||||
self.s1valididx7 = [0] * pktLen
|
||||
self.s1pteidx0 = [0] * pktLen
|
||||
self.s1pteidx1 = [0] * pktLen
|
||||
self.s1pteidx2 = [0] * pktLen
|
||||
self.s1pteidx3 = [0] * pktLen
|
||||
self.s1pteidx4 = [0] * pktLen
|
||||
self.s1pteidx5 = [0] * pktLen
|
||||
self.s1pteidx6 = [0] * pktLen
|
||||
self.s1pteidx7 = [0] * pktLen
|
||||
self.s1pf = [0] * pktLen
|
||||
self.s1af = [0] * pktLen
|
||||
self.s2entrytag = [0] * pktLen
|
||||
self.s2entryvmid = [0] * pktLen
|
||||
self.s2entryn = [0] * pktLen
|
||||
self.s2entrypbmt = [0] * pktLen
|
||||
self.s2entryppn = [0] * pktLen
|
||||
self.s2entrypermd = [0] * pktLen
|
||||
self.s2entryperma = [0] * pktLen
|
||||
self.s2entrypermg = [0] * pktLen
|
||||
self.s2entrypermu = [0] * pktLen
|
||||
self.s2entrypermx = [0] * pktLen
|
||||
self.s2entrypermw = [0] * pktLen
|
||||
self.s2entrypermr = [0] * pktLen
|
||||
self.s2entrylevel = [0] * pktLen
|
||||
self.s2gpf = [0] * pktLen
|
||||
self.s2gaf = [0] * pktLen
|
||||
self.getgpa = [0] * pktLen
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
from .auto_bundle import TlbBundle
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
from toffee import Bundle, Signals, Signal
|
||||
|
||||
class _0Bundle(Bundle):
|
||||
_vmid, _changed, _mode = Signals(3)
|
||||
|
||||
class _1Bundle(Bundle):
|
||||
_imode, _virt = Signals(2)
|
||||
|
||||
class _2Bundle(Bundle):
|
||||
_changed, _mode, _asid = Signals(3)
|
||||
|
||||
class _3Bundle(Bundle):
|
||||
_priv = _1Bundle.from_prefix("_priv")
|
||||
_vsatp = _2Bundle.from_prefix("_vsatp")
|
||||
_satp = _2Bundle.from_prefix("_satp")
|
||||
_hgatp = _0Bundle.from_prefix("_hgatp")
|
||||
|
||||
class _4Bundle(Bundle):
|
||||
_1, _2, _0 = Signals(3)
|
||||
|
||||
class _5Bundle(Bundle):
|
||||
_getGpa, _vpn, _s2xlate = Signals(3)
|
||||
|
||||
class _6Bundle(Bundle):
|
||||
_bits = _5Bundle.from_prefix("_bits")
|
||||
_valid = Signal()
|
||||
|
||||
class _7Bundle(Bundle):
|
||||
_bits = _5Bundle.from_prefix("_bits")
|
||||
_valid, _ready = Signals(2)
|
||||
|
||||
class _8Bundle(Bundle):
|
||||
_2 = _7Bundle.from_prefix("_2")
|
||||
_1 = _6Bundle.from_prefix("_1")
|
||||
_0 = _6Bundle.from_prefix("_0")
|
||||
|
||||
class _9Bundle(Bundle):
|
||||
_g, _r, _w, _a, _u, _d, _x = Signals(7)
|
||||
|
||||
class _10Bundle(Bundle):
|
||||
_perm = _9Bundle.from_prefix("_perm")
|
||||
_level, _tag, _pbmt, _v, _vmid, _asid, _ppn, _n = Signals(8)
|
||||
|
||||
class _11Bundle(Bundle):
|
||||
_6, _4, _3, _0, _1, _7, _2, _5 = Signals(8)
|
||||
|
||||
class _12Bundle(Bundle):
|
||||
_valididx = _11Bundle.from_prefix("_valididx")
|
||||
_ppn_low = _11Bundle.from_prefix("_ppn_low")
|
||||
_pteidx = _11Bundle.from_prefix("_pteidx")
|
||||
_entry = _10Bundle.from_prefix("_entry")
|
||||
_af, _addr_low, _pf = Signals(3)
|
||||
|
||||
class _13Bundle(Bundle):
|
||||
_perm = _9Bundle.from_prefix("_perm")
|
||||
_level, _tag, _pbmt, _vmid, _ppn, _n = Signals(6)
|
||||
|
||||
class _14Bundle(Bundle):
|
||||
_entry = _13Bundle.from_prefix("_entry")
|
||||
_gpf, _gaf = Signals(2)
|
||||
|
||||
class _15Bundle(Bundle):
|
||||
_s1 = _12Bundle.from_prefix("_s1")
|
||||
_s2 = _14Bundle.from_prefix("_s2")
|
||||
_getGpa, _s2xlate = Signals(2)
|
||||
|
||||
class _16Bundle(Bundle):
|
||||
_bits = _15Bundle.from_prefix("_bits")
|
||||
_valid = Signal()
|
||||
|
||||
class _17Bundle(Bundle):
|
||||
_req = _8Bundle.from_prefix("_req")
|
||||
_resp = _16Bundle.from_prefix("_resp")
|
||||
|
||||
class _18Bundle(Bundle):
|
||||
_valid, _bits_vaddr = Signals(2)
|
||||
|
||||
class _19Bundle(Bundle):
|
||||
_af_instr, _pf_instr, _gpf_instr = Signals(3)
|
||||
|
||||
class _20Bundle(Bundle):
|
||||
_0 = _19Bundle.from_prefix("_0")
|
||||
|
||||
class _21Bundle(Bundle):
|
||||
_0 = Signal()
|
||||
|
||||
class _22Bundle(Bundle):
|
||||
_gpaddr = _21Bundle.from_prefix("_gpaddr")
|
||||
_pbmt = _21Bundle.from_prefix("_pbmt")
|
||||
_paddr = _21Bundle.from_prefix("_paddr")
|
||||
_excp = _20Bundle.from_prefix("_excp")
|
||||
_miss, _isForVSnonLeafPTE = Signals(2)
|
||||
|
||||
class _23Bundle(Bundle):
|
||||
_resp_bits = _22Bundle.from_prefix("_resp_bits")
|
||||
_req = _18Bundle.from_prefix("_req")
|
||||
|
||||
class _24Bundle(Bundle):
|
||||
_valid, _bits_vaddr, _ready = Signals(3)
|
||||
|
||||
class _25Bundle(Bundle):
|
||||
_gpaddr = _21Bundle.from_prefix("_gpaddr")
|
||||
_pbmt = _21Bundle.from_prefix("_pbmt")
|
||||
_paddr = _21Bundle.from_prefix("_paddr")
|
||||
_excp = _20Bundle.from_prefix("_excp")
|
||||
_isForVSnonLeafPTE = Signal()
|
||||
|
||||
class _26Bundle(Bundle):
|
||||
_bits = _25Bundle.from_prefix("_bits")
|
||||
_valid, _ready = Signals(2)
|
||||
|
||||
class _27Bundle(Bundle):
|
||||
_resp = _26Bundle.from_prefix("_resp")
|
||||
_req = _24Bundle.from_prefix("_req")
|
||||
|
||||
class _28Bundle(Bundle):
|
||||
_0 = _23Bundle.from_prefix("_0")
|
||||
_1 = _23Bundle.from_prefix("_1")
|
||||
_2 = _27Bundle.from_prefix("_2")
|
||||
|
||||
class _29Bundle(Bundle):
|
||||
_rs2, _rs1, _hg, _flushPipe, _hv, _addr, _id = Signals(7)
|
||||
|
||||
class _30Bundle(Bundle):
|
||||
_bits = _29Bundle.from_prefix("_bits")
|
||||
_valid = Signal()
|
||||
|
||||
class _31Bundle(Bundle):
|
||||
_flushPipe = _4Bundle.from_prefix("_flushPipe")
|
||||
_sfence = _30Bundle.from_prefix("_sfence")
|
||||
_csr = _3Bundle.from_prefix("_csr")
|
||||
_ptw = _17Bundle.from_prefix("_ptw")
|
||||
_requestor = _28Bundle.from_prefix("_requestor")
|
||||
|
||||
class TlbBundle(Bundle):
|
||||
clock, reset = Signals(2)
|
||||
io = _31Bundle.from_prefix("io")
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
from toffee import Env
|
||||
from ..agent import itlb_agent
|
||||
from ..bundle import TlbBundle
|
||||
from dut.TLB import DUTTLB
|
||||
from .itlb_mdl import *
|
||||
|
||||
class ItlbEnv(Env):
|
||||
def __init__(self, dut:DUTTLB):
|
||||
super().__init__()
|
||||
self.itlbAgent = itlb_agent.ItlbAgent(TlbBundle.from_prefix("").bind(dut))
|
||||
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
from ..agent.itlb_trans import *
|
||||
import random
|
||||
|
||||
class ItlbSqr:
|
||||
def __init__(self, pktLen):
|
||||
self.pktLen = pktLen
|
||||
self.trSfence = ItlbTransSfence(2*self.pktLen)
|
||||
self.trCsr = ItlbTransCsr(2*self.pktLen)
|
||||
self.trRqstReq0 = ItlbTransRqstReq(2*self.pktLen)
|
||||
self.trRqstReq1 = ItlbTransRqstReq(2*self.pktLen)
|
||||
self.trRqstReq2 = ItlbTransRqstReq(2*self.pktLen)
|
||||
self.trRqstResp0 = ItlbTransRqstResp(2*self.pktLen)
|
||||
self.trRqstResp1 = ItlbTransRqstResp(2*self.pktLen)
|
||||
self.trRqstResp2 = ItlbTransRqstResp(2*self.pktLen)
|
||||
self.trFlsPip = ItlbTransFlsPipe(2*self.pktLen)
|
||||
self.trPtwReq0 = ItlbTransPtwReq(2*self.pktLen)
|
||||
self.trPtwReq1 = ItlbTransPtwReq(2*self.pktLen)
|
||||
self.trPtwReq2 = ItlbTransPtwReq(2*self.pktLen)
|
||||
self.trPtwResp = ItlbTransPtwResp(2*self.pktLen)
|
||||
|
||||
def gen_vec(self, caseTag):
|
||||
if(caseTag == 0):
|
||||
pass
|
||||
elif caseTag == "caseAcptRqst":
|
||||
for i in range(1, self.pktLen + 1):
|
||||
self.trRqstReq0.requestorReqBitsVaddr[i] = random.randint(0, 2**50 - 1)
|
||||
self.trRqstReq1.requestorReqBitsVaddr[i] = random.randint(0, 2**50 - 1)
|
||||
self.trRqstReq2.requestorReqBitsVaddr[i] = random.randint(0, 2**50 - 1)
|
||||
for i in range(self.pktLen):
|
||||
self.trCsr.csrSatpMode[i] = 9
|
||||
self.trCsr.csrSatpAsid[i] = 1
|
||||
else:
|
||||
print("Case Tag does not exist!")
|
||||
|
||||
return self.trSfence, self.trCsr, self.trRqstReq0, self.trRqstReq1, self.trRqstReq2, self.trRqstResp0, self.trRqstResp1, self.trRqstResp2, self.trFlsPip, self.trPtwReq0, self.trPtwReq1, self.trPtwReq2, self.trPtwResp
|
||||
|
||||
def __set_resp(self):
|
||||
for i in range(self.pktLen):
|
||||
self.trPtwResp.s1entryasid[i] = self.trcsr.csrSatpAsid[i]
|
||||
self.trPtwResp.s1entryvmid[i] = 0
|
||||
self.trPtwResp.s1entrypermd[i] = 0
|
||||
self.trPtwResp.s1entryperma[i] = random.choice(True, False)
|
||||
self.trPtwResp.s1entrypermg[i] = random.choice(True, False)
|
||||
self.trPtwResp.s1entrypermu[i] = random.choice(True, False)
|
||||
self.trPtwResp.s1entrypermx[i] = random.choice(True, False)
|
||||
self.trPtwResp.s1entrypermw[i] = random.choice(True, False)
|
||||
self.trPtwResp.s1entrypermr[i] = random.choice(True, False)
|
||||
self.trPtwResp.s1entrylevel[i] = 0
|
||||
self.trPtwResp.s1entryppn[i] = random.randint(2*33 - 1)
|
||||
self.trPtwResp.s1addrlow[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow0[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow1[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow2[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow3[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow4[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow5[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow6[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1ppnlow7[i] = random.randint(2*3 - 1)
|
||||
self.trPtwResp.s1valididx0[i] = 0
|
||||
self.trPtwResp.s1valididx1[i] = 0
|
||||
self.trPtwResp.s1valididx2[i] = 0
|
||||
self.trPtwResp.s1valididx3[i] = 0
|
||||
self.trPtwResp.s1valididx4[i] = 0
|
||||
self.trPtwResp.s1valididx5[i] = 0
|
||||
self.trPtwResp.s1valididx6[i] = 0
|
||||
self.trPtwResp.s1valididx7[i] = 0
|
||||
self.trPtwResp.s1pteidx0[i] = 0
|
||||
self.trPtwResp.s1pteidx1[i] = 0
|
||||
self.trPtwResp.s1pteidx2[i] = 0
|
||||
self.trPtwResp.s1pteidx3[i] = 0
|
||||
self.trPtwResp.s1pteidx4[i] = 0
|
||||
self.trPtwResp.s1pteidx5[i] = 0
|
||||
self.trPtwResp.s1pteidx6[i] = 0
|
||||
self.trPtwResp.s1pteidx7[i] = 0
|
||||
self.trPtwResp.s1pf[i] = 0
|
||||
self.trPtwResp.s1af[i] = 0
|
||||
self.trPtwResp.s2entrytag[i] = 0
|
||||
self.trPtwResp.s2entryvmid[i] = 0
|
||||
self.trPtwResp.s2entryn[i] = 0
|
||||
self.trPtwResp.s2entrypbmt[i] = 0
|
||||
self.trPtwResp.s2entryppn[i] = 0
|
||||
self.trPtwResp.s2entrypermd[i] = 0
|
||||
self.trPtwResp.s2entryperma[i] = 0
|
||||
self.trPtwResp.s2entrypermg[i] = 0
|
||||
self.trPtwResp.s2entrypermu[i] = 0
|
||||
self.trPtwResp.s2entrypermx[i] = 0
|
||||
self.trPtwResp.s2entrypermw[i] = 0
|
||||
self.trPtwResp.s2entrypermr[i] = 0
|
||||
self.trPtwResp.s2entrylevel[i] = 0
|
||||
self.trPtwResp.s2gpf[i] = 0
|
||||
self.trPtwResp.s2gaf[i] = 0
|
||||
self.trPtwResp.getgpa[i] = 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def __del__(self):
|
||||
pass
|
||||
#for i in range(self.pktLen):
|
||||
# del self.trSfence[i]
|
||||
# del self.trCsr[i]
|
||||
# del self.trRqstReq0[i]
|
||||
# del self.trRqstReq1[i]
|
||||
# del self.trRqstReq2[i]
|
||||
# del self.trRqstResp0[i]
|
||||
# del self.trRqstResp1[i]
|
||||
# del self.trRqstResp2[i]
|
||||
# del self.trFlsPip[i]
|
||||
# del self.trPtwReq0[i]
|
||||
# del self.trPtwReq1[i]
|
||||
# del self.trPtwReq2[i]
|
||||
# del self.trPtwResp[i]
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import toffee_test
|
||||
import toffee
|
||||
from operator import *
|
||||
from ..env import ItlbEnv
|
||||
from dut.TLB import DUTTLB
|
||||
import toffee.funcov as fc
|
||||
from comm.functions import UT_FCOV, module_name_with
|
||||
|
||||
# module path is ut_frontend.ifu.itlb.toffee_version.test.itlb_dut.py
|
||||
#gr = fc.CovGroup(UT_FCOV("../../../../itlb"))
|
||||
|
||||
|
||||
|
||||
@toffee_test.fixture
|
||||
async def itlb_env(toffee_request: toffee_test.ToffeeRequest):
|
||||
toffee.setup_logging(toffee.WARNING)
|
||||
dut = toffee_request.create_dut(DUTTLB)
|
||||
dut.InitClock("clock")
|
||||
toffee.start_clock(dut)
|
||||
env = ItlbEnv(dut)
|
||||
yield env
|
||||
|
||||
import asyncio
|
||||
cur_loop = asyncio.get_event_loop()
|
||||
for task in asyncio.all_tasks(cur_loop):
|
||||
if task.get_name() == "__clock_loop":
|
||||
task.cancel()
|
||||
try:
|
||||
await task
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import toffee_test
|
||||
from dut.TLB import DUTTLB
|
||||
from .itlb_dut import itlb_env
|
||||
from ..agent.itlb_trans import *
|
||||
from ..env.itlb_sqr import *
|
||||
from toffee import *
|
||||
import os
|
||||
TEST_CYCLE = int(os.getenv("TEST_CYCLE", 100))
|
||||
|
||||
#@toffee_test.testcase
|
||||
#async def test_reset(itlb_env):
|
||||
# print("Test reset")
|
||||
# sqr = ItlbSqr()
|
||||
# res = await itlb_env.itlbAgent.agent_itlb(*sqr.gen_vec(0))
|
||||
# del sqr
|
||||
|
||||
|
||||
@toffee_test.testcase
|
||||
async def test_tlb_acpt_rqst(itlb_env):
|
||||
print("Test TLB accepted request")
|
||||
res = []
|
||||
sqr = ItlbSqr(TEST_CYCLE)
|
||||
res= await itlb_env.itlbAgent.agent_itlb(TEST_CYCLE, *(sqr.gen_vec("caseAcptRqst")))
|
||||
del sqr
|
||||
Loading…
Reference in New Issue