Compare commits

...

16 Commits

Author SHA1 Message Date
mingyu shi 4204b942e7 final 2025-04-29 20:48:06 +08:00
mingyu shi 56962b77dd Merge remote-tracking branch 'upstream/main' 2025-03-23 19:32:34 +08:00
mingyu shi a5c34f6cfb update 2025-03-20 21:19:18 +08:00
mingyu shi f35f96a3ba Merge remote-tracking branch 'upstream/main' 2025-03-07 21:44:47 +08:00
mingyu shi 708c440ce3 delete some files 2025-02-28 15:40:27 +08:00
mingyu shi 502d823fc7 fix 2025-02-28 15:32:36 +08:00
mingyu shi 15fea20a5f fix 2025-02-28 15:31:25 +08:00
mingyu shi f68fd0ad55 Merge remote-tracking branch 'upstream/main' 2025-02-27 20:07:43 +08:00
mingyu shi 6b4e2f0680 优化细节 2025-02-27 20:06:30 +08:00
mingyu shi a7f82fe823 Merge remote-tracking branch 'upstream/main' 2025-02-26 23:20:09 +08:00
mingyu shi 380febef36 update 2025-02-24 00:36:31 +08:00
mingyu shi 2a701680c8 predecode 2025-02-22 22:27:39 +08:00
mingyu shi 23fcd1f1ba Merge remote-tracking branch 'upstream/main' 2025-02-22 20:08:19 +08:00
mingyu shi 554bbfcf43 predecode 2025-02-22 20:06:35 +08:00
mingyu shi 663d857694 f3predecoder 2025-02-20 22:48:28 +08:00
mingyu shi 5a01b8b026 test 2025-02-20 11:41:54 +08:00
12 changed files with 929 additions and 37 deletions

3
.gitignore vendored
View File

@ -171,3 +171,6 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.vscode/
.metals/

View File

@ -9,6 +9,10 @@ class F3PreDecodeData():
def __str__(self):
return f"brTypes: {self.brTypes}\nisCalls: {self.isCalls}\nisRets: {self.isRets}"
def clear(self):
self.brTypes = []
self.isCalls = []
self.isRets = []
class F3PreDecoderAgent(Agent):
def __init__(self, bundle:F3PreDecoderBundle):
@ -23,6 +27,7 @@ class F3PreDecoderAgent(Agent):
await self.bundle.step()
ret = F3PreDecodeData()
ret.clear()
for i in range(16):
ret.brTypes.append(getattr(self.bundle.io._out_pd, f"_{i}")._brType.value)
ret.isCalls.append(getattr(self.bundle.io._out_pd, f"_{i}")._isCall.value)

View File

@ -2,11 +2,56 @@ import toffee_test
from dut.F3Predecoder import DUTF3Predecoder
from toffee import start_clock
from ..env import F3PreDecoderEnv
import toffee.funcov as fc
from comm import UT_FCOV, module_name_with, get_version_checker
grp = fc.CovGroup(UT_FCOV("../../CLASSIC"))
def init_cov(dut:DUTF3Predecoder, grp: fc.CovGroup):
for i in range(16):
grp.add_cover_point(dut,{
"instr is not cfi": lambda x: getattr(dut, f'io_out_pd_{i}_brType').value == 0,
"instr is branch": lambda x: getattr(dut, f'io_out_pd_{i}_brType').value == 1,
"instr is jal": lambda x: getattr(dut, f'io_out_pd_{i}_brType').value == 2,
"instr is jalr": lambda x: getattr(dut, f'io_out_pd_{i}_brType').value == 3,
},name = f'check_cfi_{i}')
for i in range(16):
grp.add_cover_point(dut,{
"instr is RVI.JAL and is call": lambda x: getattr(dut, f'io_out_pd_{i}_isCall').value == 1 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b1101111,
"instr is RVI.JAL and is not call or ret": lambda x: getattr(dut, f'io_out_pd_{i}_isCall').value == 0 and getattr(dut, f'io_out_pd_{i}_isRet').value == 0 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b1101111,
"instr is RVC.JAL and is not call or ret": lambda x: getattr(dut, f'io_out_pd_{i}_isCall').value == 0 and getattr(dut, f'io_out_pd_{i}_isRet').value == 0 and getattr(dut, f'io_in_instr_{i}').value & 0b11 == 0b01 and (getattr(dut, f'io_in_instr_{i}').value >> 13) == 0b101,
},name = f'check_jal_{i}')
for i in range(16):
grp.add_cover_point(dut,{
"instr is RVI.JALR and is call":lambda x: getattr(dut, f'io_out_pd_{i}_isCall').value == 1 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b1100111,
"instr is RVI.JALR and is ret":lambda x: getattr(dut, f'io_out_pd_{i}_isRet').value == 1 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b1100111,
"instr is RVI.JALR and is not call or ret":lambda x: getattr(dut, f'io_out_pd_{i}_isRet').value == 0 and getattr(dut, f'io_out_pd_{i}_isCall').value == 0 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b1100111,
"instr is RVC.JALR and is not call or ret":lambda x: getattr(dut, f'io_out_pd_{i}_isRet').value == 0 and getattr(dut, f'io_out_pd_{i}_isCall').value == 0 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b0000010 and (getattr(dut, f'io_in_instr_{i}').value >> 12) == 0b1001
},name=f'check_jalr_{i}')
for i in range(16):
grp.add_cover_point(dut,{
"instr is RVC.JR and is ret":lambda x: getattr(dut, f'io_out_pd_{i}_isRet').value == 1 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b0000010 and (getattr(dut, f'io_in_instr_{i}').value >> 12) == 0b1000,
"instr is RVC.JR and is not call or ret":lambda x:getattr(dut, f'io_out_pd_{i}_isRet').value == 0 and getattr(dut, f'io_out_pd_{i}_isCall').value == 0 and getattr(dut, f'io_in_instr_{i}').value & 0b1111111 == 0b0000010 and (getattr(dut, f'io_in_instr_{i}').value >> 12) == 0b1000,
},name=f'check_jr_{i}')
def _mark(name):
return module_name_with(name, "../f3predecoder_test")
for i in range(16):
grp.mark_function(f'check_cfi_{i}',_mark(["test_cfi_checker_1_1","test_cfi_checker_1_2","test_cfi_checker_1_3"]))
grp.mark_function(f'check_jal_{i}',_mark(["test_cfi_checker_2_2_1_1","test_cfi_checker_2_2_1_2","test_cfi_checker_2_2_2"]))
grp.mark_function(f'check_jalr_{i}',_mark(["test_cfi_checker_2_3_2_1","test_cfi_checker_2_3_1_2","test_cfi_checker_2_3_1_3","test_cfi_checker_2_3_2_1"]))
grp.mark_function(f'check_jr_{i}',_mark(["test_cfi_checker_2_3_2_2_1","test_cfi_checker_2_3_2_2_2"]))
return grp
@toffee_test.fixture
async def f3predecoder_env(toffee_request: toffee_test.ToffeeRequest):
import asyncio
dut = toffee_request.create_dut(DUTF3Predecoder)
toffee_request.add_cov_groups(init_cov(dut, grp))
start_clock(dut)
predecode_env = F3PreDecoderEnv(dut)
yield predecode_env

View File

@ -0,0 +1,231 @@
import random
class F3PredecodeInstrGen():
def __init__(self):
self.brTypes = []
self.isCalls = []
self.isRets = []
self.instrs = []
def clear(self):
self.brTypes = []
self.isCalls = []
self.isRets = []
self.instrs = []
def inst_gen(self, isa = 'random', type = 'not_cfi'):
if type == 'br':
#generate br type instructions
for _ in range(16):
#rvi
opcode = 0b1100011
funct3 = random.choice([0b000,0b001,0b100,0b101,0b110,0b111])
rs1 = random.getrandbits(5)
rs2 = random.getrandbits(5)
instr_rvi = (random.getrandbits(7) << 25) | rs1 << 20 |\
rs2 << 15 | funct3 << 12 | (random.getrandbits(5) << 7) |\
opcode
#rvc
op = 0b01
func3 = random.choice([0b110,0b111])
instr_rvc = func3 << 13 | (random.getrandbits(11) << 2) | op
self.brTypes.append(1)
if isa == 'random':
self.instrs.append(random.choice([instr_rvi, instr_rvc]))
elif isa == 'rvi':
self.instrs.append(instr_rvi)
elif isa == 'rvc':
self.instrs.append(instr_rvc)
elif type == 'jal':
#generate jal type instructions
for _ in range(16):
#rvi
opcode = 0b1101111
instr_rvi = (random.getrandbits(25) << 7) | opcode
#rvc
func3 = 0b101
op = 0b01
instr_rvc = (func3 << 13) | (random.getrandbits(11) << 2) | op
self.brTypes.append(2)
if isa == 'random':
self.instrs.append(random.choice([instr_rvi, instr_rvc]))
elif isa == 'rvi':
self.instrs.append(instr_rvi)
elif isa == 'rvc':
self.instrs.append(instr_rvc)
elif type == 'jalr':
#generate jalr type instructions
for _ in range(16):
#rvi
funct3 = 0b000
opcode = 0b1100111
instr_rvi = (random.getrandbits(17) << 25) | funct3 << 12 |\
(random.getrandbits(5) << 7) | opcode
#rvc
rs1 = random.getrandbits(5) | 0b1
head = random.choice([0b1001,0b1000])
tail = 0b00000_10
instr_rvc = (head << 12) | (rs1 << 7) | tail
self.brTypes.append(3)
if isa == 'random':
self.instrs.append(random.choice([instr_rvi, instr_rvc]))
elif isa == 'rvi':
self.instrs.append(instr_rvi)
elif isa == 'rvc':
self.instrs.append(instr_rvc)
elif type == 'not_cfi':
#generate not cfi type instructions
for _ in range(16):
#rvi
opcode = random.getrandbits(7) | 0b11
funct3 = random.getrandbits(3)
while True:
flag1 = (opcode == 0b1100011) and (funct3 in [0b000,0b001,0b010,0b011,0b100,0b101,0b110,0b111])
flag2 = (opcode == 0b1101111)
flag3 = (opcode == 0b1100111) and (funct3 == 0b000)
if not flag3 and not flag2 and not flag1:
break
opcode = random.getrandbits(7) | 0b11
funct3 = random.getrandbits(3)
instr_rvi = random.getrandbits(17) << 15 | funct3 << 12 | random.getrandbits(5) << 7 | opcode
#rvc
c_ebreak = 0b100_1_00000_00000_10
instr_rvc = random.getrandbits(16)
while True:
op = instr_rvc & 0b11
func3 = instr_rvc >> 13
flag1 = (op == 0b01) and (func3 in [0b110, 0b111, 0b101])
j1 = instr_rvc & 0b1111111
j2 = instr_rvc >> 12
flag2 = (j1 == 0b0000010) and (j2 in [0b1001, 0b1000])
flag3 = op == 0b11
if not flag1 and not flag2 and not flag3:
break
instr_rvc = random.getrandbits(16)
self.brTypes.append(0)
self.instrs.append(random.choice([instr_rvc,instr_rvi,c_ebreak]))
return self.instrs, self.brTypes
def ret_call_checker(self,task = '2.1.1'):
if task =='2.1.1':
self.inst_gen(type = 'not_cfi')
self.isCalls = [0 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.1.2':
self.inst_gen(type = 'br')
self.isCalls = [0 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.2.1.1':
def rd():
return random.choice([1, 5]) << 7
mask = 0b1111_1111_1111_1111_1111_0000_0111_1111
self.inst_gen(type = 'jal', isa = 'rvi')
self.instrs = [i & mask | rd() for i in self.instrs]
self.isCalls = [1 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.2.1.2':
def rd():
valid_numbers = [x for x in range(33) if x not in {1, 5}]
num = random.choice(valid_numbers)
return num << 7
mask = 0b1111_1111_1111_1111_1111_0000_0111_1111
self.inst_gen(type = 'jal', isa = 'rvi')
self.instrs = [i & mask | rd() for i in self.instrs]
self.isCalls = [0 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.2.2':
self.isCalls = [0 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
self.inst_gen(type = 'jal', isa = 'rvc')
return self.instrs, self.isCalls, self.isRets
if task == '2.3.1.1':
def rd():
return random.choice([1, 5]) << 7
mask = 0b1111_1111_1111_1111_1111_0000_0111_1111
self.inst_gen(type = 'jalr', isa = 'rvi')
self.instrs = [i & mask | rd() for i in self.instrs]
self.isCalls = [1 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.3.1.2':
def rs():
return random.choice([1,5]) << 15
def rd():
valid_numbers = [x for x in range(32) if x not in {1, 5}]
num = random.choice(valid_numbers)
return num << 7
mask = 0b1111_1111_1111_0000_0111_0000_0111_1111
self.inst_gen('jalr', 'rvi')
self.inst_gen(type = 'jalr', isa = 'rvi')
self.instrs = [i & mask | rd() | rs() for i in self.instrs]
self.isCalls = [0 for _ in range(16)]
self.isRets = [1 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.3.1.3':
def rd():
valid_numbers = [x for x in range(32) if x not in {1, 5}]
num = random.choice(valid_numbers)
return num << 7
def rs():
valid_numbers = [x for x in range(32) if x not in {1, 5}]
num = random.choice(valid_numbers)
return num << 15
mask = 0b1111_1111_1111_0000_0111_0000_0111_1111
self.inst_gen('jalr', 'rvi')
self.inst_gen(type = 'jalr', isa = 'rvi')
self.instrs = [i & mask | rd() | rs() for i in self.instrs]
self.isCalls = [0 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.3.2.1':
self.inst_gen(type = 'jalr', isa = 'rvc')
self.instrs = [i | 1 << 12 for i in self.instrs]
self.isCalls = [1 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.3.2.2.1':
def rs():
return random.choice([1,5]) << 7
mask = 0b1110000001111111
self.inst_gen(type = 'jalr', isa = 'rvc')
self.instrs = [i & mask | rs() for i in self.instrs]
self.isCalls = [0 for _ in range(16)]
self.isRets = [1 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets
if task == '2.3.2.2.2':
def rs():
valid_numbers = [x for x in range(32) if x not in {1, 5}]
num = random.choice(valid_numbers)
return num << 7
mask = 0b1110000001111111
self.inst_gen(type = 'jalr', isa = 'rvc')
self.instrs = [i & mask | rs() for i in self.instrs]
self.isCalls = [0 for _ in range(16)]
self.isRets = [0 for _ in range(16)]
return self.instrs, self.isCalls, self.isRets

View File

@ -1,10 +1,184 @@
from .f3predecoder_fixture import f3predecoder_env
from ..env import F3PreDecoderEnv
import toffee_test
from .f3predecoder_instr_gen import F3PredecodeInstrGen
instrGen = F3PredecodeInstrGen()
@toffee_test.testcase
async def test_smoke(f3predecoder_env : F3PreDecoderEnv):
instrs = [483 for i in range(16)]
async def test_cfi_checker_1_1(f3predecoder_env : F3PreDecoderEnv):
print("test_cfi_checker_1_1")
for _ in range(2000):
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='not_cfi', isa='rvc')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='not_cfi', isa='rvi')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
print(await f3predecoder_env.agent.f3_predecode(instrs))
@toffee_test.testcase
async def test_cfi_checker_1_2(f3predecoder_env : F3PreDecoderEnv):
print("test_cfi_checker_1_2")
for _ in range(2000):
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='br', isa='rvi')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='br', isa='rvc')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
@toffee_test.testcase
async def test_cfi_checker_1_3(f3predecoder_env : F3PreDecoderEnv):
print("test_cfi_checker_1_3")
for _ in range(2000):
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='jal', isa='rvi')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='jal', isa='rvc')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
@toffee_test.testcase
async def test_cfi_checker_1_4(f3predecoder_env : F3PreDecoderEnv):
print("test_cfi_checker_1_4")
for _ in range(2000):
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='jalr', isa='rvi')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
instrGen.clear()
instrs, brTypes = instrGen.inst_gen(type='jalr', isa='rvc')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.brTypes == brTypes
@toffee_test.testcase
async def test_ret_call_checker_2_1_1(f3predecoder_env : F3PreDecoderEnv):
#check not cfi
print("test_ret_call_checker_2_1_1")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.1.1')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_1_2(f3predecoder_env : F3PreDecoderEnv):
#check br
print("test_ret_call_checker_2_1_2")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.1.2')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_2_1_1(f3predecoder_env : F3PreDecoderEnv):
#check RVI.JAL call
print("test_ret_call_checker_2_2_1_1")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.2.1.1')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_2_1_2(f3predecoder_env : F3PreDecoderEnv):
#check RVI.JAL not call and ret
print("test_ret_call_checker_2_2_1_2")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.2.1.2')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_2_2(f3predecoder_env : F3PreDecoderEnv):
#check RVC.JAL not call and ret
print("test_ret_call_checker_2_2_2")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.2.2')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_3_1_1(f3predecoder_env : F3PreDecoderEnv):
#check RVI.JALR call
print("test_ret_call_checker_2_3_1_1")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.3.1.1')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_3_1_2(f3predecoder_env : F3PreDecoderEnv):
#check RVI.JALR ret
print("test_ret_call_checker_2_3_1_2")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.3.1.2')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_3_1_3(f3predecoder_env : F3PreDecoderEnv):
#check RVI.JALR not call and ret
print("test_ret_call_checker_2_3_1_3")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.3.1.3')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_3_2_1(f3predecoder_env: F3PreDecoderEnv):
#check RVC.JALR call
print("test_ret_call_checker_2_3_2_1")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.3.2.1')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_3_2_2_1(f3predecoder_env: F3PreDecoderEnv):
#check RVC.JR ret
print("test_ret_call_checker_2_3_2_2_1")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.3.2.2.1')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets
@toffee_test.testcase
async def test_ret_call_checker_2_3_2_2_2(f3predecoder_env: F3PreDecoderEnv):
#check RVC.JR not ret
print("test_ret_call_checker_2_3_2_2_2")
for _ in range(2000):
instrGen.clear()
instrs, isCalls, isRets = instrGen.ret_call_checker(task = '2.3.2.2.2')
res = await f3predecoder_env.agent.f3_predecode(instrs)
assert res.isCalls == isCalls
assert res.isRets == isRets

View File

@ -18,32 +18,30 @@ TBD
## 功能点和测试点
| 序号 | 功能 | 名称 | 描述 |
|--------|--------------------|--------------------|-----------------------------------------------------------------------------------------------|
| 1\.1\.1 | BPU预测信息的JAL预测错误检查 | 误检测试1 | 预测块中没有JAL指令且最终预测信息也没有取用任何跳转指令的输入检查PredChecker是否会误报JAL预测错误。 |
| 1\.1\.2 | BPU预测信息的JAL预测错误检查 | 误检测试2 | 预测块中有JAL指令且最终预测信息取用的正是本条跳转指令的输入检查PredChecker是否会误报JAL预测错误。 |
| 1\.2\.1 | BPU预测信息的JAL预测错误检查 | 存在JAL未预测 | 预测块中存在JAL指令但是最终预测信息未预测跳转检查PredChecker是否能检测出JAL预测错误。 |
| 1\.2\.2 | BPU预测信息的JAL预测错误检查 | 预测的JAL并非第一条 | 预测块中存在JAL指令但是最终预测信息取的跳转指令在第一条JAL指令之后检查PredChecker是否能检测出JAL预测错误。 |
| 2\.1\.1 | BPU预测信息的RET预测错误检查 | 误检测试1 | 预测块中没有RET指令且最终预测信息也没有取用任何跳转指令的输入检查PredChecker是否会误报RET预测错误。 |
| 2\.1\.2 | BPU预测信息的RET预测错误检查 | 误检测试2 | 预测块中有RET指令且最终预测信息取用的正是本条跳转指令的输入检查PredChecker是否会误报RET预测错误。 |
| 2\.2\.1 | BPU预测信息的RET预测错误检查 | 存在RET未预测 | 预测块中存在RET指令但是最终预测信息未预测跳转检查PredChecker是否能检测出RET预测错误。 |
| 2\.2\.2 | BPU预测信息的RET预测错误检查 | 预测的跳转并非第一条 | 预测块中存在RET指令但是最终预测信息取的跳转指令在第一条RET指令之后检查PredChecker是否能检测出RET预测错误。 |
| 3\.1 | 更新指令有效范围向量和预测跳转的指令 | 有效范围无误 | 不存在任何错误的情况下PredChecker应当保留之前的预测结果。 |
| 3\.2 | 更新指令有效范围向量和预测跳转的指令 | RET和JAL预测错误引起的范围偏大 | 如果检测到了JAL或RET类的预测错误PredChecker应该将有效指令的范围修正为预测块开始至第一条跳转指令。同时应该将预测跳转的指令位置修正为预测块中的第一条跳转指令。 |
| 3\.3 | 更新指令有效范围向量和预测跳转的指令 | 非CFI和无效指令引起的预测范围偏小 | 如果出现了非控制流指令和无效指令的误预测,应该将预测跳转的指令重新修正到预测块中第一条跳转指令 |
| 4\.1\.1 | 非CFI预测错误检查 | 误检测试1 | 构造不存在CFI指令并且未预测跳转的预测信息作为输入测试PredChecker是否会错检非CFI预测错误 |
| 4\.1\.2 | 非CFI预测错误检查 | 误检测试2 | 构造存在CFI指令并且正确预测跳转的预测信息作为输入测试PredChecker是否会错检非CFI预测错误 |
| 4\.2 | 非CFI预测错误检查 | 正确检测测试 | 构造不存在CFI指令但是预测了跳转的预测信息作为输入测试PredChecker是否能检查出非CFI预测错误 |
| 5\.1\.1 | 无效指令预测错误检查 | 误检测试1 | 构造不存在跳转指令并且未预测跳转的预测信息作为输入测试PredChecker是否会错检无效指令预测错误 |
| 5\.1\.2 | 无效指令预测错误检查 | 误检测试2 | 构造存在无效跳转指令并且未预测跳转的预测信息作为输入测试PredChecker是否会错检无效指令预测错误 |
| 5\.1\.3 | 无效指令预测错误检查 | 误检测试3 | 构造存在有效跳转指令并且正确预测跳转的预测信息作为输入测试PredChecker是否会错检无效指令预测错误 |
| 5\.2 | 无效指令预测错误检查 | 正确检测测试 | 构造无效指令但是预测了跳转的预测信息作为输入测试PredChecker是否能检查出无效指令预测错误 |
| 6\.1\.1 | 目标地址预测错误检查 | 误检测试1 | 构造不存在跳转指令并且未预测跳转的预测信息作输入测试PredChecker是否会错检目标地址预测错误 |
| 6\.1\.2 | 目标地址预测错误检查 | 误检测试2 | 构造存在有效跳转指令并且正确预测跳转的预测信息作为输入测试PredChecker是否会错检目标地址预测错误 |
| 6\.2 | 目标地址预测错误检查 | 正确检测测试 | 构造存在有效跳转指令的预测块和预测跳转但跳转目标计算错误的预测信息作为输入测试PredChecker能否检出目标地址预测错误 |
| 7\.1 | 生成跳转和顺序目标 | 随机测试 | 随机提供译码信息,检测生成的跳转目标和顺序目标。 |
| 序号 | 功能 | 名称 | 描述 |
| ------- | ------------------------------------ | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1\.1\.1 | BPU预测信息的JAL预测错误检查 | 误检测试1 | 预测块中没有JAL指令且最终预测信息也没有取用任何跳转指令的输入检查PredChecker是否会误报JAL预测错误。 |
| 1\.1\.2 | BPU预测信息的JAL预测错误检查 | 误检测试2 | 预测块中有JAL指令且最终预测信息取用的正是本条跳转指令的输入检查PredChecker是否会误报JAL预测错误。 |
| 1\.2\.1 | BPU预测信息的JAL预测错误检查 | 存在JAL未预测 | 预测块中存在JAL指令但是最终预测信息未预测跳转检查PredChecker是否能检测出JAL预测错误。 |
| 1\.2\.2 | BPU预测信息的JAL预测错误检查 | 预测的JAL并非第一条 | 预测块中存在JAL指令但是最终预测信息取的跳转指令在第一条JAL指令之后检查PredChecker是否能检测出JAL预测错误。 |
| 2\.1\.1 | BPU预测信息的RET预测错误检查 | 误检测试1 | 预测块中没有RET指令且最终预测信息也没有取用任何跳转指令的输入检查PredChecker是否会误报RET预测错误。 |
| 2\.1\.2 | BPU预测信息的RET预测错误检查 | 误检测试2 | 预测块中有RET指令且最终预测信息取用的正是本条跳转指令的输入检查PredChecker是否会误报RET预测错误。 |
| 2\.2\.1 | BPU预测信息的RET预测错误检查 | 存在RET未预测 | 预测块中存在RET指令但是最终预测信息未预测跳转检查PredChecker是否能检测出RET预测错误。 |
| 2\.2\.2 | BPU预测信息的RET预测错误检查 | 预测的跳转并非第一条 | 预测块中存在RET指令但是最终预测信息取的跳转指令在第一条RET指令之后检查PredChecker是否能检测出RET预测错误。 |
| 3\.1 | 更新指令有效范围向量和预测跳转的指令 | 有效范围无误 | 不存在任何错误的情况下PredChecker应当保留之前的预测结果。 |
| 3\.2 | 更新指令有效范围向量和预测跳转的指令 | RET和JAL预测错误引起的范围偏大 | 如果检测到了JAL或RET类的预测错误PredChecker应该将有效指令的范围修正为预测块开始至第一条跳转指令。同时应该将预测跳转的指令位置修正为预测块中的第一条跳转指令。 |
| 3\.3 | 更新指令有效范围向量和预测跳转的指令 | 非CFI和无效指令引起的预测范围偏小 | 如果出现了非控制流指令和无效指令的误预测,应该将预测跳转的指令重新修正到预测块中第一条跳转指令 |
| 4\.1\.1 | 非CFI预测错误检查 | 误检测试1 | 构造不存在CFI指令并且未预测跳转的预测信息作为输入测试PredChecker是否会错检非CFI预测错误 |
| 4\.1\.2 | 非CFI预测错误检查 | 误检测试2 | 构造存在CFI指令并且正确预测跳转的预测信息作为输入测试PredChecker是否会错检非CFI预测错误 |
| 4\.2 | 非CFI预测错误检查 | 正确检测测试 | 构造不存在CFI指令但是预测了跳转的预测信息作为输入测试PredChecker是否能检查出非CFI预测错误 |
| 5\.1\.1 | 无效指令预测错误检查 | 误检测试1 | 构造不存在跳转指令并且未预测跳转的预测信息作为输入测试PredChecker是否会错检无效指令预测错误 |
| 5\.1\.2 | 无效指令预测错误检查 | 误检测试2 | 构造存在无效跳转指令并且未预测跳转的预测信息作为输入测试PredChecker是否会错检无效指令预测错误 |
| 5\.1\.3 | 无效指令预测错误检查 | 误检测试3 | 构造存在有效跳转指令并且正确预测跳转的预测信息作为输入测试PredChecker是否会错检无效指令预测错误 |
| 5\.2 | 无效指令预测错误检查 | 正确检测测试 | 构造无效指令但是预测了跳转的预测信息作为输入测试PredChecker是否能检查出无效指令预测错误 |
| 6\.1\.1 | 目标地址预测错误检查 | 误检测试1 | 构造不存在跳转指令并且未预测跳转的预测信息作输入测试PredChecker是否会错检目标地址预测错误 |
| 6\.1\.2 | 目标地址预测错误检查 | 误检测试2 | 构造存在有效跳转指令并且正确预测跳转的预测信息作为输入测试PredChecker是否会错检目标地址预测错误 |
| 6\.2 | 目标地址预测错误检查 | 正确检测测试 | 构造存在有效跳转指令的预测块和预测跳转但跳转目标计算错误的预测信息作为输入测试PredChecker能否检出目标地址预测错误 |
| 7\.1 | 生成跳转和顺序目标 | 随机测试 | 随机提供译码信息,检测生成的跳转目标和顺序目标。 |
## Env提供的验证接口(API)
@ -75,4 +73,4 @@ TBD
参考模型
文档:测试流程
文档:测试流程

View File

@ -16,6 +16,16 @@ class PreDecodeDataDef():
res = f"new instrs: {self.new_instrs}\njump offsets: {self.jmp_offsets}\nrvcs: {self.rvcs}\nvalid_starts: {self.valid_starts}\nhalf_valid_starts: {self.half_valid_starts}\n"
res += f"isRets:{self.isRets}\nisCalls:{self.isCalls}\nbyTypes:{self.brTypes}"
return res
def clear(self):
self.new_instrs = []
self.jmp_offsets = []
self.rvcs = []
self.valid_starts = []
self.half_valid_starts = []
self.isRets = []
self.isCalls = []
self.brTypes = []
class PreDecodeAgent(Agent):
@ -29,10 +39,11 @@ class PreDecodeAgent(Agent):
async def predecode(self, instrs: list[int]) -> PreDecodeDataDef:
for i in range(17):
getattr(self.bundle.io._in_bits_data, f"_{i}").value = instrs[i]
print("going to step")
#print("going to step")
await self.bundle.step()
print("step over")
#print("step over")
ret = PreDecodeDataDef()
ret.clear()
for i in range(16):
ret.new_instrs.append(getattr(self.bundle.io._out._instr, f"_{i}").value)

View File

@ -2,13 +2,50 @@ import toffee_test
from dut.PreDecode import DUTPreDecode
from ..env import PreDecodeEnv
from toffee import start_clock
import toffee.funcov as fc
from comm import UT_FCOV, module_name_with, get_version_checker
grp = fc.CovGroup(UT_FCOV("../../CLASSIC"))
def init_cov(dut:DUTPreDecode, grp: fc.CovGroup):
for i in range(16):
grp.add_cover_point(dut,{
"instr is rvc:": lambda x: getattr(dut,f'io_out_pd_{i}_isRVC').value == 1,
"instr is rvi:": lambda x: getattr(dut,f'io_out_pd_{i}_isRVC').value == 0,
},name=f'check_rvc_rvi_{i}')
for i in range(2,16):
grp.add_cover_point(dut,{
"instr is half_valid_start:": lambda x: getattr(dut,f'io_out_hasHalfValid_{i}').value == 1,
"instr is not half_valid_start:": lambda x: getattr(dut,f'io_out_hasHalfValid_{i}').value == 0,
},name=f'check_half_valid_start_{i}')
for i in range(1,16):
grp.add_cover_point(dut,{
"instr is valid_starts:": lambda x: getattr(dut,f'io_out_pd_{i}_valid').value == 1,
"instr is not valid_starts:": lambda x: getattr(dut,f'io_out_pd_{i}_valid').value == 0,
},name=f'check_valid_start_{i}')
def _mark(name):
return module_name_with(name, "../predecode_test")
for i in range(16):
grp.mark_function(f'check_rvc_rvi_{i}',_mark(["test_rvc_rvi_checker_2_1_2","test_rvc_rvi_checker_2_1_1"]))
for i in range(2,16):
grp.mark_function(f'check_half_valid_start_{i}',_mark(["test_precoding_checker_2_3_2"]))
for i in range(1,16):
grp.mark_function(f'check_valid_start_{i}',_mark(["test_precoding_checker_2_3_1"]))
return grp
@toffee_test.fixture
async def predecode_env(toffee_request: toffee_test.ToffeeRequest):
import asyncio
# version_check()
dut = toffee_request.create_dut(DUTPreDecode)
toffee_request.add_cov_groups(init_cov(dut, grp))
start_clock(dut)
predecode_env = PreDecodeEnv(dut)
yield predecode_env

View File

@ -0,0 +1,289 @@
import random
class PreDecodeInstrGen():
def __init__(self):
self.instrs = []
self.new_instrs = []
self.jmp_offsets = []
self.rvcs = []
self.valid_starts = []
self.half_valid_starts = []
self.isRets = []
self.isCalls = []
self.brTypes = []
def clear(self):
self.instrs = []
self.new_instrs = []
self.jmp_offsets = []
self.rvcs = []
self.valid_starts = []
self.half_valid_starts = []
self.isRets = []
self.isCalls = []
self.brTypes = []
def random_instrs(self):
#genetare random instructions
self.instrs = [random.getrandbits(16) for _ in range(17)]
self.new_instrs = [self.instrs[i+1] << 16 | self.instrs[i] for i in range(16)]
return self.instrs, self.new_instrs
def instr_gen(self, type='random', isa='rvi'):
if type == 'random':
instr_rvi = random.getrandbits(32) | 0b11
instr_rvc = random.getrandbits(14) << 2 | random.choice([0b00,0b01,0b10])
return instr_rvi if isa == 'rvi' else instr_rvc
if type == 'j':
opcode = 0b1101111
instr_rvi = (random.getrandbits(25) << 7) | opcode
instr_rvi = (0b1111100101100010010000111 << 7) | opcode
func3 = random.choice([0b101])
op = 0b01
instr_rvc = (func3) << 13 | (random.getrandbits(11) << 2) | op
return instr_rvi if isa == 'rvi' else instr_rvc
if type == 'br':
instr_rvi = 0 #instr_rvi is aborted
func3 = random.choice([0b110,0b111])
op = 0b01
instr_rvc = func3 << 13 | random.getrandbits(11) << 2 | op
return instr_rvi if isa == 'rvi' else instr_rvc
if type == 'jalr':
instr_rvc = (0b1101) << 12 | random.getrandbits(5) << 7 | 0b0000010
instr_rvi = random.getrandbits(1) << 15 | (0b000) << 12 | random.getrandbits(5) << 7 | 0b1100111
return instr_rvi
if type == 'jal':
instr_rvi = random.getrandbits(9) << 7 | 0b1101111
return instr_rvi
def inst_gen_new_signal(self, isa = 'random', type = 'not_cfi'):
if type == 'br':
#generate br type instructions
for _ in range(16):
#rvi
opcode = 0b1100011
funct3 = random.choice([0b000,0b001,0b100,0b101,0b110,0b111])
rs1 = random.getrandbits(5)
rs2 = random.getrandbits(5)
instr_rvi = (random.getrandbits(7) << 25) | rs1 << 20 |\
rs2 << 15 | funct3 << 12 | (random.getrandbits(5) << 7) |\
opcode
#rvc
op = 0b01
func3 = random.choice([0b110,0b111])
instr_rvc = func3 << 13 | (random.getrandbits(11) << 2) | op
self.brTypes.append(1)
if isa == 'random':
self.instrs.append(random.choice([instr_rvi, instr_rvc]))
elif isa == 'rvi':
self.instrs.append(instr_rvi)
elif isa == 'rvc':
self.instrs.append(instr_rvc)
elif type == 'jal':
#generate jal type instructions
for _ in range(16):
#rvi
opcode = 0b1101111
instr_rvi = (random.getrandbits(25) << 7) | opcode
#rvc
func3 = 0b101
op = 0b01
instr_rvc = (func3 << 13) | (random.getrandbits(11) << 2) | op
self.brTypes.append(2)
if isa == 'random':
self.instrs.append(random.choice([instr_rvi, instr_rvc]))
elif isa == 'rvi':
self.instrs.append(instr_rvi)
elif isa == 'rvc':
self.instrs.append(instr_rvc)
elif type == 'jalr':
#generate jalr type instructions
for _ in range(16):
#rvi
funct3 = 0b000
opcode = 0b1100111
instr_rvi = (random.getrandbits(17) << 25) | funct3 << 12 |\
(random.getrandbits(5) << 7) | opcode
#rvc
rs1 = random.getrandbits(5) | 0b1
head = random.choice([0b1001,0b1000])
tail = 0b00000_10
instr_rvc = (head << 12) | (rs1 << 7) | tail
self.brTypes.append(3)
if isa == 'random':
self.instrs.append(random.choice([instr_rvi, instr_rvc]))
elif isa == 'rvi':
self.instrs.append(instr_rvi)
elif isa == 'rvc':
self.instrs.append(instr_rvc)
elif type == 'not_cfi':
#generate not cfi type instructions
for _ in range(16):
#rvi
opcode = random.getrandbits(7) | 0b11
funct3 = random.getrandbits(3)
while True:
flag1 = (opcode == 0b1100011) and (funct3 in [0b000,0b001,0b010,0b011,0b100,0b101,0b110,0b111])
flag2 = (opcode == 0b1101111)
flag3 = (opcode == 0b1100111) and (funct3 == 0b000)
if not flag3 and not flag2 and not flag1:
break
opcode = random.getrandbits(7) | 0b11
funct3 = random.getrandbits(3)
instr_rvi = random.getrandbits(17) << 15 | funct3 << 12 | random.getrandbits(5) << 7 | opcode
#rvc
c_ebreak = 0b100_1_00000_00000_10
instr_rvc = random.getrandbits(16)
while True:
op = instr_rvc & 0b11
func3 = instr_rvc >> 13
flag1 = (op == 0b01) and (func3 in [0b110, 0b111, 0b101])
j1 = instr_rvc & 0b1111111
j2 = instr_rvc >> 12
flag2 = (j1 == 0b0000010) and (j2 in [0b1001, 0b1000])
flag3 = op == 0b11
if not flag1 and not flag2 and not flag3:
break
instr_rvc = random.getrandbits(16)
self.brTypes.append(0)
self.instrs.append(random.choice([instr_rvc,instr_rvi,c_ebreak]))
return self.instrs, self.brTypes
def precoding_checker(self, task = '2.1.1'):
if task == '2.1.1':
self.instrs = [self.instr_gen(type = 'random', isa = 'rvc') for _ in range(17)]
self.rvcs = [1 for _ in range(16)]
return self.instrs, self.rvcs
if task == '2.1.2':
self.instrs = [random.getrandbits(16) | 0b11 for _ in range(17)]
self.rvcs = [0 for _ in range(16)]
return self.instrs, self.rvcs
if task == '2.2.1':
self.instrs = [self.instr_gen(type = 'j', isa = 'rvc') for _ in range(17)]
def offset(instr):
mask = 0b11111111111
offset = (instr >> 2) & mask
o11 = (offset >> 10) & 1
o4 = (offset >> 9) & 1
o98 = (offset >> 7) & 0b11
o10 = (offset >> 6) & 1
o6 = (offset >> 5) & 1
o7 = (offset >> 4) & 1
o31 = (offset >> 1) & 0b111
o5 = (offset >> 0) & 1
offset = (o11 << 11) | (o4 << 4) | (o98 << 8) | (o10 << 10) | (o6 << 6) | (o7 << 7) | (o31 << 1) | (o5 << 5)
offset = offset if o11 == 0 else (offset | (0b1111) << 12) & 0xFFFF
return offset
self.jmp_offsets = [offset(i) for i in self.instrs]
self.jmp_offsets.pop()
return self.instrs, self.jmp_offsets
if task == '2.2.2':
self.instrs = [random.getrandbits(9) << 7 | 0b1101111 for _ in range(17)]
self.new_instrs = [self.instrs[i+1] << 16 | self.instrs[i] for i in range(16)]
def offset(instr):
offset = instr >> 12
o20 = (offset >> 19) & 1
o101 = (offset >> 9) & 0b1111111111
o11 = (offset >> 8) & 1
o1912 = offset & 0b11111111
offset = (o20 << 20) | (o101 << 1) | (o11 << 11) | (o1912 << 12)
offset = offset & 0xFFFFFFFF if o20 == 0 else (offset | (0xFFFFFF) << 21) & 0xFFFFFFFF
return offset
self.jmp_offsets = [offset(i) for i in self.new_instrs]
return self.instrs, self.jmp_offsets
if task == '2.2.3':
self.instrs = [self.instr_gen(type = 'br', isa = 'rvc') for _ in range(17)]
def offset(instr):
o5 = (instr >> 2) & 1
o21 = (instr >> 3) & 0b11
o76 = (instr >> 5) & 0b11
o43 = (instr >> 10) & 0b11
o8 = (instr >> 12) & 1
offset = o5 << 5 | o21 << 1 | o76 << 6 | o43 << 3 | o8 << 8
offset = offset if o8 == 0 else (offset | 0xFF << 9) & 0xFFFF
return offset
self.jmp_offsets = [offset(i) for i in self.instrs]
self.jmp_offsets.pop()
return self.instrs, self.jmp_offsets
if task == '2.2.4':
def offset(instr):
o12 = (instr >> 31) & 1
o105 = (instr >> 25) & 0b111111
o11 = (instr >> 7) & 1
o41 = (instr >> 8) & 0b1111
offset = o12 << 12 | o105 << 5 | o11 << 11 | o41 << 1
offset = offset if o12 == 0 else (offset | 0xFFFFFFF << 13) & 0xFFFFFFFF
return offset
self.instrs = [random.getrandbits(5) << 7 | random.getrandbits(1) << 15 | 0b1100011 | random.choice([0b000,0b001,0b100,0b101,0b110,0b111]) << 12 for _ in range(17)]
self.new_instrs = [self.instrs[i+1] << 16 | self.instrs[i] for i in range(16)]
self.jmp_offsets = [offset(i) for i in self.new_instrs]
return self.instrs, self.jmp_offsets
if task == '3.1':
self.instrs = [random.getrandbits(16) for _ in range(17)]
self.new_instrs = [self.instrs[i+1] << 16 | self.instrs[i] for i in range(16)]
mask = 0b11
flag = 2
for i in range(16):
if i == 0:
self.valid_starts.append(1)
flag = 1 if (self.new_instrs[i] & mask) == 0b11 else 0
else:
if flag == 1:
self.valid_starts.append(0)
flag = 2
elif flag == 0:
self.valid_starts.append(1)
flag = 1 if (self.new_instrs[i] & mask) == 0b11 else 0
elif flag == 2:
self.valid_starts.append(1)
flag = 1 if (self.new_instrs[i] & mask) == 0b11 else 0
return self.instrs, self.valid_starts
if task == '3.2':
self.instrs = [random.getrandbits(16) for _ in range(17)]
self.new_instrs = [self.instrs[i+1] << 16 | self.instrs[i] for i in range(16)]
mask = 0b11
flag = 2
for i in range(16):
if i == 0:
self.half_valid_starts.append(0)
elif i == 1:
self.half_valid_starts.append(1)
flag = 1 if (self.new_instrs[i] & mask) == 0b11 else 0
else:
if flag == 1:
self.half_valid_starts.append(0)
flag = 2
elif flag == 0:
self.half_valid_starts.append(1)
flag = 1 if (self.new_instrs[i] & mask) == 0b11 else 0
elif flag == 2:
self.half_valid_starts.append(1)
flag = 1 if (self.new_instrs[i] & mask) == 0b11 else 0
return self.instrs, self.half_valid_starts

View File

@ -1,10 +1,108 @@
import toffee_test
from .predecode_fixture import predecode_env
from ..env import PreDecodeEnv
from .predecode_instr_gen import PreDecodeInstrGen
instrGen = PreDecodeInstrGen()
@toffee_test.testcase
async def test_smoke(predecode_env : PreDecodeEnv):
fake_instrs = [54541 for i in range(17)]
res = await predecode_env.agent.predecode(fake_instrs)
print(res)
@toffee_test.testcase
async def test_splice_checker(predecode_env : PreDecodeEnv):
#指令拼接测试
print('test_splice_checker')
for _ in range(100):
instrGen.clear()
instrs, new_instrs = instrGen.random_instrs()
res = await predecode_env.agent.predecode(instrs)
assert res.new_instrs == new_instrs
@toffee_test.testcase
async def test_precoding_checker_2_1_1(predecode_env : PreDecodeEnv):
##RVC判定
print('test_precoding_checker_2_1_1')
for _ in range(100):
instrGen.clear()
instrs, rvcs = instrGen.precoding_checker(task = '2.1.1')
res = await predecode_env.agent.predecode(instrs)
assert res.rvcs == rvcs
@toffee_test.testcase
async def test_precoding_checker_2_1_2(predecode_env : PreDecodeEnv):
#RVI判定
print('test_precoding_checker_2_1_2')
for _ in range(100):
instrGen.clear()
instrs, rvcs = instrGen.precoding_checker(task = '2.1.2')
res = await predecode_env.agent.predecode(instrs)
assert res.rvcs == rvcs
@toffee_test.testcase
async def test_precoding_checker_2_2_1(predecode_env : PreDecodeEnv):
##RVC.J计算 offset
print('test_precoding_checker_2_2_1')
for _ in range(100):
instrGen.clear()
instrs, jmp_offsets = instrGen.precoding_checker(task = '2.2.1')
res = await predecode_env.agent.predecode(instrs)
assert [i & 0xFFFF for i in res.jmp_offsets] == jmp_offsets
@toffee_test.testcase
async def test_precoding_checker_2_2_2(predecode_env : PreDecodeEnv):
##RVI.J计算 offset
print('test_precoding_checker_2_2_2')
for _ in range(100):
instrGen.clear()
instrs, jmp_offsets = instrGen.precoding_checker(task = '2.2.2')
res = await predecode_env.agent.predecode(instrs)
assert [i & 0xFFFFFFFF for i in res.jmp_offsets] == jmp_offsets
@toffee_test.testcase
async def test_precoding_checker_2_2_3(predecode_env : PreDecodeEnv):
#RVC.BR计算 offset
print('test_precoding_checker_2_2_3')
for _ in range(100):
instrGen.clear()
instrs, jmp_offsets = instrGen.precoding_checker(task = '2.2.3')
res = await predecode_env.agent.predecode(instrs)
assert [i & 0xFFFF for i in res.jmp_offsets] == jmp_offsets
@toffee_test.testcase
async def test_precoding_checker_2_2_4(predecode_env : PreDecodeEnv):
#RVI.BR计算 offset
print('test_precoding_checker_2_2_4')
for _ in range(100):
instrGen.clear()
instrs, jmp_offsets = instrGen.precoding_checker(task = '2.2.4')
res = await predecode_env.agent.predecode(instrs)
assert [i & 0xFFFFFFFF for i in res.jmp_offsets] == jmp_offsets
@toffee_test.testcase
async def test_precoding_checker_3_1(predecode_env : PreDecodeEnv):
#有效指令开始向量计算1
print('test_precoding_checker_3_1')
for _ in range(100):
instrGen.clear()
instrs, valid_starts = instrGen.precoding_checker(task = '3.1')
res = await predecode_env.agent.predecode(instrs)
assert res.valid_starts == valid_starts
@toffee_test.testcase
async def test_precoding_checker_3_2(predecode_env : PreDecodeEnv):
#有效指令开始向量计算2
print('test_precoding_checker_3_2')
for _ in range(100):
instrGen.clear()
instrs, half_valid_starts = instrGen.precoding_checker(task = '3.2')
res = await predecode_env.agent.predecode(instrs)
assert res.half_valid_starts ==half_valid_starts
@toffee_test.testcase
async def test_precoding_checker_2_3_1(predecode_env : PreDecodeEnv):
#非CFI判定
print('test_precoding_checker_2_3_1')
#TODO

View File

@ -31,6 +31,7 @@ def test_req_from_icache_rand_vaddr_rand_valid_single_port(tlb_fixture):
# connect to fixture
tlb = tlb_fixture
# add watch point
case_name = inspect.currentframe().f_back.f_code.co_name
g.add_watch_point(tlb.requestor_0.resp.miss, {
"miss": fc.Eq(1),
@ -52,7 +53,7 @@ def test_req_from_icache_rand_vaddr_rand_valid_single_port(tlb_fixture):
tlb.set_default_value()
# reset
tlb.reset()
print(tlb)
# add clock
tlb.dut.xclock.StepRis(lambda _: g.sample())
# start

View File

@ -26,7 +26,7 @@ import inspect
# the bug occurs. In practice, initiating a request (req) simultaneously with
# a reset signal constitutes an invalid input and violates the protocol
# specification.
def test_reset_when_request(tlb_fixture):
def reset_when_request(tlb_fixture):
"""
Check reset
Request & reset in the same cycle