forked from XS-MLVP/env-xs-ov-00-bpu
add func test and manual run support
This commit is contained in:
parent
277168bb40
commit
155b1eaab5
|
@ -101,7 +101,7 @@ def reset_init(ittage: DUTITTage):
|
|||
mlvp.info("ITTAGE initialized")
|
||||
|
||||
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()
|
||||
reset_init(self.dut)
|
||||
self.top = ITTAGETop(self.dut, log_mode)
|
||||
|
@ -111,6 +111,7 @@ class ITTAGEDriver:
|
|||
self.top.s3_fire = 1
|
||||
self.max_trace = max_trace
|
||||
self.trace_count = 0
|
||||
self.update_latency = update_latency
|
||||
|
||||
def run(self, trace_file_path: str = ""):
|
||||
mlvp.info("================== Running ITTAGE Driver with Trace ==================")
|
||||
|
@ -182,5 +183,14 @@ class ITTAGEDriver:
|
|||
break
|
||||
|
||||
|
||||
def manual_run(self, pc: int, folded_hists, target: int):
|
||||
self.top.cycle(has_trace=True, pc=pc, folded_hists=folded_hists, target=target)
|
||||
def manual_run(self, pc: int = 0, folded_hists = [], target: int = 0, manual_alloc: bool = False,
|
||||
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)
|
|
@ -176,6 +176,7 @@ class ITTAGEInfo(ITTAGEInterReg, ITTAGELastStageMeta):
|
|||
ITTAGEInterReg.__init__(self)
|
||||
ITTAGELastStageMeta.__init__(self)
|
||||
self.is_trace = 0
|
||||
self.manual_alloc = 0
|
||||
self.pc = 0
|
||||
self.folded_hists = [0, 0, [0,0], [0,0], [0,0]]
|
||||
# output feedback
|
||||
|
@ -195,6 +196,7 @@ class ITTAGEInfo(ITTAGEInterReg, ITTAGELastStageMeta):
|
|||
|
||||
def clear(self) -> None:
|
||||
self.is_trace = 0
|
||||
self.manual_alloc = 0
|
||||
self.pc = 0
|
||||
self.folded_hists = [0, 0, [0, 0], [0, 0], [0, 0]]
|
||||
self.update_valid = 0
|
||||
|
|
|
@ -14,7 +14,7 @@ import queue
|
|||
import random
|
||||
|
||||
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.ref = ITTAGEModel(log_mode)
|
||||
# input in current cycle
|
||||
|
@ -25,7 +25,8 @@ class ITTAGETop:
|
|||
# update queue (to simulate latency of update)
|
||||
self.update_q = queue.Queue()
|
||||
self.cycles = 0
|
||||
self.latency = 20
|
||||
self.latency = update_latency
|
||||
assert(self.latency >= 1)
|
||||
# for debug
|
||||
self.log_mode = log_mode
|
||||
self.has_dut = isinstance(dut, DUTITTage)
|
||||
|
@ -69,9 +70,15 @@ class ITTAGETop:
|
|||
return self
|
||||
|
||||
def _assign_dut_meta_to_ref(self, ref_info: ITTAGEInfo, dut_info: ITTAGEInfo):
|
||||
ref_info.alloc_valid = dut_info.alloc_valid
|
||||
ref_info.alloc_table = dut_info.alloc_table
|
||||
ref_info.meta_str = dut_info.meta_str
|
||||
if not ref_info.manual_alloc:
|
||||
ref_info.alloc_valid = dut_info.alloc_valid
|
||||
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):
|
||||
# When no provider, set mispred to allocate new table item
|
||||
|
@ -99,7 +106,8 @@ class ITTAGETop:
|
|||
return False
|
||||
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_info = None
|
||||
if is_trace:
|
||||
|
@ -108,6 +116,12 @@ class ITTAGETop:
|
|||
_input_info.pc = pc
|
||||
_input_info.folded_hists = folded_hists
|
||||
_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
|
||||
self.ref.set_s0_fire(self.s0_fire)
|
||||
self.ref.set_s1_fire(self.s1_fire)
|
||||
|
@ -135,7 +149,6 @@ class ITTAGETop:
|
|||
self.dut.Step(1)
|
||||
|
||||
def _assign_dut_update(self, update: ITTAGEInfo = None):
|
||||
# TODO: assign DUT update signals
|
||||
# no DUT or no update valid in this cycle
|
||||
if not self.has_dut:
|
||||
return
|
||||
|
@ -167,7 +180,6 @@ class ITTAGETop:
|
|||
|
||||
def _log_info(self, ref_info: ITTAGELastStageMeta = None, dut_info: ITTAGELastStageMeta = None):
|
||||
# basic meta log
|
||||
# TODO: ref_info attribute error
|
||||
mlvp.info(f'================= cycle={self.cycles} =================')
|
||||
title = ['dut output:', 'ref output:']
|
||||
_info_vec: list[ITTAGELastStageMeta] = [dut_info, ref_info]
|
||||
|
@ -176,7 +188,8 @@ class ITTAGETop:
|
|||
_info_vec[i].log_meta()
|
||||
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 --------------
|
||||
_out_ref_info = self._gen_ref_output()
|
||||
# ------------- Gen DUT Output --------------
|
||||
|
@ -210,7 +223,7 @@ class ITTAGETop:
|
|||
self._assign_dut_update(_update_info)
|
||||
|
||||
# ------------- 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.cycles += 1
|
||||
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue