add func test and manual run support

This commit is contained in:
llyyqq 2024-09-20 10:12:30 +08:00
parent 277168bb40
commit 155b1eaab5
4 changed files with 201 additions and 13 deletions

View File

@ -101,7 +101,7 @@ def reset_init(ittage: DUTITTage):
mlvp.info("ITTAGE initialized") mlvp.info("ITTAGE initialized")
class ITTAGEDriver: class ITTAGEDriver:
def __init__(self, log_mode: int = 0, max_trace: int = 10000): def __init__(self, log_mode: int = 0, max_trace: int = 10000, update_latency: int = 10):
self.dut = DUTITTage() self.dut = DUTITTage()
reset_init(self.dut) reset_init(self.dut)
self.top = ITTAGETop(self.dut, log_mode) self.top = ITTAGETop(self.dut, log_mode)
@ -111,6 +111,7 @@ class ITTAGEDriver:
self.top.s3_fire = 1 self.top.s3_fire = 1
self.max_trace = max_trace self.max_trace = max_trace
self.trace_count = 0 self.trace_count = 0
self.update_latency = update_latency
def run(self, trace_file_path: str = ""): def run(self, trace_file_path: str = ""):
mlvp.info("================== Running ITTAGE Driver with Trace ==================") mlvp.info("================== Running ITTAGE Driver with Trace ==================")
@ -182,5 +183,14 @@ class ITTAGEDriver:
break break
def manual_run(self, pc: int, folded_hists, target: int): def manual_run(self, pc: int = 0, folded_hists = [], target: int = 0, manual_alloc: bool = False,
self.top.cycle(has_trace=True, pc=pc, folded_hists=folded_hists, target=target) alloc_valid: int = 0, alloc_table: int = 0):
self.top.cycle(has_trace = True, pc = pc, folded_hists = folded_hists, target = target,
manual_alloc = manual_alloc, alloc_valid = alloc_valid, alloc_table = alloc_table)
_wait_cycles = 3
if manual_alloc:
_wait_cycles += self.update_latency + 2
# wait util both the prediction and update are done
for _ in range(0, _wait_cycles):
self.top.cycle(has_trace = False)

View File

@ -176,6 +176,7 @@ class ITTAGEInfo(ITTAGEInterReg, ITTAGELastStageMeta):
ITTAGEInterReg.__init__(self) ITTAGEInterReg.__init__(self)
ITTAGELastStageMeta.__init__(self) ITTAGELastStageMeta.__init__(self)
self.is_trace = 0 self.is_trace = 0
self.manual_alloc = 0
self.pc = 0 self.pc = 0
self.folded_hists = [0, 0, [0,0], [0,0], [0,0]] self.folded_hists = [0, 0, [0,0], [0,0], [0,0]]
# output feedback # output feedback
@ -195,6 +196,7 @@ class ITTAGEInfo(ITTAGEInterReg, ITTAGELastStageMeta):
def clear(self) -> None: def clear(self) -> None:
self.is_trace = 0 self.is_trace = 0
self.manual_alloc = 0
self.pc = 0 self.pc = 0
self.folded_hists = [0, 0, [0, 0], [0, 0], [0, 0]] self.folded_hists = [0, 0, [0, 0], [0, 0], [0, 0]]
self.update_valid = 0 self.update_valid = 0

View File

@ -14,7 +14,7 @@ import queue
import random import random
class ITTAGETop: class ITTAGETop:
def __init__(self, dut: DUTITTage = None, log_mode: int = 0) -> None: def __init__(self, dut: DUTITTage = None, log_mode: int = 0, update_latency: int = 10) -> None:
self.dut = dut self.dut = dut
self.ref = ITTAGEModel(log_mode) self.ref = ITTAGEModel(log_mode)
# input in current cycle # input in current cycle
@ -25,7 +25,8 @@ class ITTAGETop:
# update queue (to simulate latency of update) # update queue (to simulate latency of update)
self.update_q = queue.Queue() self.update_q = queue.Queue()
self.cycles = 0 self.cycles = 0
self.latency = 20 self.latency = update_latency
assert(self.latency >= 1)
# for debug # for debug
self.log_mode = log_mode self.log_mode = log_mode
self.has_dut = isinstance(dut, DUTITTage) self.has_dut = isinstance(dut, DUTITTage)
@ -69,9 +70,15 @@ class ITTAGETop:
return self return self
def _assign_dut_meta_to_ref(self, ref_info: ITTAGEInfo, dut_info: ITTAGEInfo): def _assign_dut_meta_to_ref(self, ref_info: ITTAGEInfo, dut_info: ITTAGEInfo):
ref_info.alloc_valid = dut_info.alloc_valid if not ref_info.manual_alloc:
ref_info.alloc_table = dut_info.alloc_table ref_info.alloc_valid = dut_info.alloc_valid
ref_info.meta_str = dut_info.meta_str ref_info.alloc_table = dut_info.alloc_table
ref_info.meta_str = dut_info.meta_str
else:
_alloc_valid_str = '1' if ref_info.alloc_valid == 1 else '0'
_alloc_table_str = bin(ref_info.alloc_table).ljust(3, '0')
ref_info.meta_str = dut_info.meta_str[0:14] + _alloc_valid_str + _alloc_table_str + dut_info.meta_str[18:]
assert(len(ref_info.meta_str) == 101)
def _assign_mispred(self, out_info: ITTAGEInfo): def _assign_mispred(self, out_info: ITTAGEInfo):
# When no provider, set mispred to allocate new table item # When no provider, set mispred to allocate new table item
@ -99,7 +106,8 @@ class ITTAGETop:
return False return False
return True return True
def _ref_input_and_step(self, is_trace: bool, pc: int, folded_hists, target: int): def _ref_input_and_step(self, is_trace: bool, pc: int, folded_hists, target: int, manual_alloc: bool = False,
alloc_valid: int = 0, alloc_table: int = 0):
# input drive from outside # input drive from outside
_input_info = None _input_info = None
if is_trace: if is_trace:
@ -108,6 +116,12 @@ class ITTAGETop:
_input_info.pc = pc _input_info.pc = pc
_input_info.folded_hists = folded_hists _input_info.folded_hists = folded_hists
_input_info.target = target _input_info.target = target
if manual_alloc:
assert(alloc_valid == '0' or alloc_valid == '1')
assert(alloc_table >= 0 and alloc_table <= 4)
_input_info.manual_alloc = manual_alloc
_input_info.alloc_valid = alloc_valid
_input_info.alloc_table = alloc_table
# Set ref pipeline shake hand signal # Set ref pipeline shake hand signal
self.ref.set_s0_fire(self.s0_fire) self.ref.set_s0_fire(self.s0_fire)
self.ref.set_s1_fire(self.s1_fire) self.ref.set_s1_fire(self.s1_fire)
@ -135,7 +149,6 @@ class ITTAGETop:
self.dut.Step(1) self.dut.Step(1)
def _assign_dut_update(self, update: ITTAGEInfo = None): def _assign_dut_update(self, update: ITTAGEInfo = None):
# TODO: assign DUT update signals
# no DUT or no update valid in this cycle # no DUT or no update valid in this cycle
if not self.has_dut: if not self.has_dut:
return return
@ -167,7 +180,6 @@ class ITTAGETop:
def _log_info(self, ref_info: ITTAGELastStageMeta = None, dut_info: ITTAGELastStageMeta = None): def _log_info(self, ref_info: ITTAGELastStageMeta = None, dut_info: ITTAGELastStageMeta = None):
# basic meta log # basic meta log
# TODO: ref_info attribute error
mlvp.info(f'================= cycle={self.cycles} =================') mlvp.info(f'================= cycle={self.cycles} =================')
title = ['dut output:', 'ref output:'] title = ['dut output:', 'ref output:']
_info_vec: list[ITTAGELastStageMeta] = [dut_info, ref_info] _info_vec: list[ITTAGELastStageMeta] = [dut_info, ref_info]
@ -176,7 +188,8 @@ class ITTAGETop:
_info_vec[i].log_meta() _info_vec[i].log_meta()
return self return self
def cycle(self, has_trace: bool = False, pc: int = 0, folded_hists = [], target: int = 0): def cycle(self, has_trace: bool = False, pc: int = 0, folded_hists = [], target: int = 0,
manual_alloc: bool = False, alloc_valid: int = 0, alloc_table: int = 0):
# ------------- Gen Ref output -------------- # ------------- Gen Ref output --------------
_out_ref_info = self._gen_ref_output() _out_ref_info = self._gen_ref_output()
# ------------- Gen DUT Output -------------- # ------------- Gen DUT Output --------------
@ -210,7 +223,7 @@ class ITTAGETop:
self._assign_dut_update(_update_info) self._assign_dut_update(_update_info)
# ------------- Input and Cycle -------------- # ------------- Input and Cycle --------------
self._ref_input_and_step(has_trace, pc, folded_hists, target) self._ref_input_and_step(has_trace, pc, folded_hists, target, manual_alloc, alloc_valid, alloc_table)
self._dut_input_and_step(has_trace, pc, folded_hists) self._dut_input_and_step(has_trace, pc, folded_hists)
self.cycles += 1 self.cycles += 1

View File

@ -0,0 +1,163 @@
import os
os.sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/..")
import mlvp
from env.driver import *
from utils.BRTParser import *
import random
def gen_random_pc_and_fh(fh: FoldedHists = None):
pc = random.randint(0, 0x1ffffffffff)
if fh is None:
return pc, [0, 0, [0, 0], [0, 0], [0, 0]]
else:
fh.reinit_random_gh()
return pc, fh.get_ref_fh()
# TODO: last manual_run should not raise update
# TODO: DUT.Finish()
# Test provider provides targets function
def test_ittage_provider():
mlvp.setup_logging(log_level=logging.INFO,
format=default_fmt,
console_display=True,
log_file='log_ittage_provider.log')
_driver = ITTAGEDriver(log_mode = 0, max_trace = 1000, update_latency = 1)
fh = FoldedHists()
_targets = [0x1111111111, 0x2222222222, 0x3333333333, 0x4444444444, 0x5555555555]
for i in range(0, 5):
_pc, _fh = gen_random_pc_and_fh(fh)
# alloc new table
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[i], manual_alloc = True, alloc_valid = 1, alloc_table = i)
# repredict
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[i], manual_alloc = False)
# Test alt provider functions
def test_ittage_alt_provider():
mlvp.setup_logging(log_level=logging.INFO,
format=default_fmt,
console_display=True,
log_file='log_ittage_alt_provider.log')
_driver = ITTAGEDriver(log_mode = 0, max_trace = 1000, update_latency = 1)
fh = FoldedHists()
_targets = [0x1111111111, 0x2222222222, 0x3333333333, 0x4444444444, 0x5555555555]
# alt provider alloc and ctr functions
for provider in range(0, 5):
for alt in range(0, provider):
_pc, _fh = gen_random_pc_and_fh(fh)
# alloc new table, provider_ctr -> 0b01, alt_ctr -> 0b00
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[0], manual_alloc = True, alloc_valid = 1, alloc_table = alt)
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[1], manual_alloc = True, alloc_valid = 1, alloc_table = provider)
# provider incorrect 2 times then alt incorrect 1 time
for i in range(2, 5):
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[i], manual_alloc = True, alloc_valid = 0)
# check
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[4], manual_alloc = False)
# TODO: alt differs funtions (equal and not equal)
for provider in range(0, 5):
for alt in range(0, provider):
_pc, _fh = gen_random_pc_and_fh(fh)
# alloc new table, provider_ctr -> 0b10, alt_ctr -> 0b01
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[0], manual_alloc = True, alloc_valid = 1, alloc_table = alt)
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[1], manual_alloc = True, alloc_valid = 1, alloc_table = provider)
# check
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[2], manual_alloc = False)
# Test ctr functions
def test_ittage_ctr():
mlvp.setup_logging(log_level=logging.INFO,
format=default_fmt,
console_display=True,
log_file='log_ittage_ctr.log')
_driver = ITTAGEDriver(log_mode = 0, max_trace = 1000, update_latency = 1)
fh = FoldedHists()
_targets = [0x1111111111, 0x2222222222, 0x3333333333, 0x4444444444]
# single provider ctr
for provider in range(0, 5):
_pc, _fh = gen_random_pc_and_fh(fh)
# alloc new table, provider_ctr -> 0b10
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[0], manual_alloc = True, alloc_valid = 1, alloc_table = provider)
# provider incorrect, provider_ctr from 0b10 to 0b00
for i in range(1, 3):
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[i], manual_alloc = True, alloc_valid = 0)
# provider ctr from 0b00 to 0b11
for _ in range(0, 5):
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[2], manual_alloc = True, alloc_valid = 0)
# alt ctr update function
for provider in range(0, 5):
for alt in range(0, provider):
_pc, _fh = gen_random_pc_and_fh(fh)
# alloc new table, provider_ctr -> 0b10, alt_ctr -> 0b01
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[0], manual_alloc = True, alloc_valid = 1, alloc_table = alt)
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[1], manual_alloc = True, alloc_valid = 1, alloc_table = provider)
# provider incorrectt, provider_ctr from 0b10 to 0b00
for i in range(2, 4):
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[i], manual_alloc = True, alloc_valid = 0)
# alt correct, alt_ctr from 0b01 to 0b10
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[0], manual_alloc = True, alloc_valid = 0)
# Test usefulness functions
def test_ittage_useful():
mlvp.setup_logging(log_level=logging.INFO,
format=default_fmt,
console_display=True,
log_file='log_ittage_useful.log')
_driver = ITTAGEDriver(log_mode = 0, max_trace = 1000, update_latency = 1)
fh = FoldedHists()
_targets = [0x1111111111, 0x2222222222, 0x3333333333]
for provider in range(0, 5):
for alt in range(0, provider):
_pc, _fh = gen_random_pc_and_fh(fh)
# alloc new table, provider_ctr -> 0b10, alt_ctr -> 0b01
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[0], manual_alloc = True, alloc_valid = 1, alloc_table = alt)
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[1], manual_alloc = True, alloc_valid = 1, alloc_table = provider)
# provider correct, alt differs, providerU -> 0b1
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[1], manual_alloc = True, alloc_valid = 0)
# provider incorrect, alt differs, providerU -> 0b0
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[2], manual_alloc = True, alloc_valid = 0)
# Test usefulness functions
def test_ittage_useful():
mlvp.setup_logging(log_level=logging.INFO,
format=default_fmt,
console_display=True,
log_file='log_ittage_useful.log')
_driver = ITTAGEDriver(log_mode = 0, max_trace = 1000, update_latency = 1)
fh = FoldedHists()
_targets = [0x1111111111, 0x2222222222]
# tickCtr function test
_input_vec = []
# Set useful in a random chosen table item for every table
for provider in range(0, 5):
_pc, _fh = gen_random_pc_and_fh(fh)
# alloc new table, provider_ctr -> 0b10, alt_ctr -> 0b01
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[0], manual_alloc = True, alloc_valid = 1, alloc_table = 0)
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[1], manual_alloc = True, alloc_valid = 1, alloc_table = provider)
# provider correct, alt differs, providerU -> 0b1
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _targets[1], manual_alloc = True, alloc_valid = 0)
_input_vec.append((_pc, _fh))
# increase tickCtr
for i in range(0, 255):
_target_random = random.randint(0, 0x1ffffffffff)
_pc, _fh = gen_random_pc_and_fh(fh)
_driver.manual_run(pc = _pc, folded_hists = _fh, target = _target_random, manual_alloc = True, alloc_valid = 0)
# check useful is set to 0
for (temp_pc, temp_fh) in _input_vec:
_target_random = random.randint(0, 0x1ffffffffff)
_driver.manual_run(pc = temp_pc, folded_hists = temp_fh, target = _target_random, manual_alloc = True, alloc_valid = 0)