Compare commits

...

9 Commits

Author SHA1 Message Date
cjh ebb698c251 tmp save lzl changes 2025-05-21 16:05:05 +08:00
Shio2077 5ace2441e6 agent fixed 2025-04-24 21:20:07 +08:00
Shio2077 ec09eb24dc
Merge branch 'XS-MLVP:main' into main 2025-04-01 20:08:57 +08:00
Shio2077 3825f86420 1 2025-04-01 20:08:11 +08:00
Shio2077 8b2d55fc00
Merge branch 'XS-MLVP:main' into main 2025-03-25 20:00:36 +08:00
Shio2077 4928ddd8f6 cover bins improve 2025-03-11 18:23:02 +08:00
Shio2077 c7cbe0d38d
Merge branch 'XS-MLVP:main' into main 2025-03-11 11:28:55 +08:00
Shio2077 f44db511d1 jalr test complete 2025-03-11 10:51:05 +08:00
Shio2077 3cad0d6bd0 20250309:manually_merge 2025-03-09 20:27:04 +08:00
33 changed files with 4309 additions and 124 deletions

View File

@ -1,7 +1,7 @@
# FrontendTrigger 单元验证
## 测试目标
| 序号 | 功能 | 名称 | 描述 |
|------|------|------|------|
测试目标是验证FrontendTrigger子模块的功能。
FrontendTrigger的功能分为两部分断点设置和断点触发。
@ -71,4 +71,6 @@ TBD
参考模型
文档:测试流程
文档:测试流程

View File

@ -1,2 +1,2 @@
from .frontend_trigger_agent import FrontendTriggerAgent,BreakpointInfo, BreakpointReq
from .frontend_trigger_agent import FrontendTriggerAgent,BreakpointInfo

View File

@ -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

View File

@ -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的步长划分 |

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
from .auto_bundle import TlbBundle

View File

@ -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")

View File

@ -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))

View File

View File

@ -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]

View File

@ -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

View File

@ -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