diff --git a/scripts/build_ut_frontend_bpu_ittage.py b/scripts/build_ut_frontend_bpu_ittage.py index fc42f90..d28ef8a 100644 --- a/scripts/build_ut_frontend_bpu_ittage.py +++ b/scripts/build_ut_frontend_bpu_ittage.py @@ -17,8 +17,34 @@ def build(cfg): - return False + from tempfile import NamedTemporaryFile + from toffee_test.markers import match_version + from comm import error, info, get_root_dir, exe_cmd, get_all_rtl_files + + # check version + if not match_version(cfg.rtl.version, "openxiangshan-kmh-*"): + error(f"frontend_bpu_ittage: Unsupported RTL version {cfg.rtl.version}") + return False + + # find source files for ITTage + rtl_files = get_all_rtl_files("ITTage", cfg=cfg) + assert rtl_files, "Cannot find RTL files of Frontend.BPU.ITTage" + + internal_signals_path = os.path.join(get_root_dir("ut_frontend/bpu/ittage/internal.yaml")) + assert os.path.exists(internal_signals_path), "Cannot find internal signal files" + + # export ITTage.sv + if not os.path.exists(get_root_dir("dut/ITTage")): + info("Exporting ITTage.sv") + with NamedTemporaryFile("w+", encoding="utf-8", suffix=".txt") as filelist: + filelist.write("\n".join(rtl_files)) + filelist.flush() + s, _, err = exe_cmd( + f"picker export --cp_lib false {rtl_files[0]} --fs {filelist.name} --lang python --tdir " + f"{get_root_dir('dut')}/ -w ITTage.fst -c --internal={internal_signals_path}") + assert s, err + return True def line_coverage_files(cfg): - return [] + return ["ITTage.v"] diff --git a/ut_frontend/bpu/ittage/env/__init__.py b/ut_frontend/bpu/ittage/env/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ut_frontend/bpu/ittage/env/bundle.py b/ut_frontend/bpu/ittage/env/bundle.py new file mode 100644 index 0000000..69e079a --- /dev/null +++ b/ut_frontend/bpu/ittage/env/bundle.py @@ -0,0 +1,48 @@ +__all__ = ['UpdateBundle', 'InBundle', 'OutBundle', 'PipelineCtrl'] + +from toffee import Bundle, Signals, Signal + +class PipelineCtrl(Bundle): + s0_fire_0, s0_fire_1, s0_fire_2, s0_fire_3 = Signals(4) + s1_fire_0, s1_fire_1, s1_fire_2, s1_fire_3 = Signals(4) + s2_fire_0, s2_fire_1, s2_fire_2, s2_fire_3 = Signals(4) + +class FullPred(Bundle): + jalr_target = Signal() + +class FoldedHist(Bundle): + [hist_14_folded_hist, hist_13_folded_hist , hist_12_folded_hist , hist_10_folded_hist, + hist_6_folded_hist , hist_4_folded_hist , hist_3_folded_hist , hist_2_folded_hist] = Signals(8) + +class FTBEntry(Bundle): + tailSlot_offset, tailSlot_sharing, tailSlot_valid, isRet, isJalr = Signals(5) + +class CFI(Bundle): + valid, bits = Signals(2) + +# io_update_ +class UpdateBundle(Bundle): + valid, bits_pc, bits_jmp_taken, bits_mispred_mask_2, bits_meta, bits_full_target = Signals(6) + bits_ghist = Signal() + ftb_entry = FTBEntry.from_prefix("bits_ftb_entry_") + # folded_hist= FoldedHist.from_prefix("bits_spec_info_folded_hist_") + cfi = CFI.from_prefix("bits_cfi_idx_") + +# io_in_ +class InBundle(Bundle): + bits_s0_pc_3 = Signal() + + folded_hist = FoldedHist.from_prefix("bits_s1_folded_hist_3_") + pred0 = FullPred.from_prefix("bits_resp_in_0_s2_full_pred_0_") + pred1 = FullPred.from_prefix("bits_resp_in_0_s2_full_pred_1_") + pred2 = FullPred.from_prefix("bits_resp_in_0_s2_full_pred_2_") + pred3 = FullPred.from_prefix("bits_resp_in_0_s2_full_pred_3_") + +# io_out_ +class OutBundle(Bundle): + last_stage_meta = Signal() + + pred1 = FullPred.from_prefix("s3_full_pred_1_") + pred0 = FullPred.from_prefix("s3_full_pred_0_") + pred2 = FullPred.from_prefix("s3_full_pred_2_") + pred3 = FullPred.from_prefix("s3_full_pred_3_") \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/env/global_history.py b/ut_frontend/bpu/ittage/env/global_history.py new file mode 100644 index 0000000..4914e60 --- /dev/null +++ b/ut_frontend/bpu/ittage/env/global_history.py @@ -0,0 +1,26 @@ +__all__ = ["GlobalHistory"] + +GLOBAL_HISTORY_LEN = 256 +GLOBAL_HISTORY_MASK = (1 << GLOBAL_HISTORY_LEN) - 1 + + +class GlobalHistory: + def __init__(self, init_val: int = 0, gh_len: int = GLOBAL_HISTORY_LEN): + self.value = init_val + self._len = gh_len + + def update(self, taken: bool) -> None: + g = self.value + self.value = (g << 1) | taken & GLOBAL_HISTORY_MASK + + def get_fh(self, folded_len: int, hist_len: int) -> int: + if folded_len == 0: + return 0 + res = 0 + g = self.value & ((1 << hist_len) - 1) + mask = (1 << folded_len) - 1 + for _ in range(0, min(self._len, hist_len), folded_len): + res ^= g & mask + g >>= folded_len + + return res \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/env/ittage_wrapper.py b/ut_frontend/bpu/ittage/env/ittage_wrapper.py new file mode 100644 index 0000000..e6e3d8d --- /dev/null +++ b/ut_frontend/bpu/ittage/env/ittage_wrapper.py @@ -0,0 +1,134 @@ +import os.path +import random +from datetime import datetime + + +import toffee +from toffee import ClockCycles +from dut.ITTage import DUTITTage +from ..util.common import get_folded_hist +from .bundle import * + +__all__ = ['ITTageWrapper'] + + +class ITTageWrapper: + def __init__(self, dut: DUTITTage): + # Create DUT + self.dut = dut + self.dut.InitClock("clock") + self.xclock = self.dut.xclock # for callback function + + # Connect Bundle + self.update_bundle = UpdateBundle.from_prefix("io_update_").set_name("ittage_update").bind(self.dut) + self.in_bundle = InBundle.from_prefix("io_in_").set_name("ittage_in").bind(self.dut) + self.out_bundle = OutBundle.from_prefix("io_out_").set_name("ittage_out").bind(self.dut) + self.pipeline_ctrl = PipelineCtrl.from_prefix("io_").set_name("ittage_pipeline_ctrl").bind(self.dut) + + # Reset + self.reset() + + def finalize(self): + self.dut.Finish() + + async def __rst_async__(self): + self.dut.reset.value = 1 + await ClockCycles(self.dut, 10) + self.dut.reset.value = 0 + + def __set_fire__(self, stage): + for i in range(0, 4): + getattr(self.pipeline_ctrl, f"s{stage}_fire_{i}").value = 1 + + + def __unset_fire__(self, stage): + for i in range(0, 4): + getattr(self.pipeline_ctrl, f"s{stage}_fire_{i}").value = 0 + + async def __predict_async__(self, fh, pc, use_dummy_fh=False): + # stage0 + self.__set_fire__(0) + self.in_bundle.bits_s0_pc_3.value = pc + if use_dummy_fh: + self.in_bundle.folded_hist.set_all(0) + else: + self.in_bundle.folded_hist.assign(get_folded_hist(fh)) + await ClockCycles(self.dut, 1) + self.__unset_fire__(0) + + # stage1 + self.__set_fire__(1) + await ClockCycles(self.dut, 1) + self.__unset_fire__(1) + + # stage2 + self.__set_fire__(2) + await ClockCycles(self.dut, 1) + self.__unset_fire__(2) + + # stage3 + await ClockCycles(self.dut, 1) + + return self.out_bundle.as_dict() + + async def __update_async__(self, update_req): + self.update_bundle.assign(update_req) + self.update_bundle.valid.value = 1 + await ClockCycles(self.dut, 1) + self.update_bundle.valid.value = 0 + + await ClockCycles(self.dut, 3) + + return None + + def predict(self, fh, pc, use_dummy_fh=False): + # stage0 + self.__set_fire__(0) + self.in_bundle.bits_s0_pc_3.value = pc + if use_dummy_fh: + self.in_bundle.folded_hist.set_all(0) + else: + self.in_bundle.folded_hist.assign(get_folded_hist(fh)) + self.xclock.Step(1) + self.__unset_fire__(0) + + # stage1 + self.__set_fire__(1) + self.xclock.Step(1) + self.__unset_fire__(1) + + # stage2 + self.__set_fire__(2) + self.xclock.Step(1) + self.__unset_fire__(2) + + # stage3 + self.xclock.Step(1) + + return self.out_bundle.as_dict() + + def predict_async(self, fh, pc, use_dummy_fh=False): + return toffee.create_task(self.__predict_async__(fh, pc, use_dummy_fh)) + + def update(self, update_req): + self.update_bundle.assign(update_req) + self.update_bundle.valid.value = 1 + self.xclock.Step(1) + self.update_bundle.valid.value = 0 + + self.xclock.Step(1) + pass + + def update_async(self, update_req): + return toffee.create_task(self.__update_async__(update_req)) + + def reset(self): + self.dut.reset.value = 1 + self.xclock.Step(1) + self.dut.reset.value = 0 + while self.dut.io_s1_ready.value == 0: + self.xclock.Step(1) + self.xclock.Step(10) + + def reset_async(self): + return toffee.create_task(self.__rst_async__()) \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/internal.yaml b/ut_frontend/bpu/ittage/internal.yaml new file mode 100644 index 0000000..ef2852f --- /dev/null +++ b/ut_frontend/bpu/ittage/internal.yaml @@ -0,0 +1,62 @@ +ITTage: + - "logic s3_altProvided" + - "logic [1:0] s3_altProviderCtr" + - "logic [40:0] s3_altProviderTarget" + - "logic [2:0] s3_altProvider" + - "logic s3_provided" + - "logic [1:0] s3_providerCtr" + - "logic s3_providerU" + - "logic [2:0] s3_provider" + - "logic [40:0] s3_providerTarget" + - "logic [7:0] tickCtr" + - "logic updateValid" + - tables_0: + - "wire io_resp_valid" + - "wire io_update_valid" + - "wire io_update_alloc" + - "wire io_update_correct" + - "wire [1:0] io_update_oldCtr" + - "wire [1:0] update_wdata_ctr" + - "wire io_update_reset_u" + - "wire io_update_uValid" + - "wire io_update_u" + - tables_1: + - "wire io_resp_valid" + - "wire io_update_valid" + - "wire io_update_alloc" + - "wire io_update_correct" + - "wire [1:0] io_update_oldCtr" + - "wire [1:0] update_wdata_ctr" + - "wire io_update_reset_u" + - "wire io_update_uValid" + - "wire io_update_u" + - tables_2: + - "wire io_resp_valid" + - "wire io_update_valid" + - "wire io_update_alloc" + - "wire io_update_correct" + - "wire [1:0] io_update_oldCtr" + - "wire [1:0] update_wdata_ctr" + - "wire io_update_reset_u" + - "wire io_update_uValid" + - "wire io_update_u" + - tables_3: + - "wire io_resp_valid" + - "wire io_update_valid" + - "wire io_update_alloc" + - "wire io_update_correct" + - "wire [1:0] io_update_oldCtr" + - "wire [1:0] update_wdata_ctr" + - "wire io_update_reset_u" + - "wire io_update_uValid" + - "wire io_update_u" + - tables_4: + - "wire io_resp_valid" + - "wire io_update_valid" + - "wire io_update_alloc" + - "wire io_update_correct" + - "wire [1:0] io_update_oldCtr" + - "wire [1:0] update_wdata_ctr" + - "wire io_update_reset_u" + - "wire io_update_uValid" + - "wire io_update_u" \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/__init__.py b/ut_frontend/bpu/ittage/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ut_frontend/bpu/ittage/test/chk_helper.py b/ut_frontend/bpu/ittage/test/chk_helper.py new file mode 100644 index 0000000..cfccb71 --- /dev/null +++ b/ut_frontend/bpu/ittage/test/chk_helper.py @@ -0,0 +1,116 @@ +""" + Define all the coverage group calculation here + Author: yzcc +""" +from comm import UT_FCOV +from .chk_pred import * +from .chk_train import * +from ..env.ittage_wrapper import ITTageWrapper + + +def get_cov_grp_of_alt_pred(dut: DUTITTage) -> CovGroup: + grp = CovGroup(UT_FCOV("../UT_ITTage")) + + bins = {} + for i in range(4): + bins[f"alt_use_table_{i}"] = is_alt_from_table_i(i) + + grp.add_watch_point(dut, bins, name="ITTAGE Alt Pred altProvider from Tn") + return grp + + +def get_cov_grp_of_longest_and_alt_train(dut: ITTageWrapper) -> CovGroup: + grp = CovGroup(UT_FCOV("../UT_ITTage")) + + bins_as_provider = {} + bins_as_alt = {} + for i in range(5): + # 第i个表被作为主预测更新 + bins_as_provider["_".join([f"table{i + 1}", "update", "as", "provider"])] = is_update_table_as_provider(i) + + # 第i个表被作为替代预测更新 + if i != 4: + bins_as_alt["_".join([f"table{i + 1}", "update", "as", "alt"])] = is_update_table_as_alt(i) + + grp.add_watch_point(dut, bins_as_provider, name="ITTAGE Longest and Alt Train Update as Provider") + grp.add_watch_point(dut, bins_as_alt, name="ITTAGE Longest and Alt Train Update as Alt Provider") + return grp + + +def get_cov_grp_of_main_pred(dut: DUTITTage) -> CovGroup: + grp = CovGroup(UT_FCOV("../UT_ITTage")) + + bins = {} + for i in range(5): + bins[f"T{i}_hit"] = is_hit_table_i(i) + + grp.add_watch_point(dut, bins, name="ITTAGE Main Pred Hit Tn") + return grp + + +def get_cov_grp_of_other_pred(dut: DUTITTage) -> CovGroup: + grp = CovGroup(UT_FCOV("../UT_ITTage")) + # 是否命中多个表 + grp.add_watch_point(dut, {"hit_multi": is_hit_multi_table()}, name="ITTAGE Other Pred Hit Multi Table") + + # 是否一个表都没命中 + grp.add_watch_point(dut, {"hit_no": is_hit_no_table()}, name="ITTAGE Other Pred Hit No Table") + + # Res src + # 替代预测来自ftb + bins_src = {} + bins_src["src_from_main"] = is_src_from_main() + bins_src["src_from_alt"] = is_src_from_alt() + bins_src["src_from_ftb"] = is_src_from_ftb() + grp.add_watch_point(dut, bins_src, name="ITTAGE Other Pred Result Source") + + return grp + + +def get_cov_grp_of_other_train(dut: DUTITTage) -> CovGroup: + grp = CovGroup(UT_FCOV("../UT_ITTage")) + + # tickCtr -> reset + grp.add_watch_point(dut, {"reset_us": is_reset_us}, name="ITTAGE Other Train Reset Useful Bit") + + # 更新最长表的时候,更新/不更新替代预测 + bins_update = {} + for update_alt in range(2): + s = ["update", "provider", "and", "alt"] if update_alt else ["only", "update", "provider"] + bins_update["_".join(s)] = is_update_table_as_provider(update_alt) + grp.add_watch_point(dut, bins_update, name="ITTAGE Other Train Update Entry") + + # 申请新表项成功/失败 + bins_alloc = {} + for success in range(2): + s = "succeed" if success else "fail" + bins_alloc["allocate_" + s] = is_allocate_succeed_or_fail(success) + grp.add_watch_point(dut, bins_alloc, name="ITTAGE Other Train Allocate Entry") + + return grp + + +def get_cov_grp_of_train_saturation(dut: DUTITTage) -> CovGroup: + grp = CovGroup(UT_FCOV("../UT_ITTage")) + + for up_or_down in range(2): + saturating_status = "up" if up_or_down else "down" + bins = {} + for i in range(5): + bins[f"T{i}_{saturating_status}_saturate"] = is_table_ctr_saturing(i, up_or_down) + grp.add_watch_point(dut, bins, name=f"ITTAGE Saturation Train {saturating_status} saturing") + + return grp + + +def get_cov_grp_of_us_train(dut: DUTITTage) -> CovGroup: + grp = CovGroup(UT_FCOV("../UT_ITTage")) + + bins_set = {} + bins_clr = {} + for i in range(5): + bins_set[f"T{i} us set"] = is_us_set_or_clear(1, i) + bins_clr[f"T{i} us clear"] = is_us_set_or_clear(0, i) + grp.add_watch_point(dut, bins_set, name="ITTAGE Us Train Tn us set") + grp.add_watch_point(dut, bins_clr, name="ITTAGE Us Train Tn us clear") + return grp \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/chk_pred.py b/ut_frontend/bpu/ittage/test/chk_pred.py new file mode 100644 index 0000000..e4290e0 --- /dev/null +++ b/ut_frontend/bpu/ittage/test/chk_pred.py @@ -0,0 +1,86 @@ +""" + Checkpoint for prediction +""" + +from dut.ITTage import DUTITTage + + +def is_hit_table_i(i: int): + def hit_table_i(dut: DUTITTage): + tn_hit = getattr(dut, f"ITTage_tables_{i}_io_resp_valid").value + return tn_hit + + return hit_table_i + + +def is_hit_multi_table(): + def hit_multi_table(dut: DUTITTage): + tn_hit = 0 + for i in range(5): + tn_hit += is_hit_table_i(i)(dut) + return tn_hit > 1 + + return hit_multi_table + + +def is_hit_no_table(): + def hit_no_table(dut: DUTITTage): + tn_hit = 0 + for i in range(5): + tn_hit += is_hit_table_i(i)(dut) + return tn_hit == 0 + + return hit_no_table + + +def is_alt_from_ftb(): + def alt_from_ftb(dut: DUTITTage): + provided = dut.ITTage_s3_provided.value + alt_provided = dut.ITTage_s3_altProvided.value + return alt_provided == 0 and provided == 0 + + return alt_from_ftb + + +def is_alt_from_table_i(i: int): + def alt_from_table_i(dut: DUTITTage): + alt_provided = dut.ITTage_s3_altProvided.value + alt_provider = dut.ITTage_s3_altProvider.value + return alt_provided and alt_provider == i + + return alt_from_table_i + + +# final prediction target +def is_src_from_main(): + def src_from_main(dut: DUTITTage): + provided = dut.ITTage_s3_provided.value + provider_ctr = dut.ITTage_s3_providerCtr.value + provider_target = dut.ITTage_s3_providerTarget.value + pred_target = dut.io_out_s3_full_pred_3_jalr_target.value + return provided > 0 and provider_ctr > 0 and provider_target == pred_target + + return src_from_main + + +def is_src_from_alt(): + def src_from_alt(dut: DUTITTage): + provided = dut.ITTage_s3_provided.value + provider_ctr = dut.ITTage_s3_providerCtr.value + alt_provided = dut.ITTage_s3_altProvided.value + alt_target = dut.ITTage_s3_altProviderTarget.value + pred_target = dut.io_out_s3_full_pred_3_jalr_target.value + return provided > 0 and provider_ctr == 0 and alt_provided > 0 and alt_target == pred_target + + return src_from_alt + + +def is_src_from_ftb(): + def src_from_ftb(dut: DUTITTage): + provided = dut.ITTage_s3_provided.value + alt_provided = dut.ITTage_s3_altProvided.value + ftb_target = dut.io_in_bits_resp_in_0_s2_full_pred_3_jalr_target.value + pred_target = dut.io_out_s3_full_pred_3_jalr_target.value + return provided == 0 and alt_provided == 0 and ftb_target == pred_target + + return src_from_ftb \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/chk_train.py b/ut_frontend/bpu/ittage/test/chk_train.py new file mode 100644 index 0000000..f9f96dc --- /dev/null +++ b/ut_frontend/bpu/ittage/test/chk_train.py @@ -0,0 +1,165 @@ +""" + Checkpoint for train +""" + +from toffee import CovGroup +from ..util.meta_parser import MetaParser + +from dut.ITTage import DUTITTage + + +def is_table_ctr_saturing(i: int, up_or_down: int): + sat_value = 0b11 if up_or_down else 0 + + def table_ctr_saturing(dut: DUTITTage): + alloc = getattr(dut, f"ITTage_tables_{i}_io_update_alloc").value + correct = getattr(dut, f"ITTage_tables_{i}_io_update_correct").value + valid = getattr(dut, f"ITTage_tables_{i}_io_update_valid").value and not alloc and up_or_down == correct + old_ctr = getattr(dut, f"ITTage_tables_{i}_io_update_oldCtr").value + new_ctr = getattr(dut, f"ITTage_tables_{i}_update_wdata_ctr").value + return valid and old_ctr == sat_value and new_ctr == sat_value + + return table_ctr_saturing + + +def is_update_provider(update_alt: int): + def update_provider(dut: DUTITTage): + valid = dut.io_update_valid.value and dut.ITTage_updateValid.value + provided = dut.ITTage_s3_provided.value + alt_provided = dut.ITTage_s3_altProvided.value + if valid and provided: + return update_alt == alt_provided + return False + + return update_provider + + +def is_update_table_as_provider(i: int): + def update_table_as_provider(dut: DUTITTage): + valid = dut.io_update_valid.value and dut.ITTage_updateValid.value + provided = dut.ITTage_s3_provided.value + provider = dut.ITTage_s3_provider.value + return valid and provided and (provider == i) + + return update_table_as_provider + + +def is_update_table_as_alt(i: int): + def update_table_as_alt(dut: DUTITTage): + valid = dut.io_update_valid.value and dut.ITTage_updateValid.value + alt_provided = dut.ITTage_s3_altProvided.value + alt_provider = dut.ITTage_s3_altProvider.value + return valid and alt_provided and (alt_provider == i) + + return update_table_as_alt + + +def is_reset_us(dut: DUTITTage): + valid = dut.io_update_valid.value + tick_ctr = dut.ITTage_tickCtr.value + reset = sum([getattr(dut, f"ITTage_tables_{i}_io_update_reset_u").value for i in range(5)]) + assert reset in {0, 5}, "Number of reset tables must be 5" + if valid and (reset == 5): + # assert tick_ctr == 0xff + return True + return False + + +def is_allocate_succeed_or_fail(success_or_fail: int): + def allocate_succeed_or_fail(dut: DUTITTage): + valid = dut.io_update_valid.value and dut.ITTage_updateValid.value + allocate_valid = MetaParser(dut.io_update_bits_meta.value).allocate_valid + return valid and (allocate_valid == success_or_fail) + + return allocate_succeed_or_fail + + +def is_us_set_or_clear(set_or_clear: int, i: int): + def us_set_or_clear(dut: DUTITTage): + meta_wrap = MetaParser(dut.io_update_bits_meta.value) + + altDiffer = meta_wrap.altDiffers + providerU = meta_wrap.providerU + provider = meta_wrap.provider + misPred = dut.io_update_bits_mispred_mask_2.value + + set_value = (not misPred) if altDiffer else providerU + + valid = dut.io_update_valid.value and meta_wrap.provided + + return valid and set_value == set_or_clear and provider == i + + return us_set_or_clear + + +def is_set_us_correct(dut: DUTITTage): + meta_parser = MetaParser(dut.io_update_bits_meta.value) + provided = meta_parser.provided + provider = meta_parser.provider + provider_ctr = meta_parser.providerCtr + provider_target = meta_parser.providerTarget + use_provider = provided and provider_ctr != 0 + real_target = dut.io_update_bits_full_target.value + provider_correct = provider_target == real_target + + valid = dut.io_update_valid.value and dut.ITTage_updateValid.value + set_us_true = (getattr(dut, f"ITTage_tables_{provider}_io_update_uValid").value and + getattr(dut, f"ITTage_tables_{provider}_io_update_u").value) + + if valid and set_us_true: + # 香山ITTAGE对于us置1的基本逻辑是,只要 + return use_provider and provider_correct + return False + + +def _get_cov_grp_of_pred(dut: DUTITTage) -> CovGroup: + grp = CovGroup("ITTAGE Train") + + # 第i个表计数器达到上/下饱和 + for i in range(5): + for up_or_down in range(2): + saturing_status = "up" if up_or_down else "down" + grp.add_watch_point( + dut, + {"_".join([f"table{i + 1}", saturing_status, "saturing"]): is_table_ctr_saturing(i, up_or_down)}, + name=" ".join([f"Table{i + 1}", "is", saturing_status.capitalize(), "Saturing"]), + ) + + for i in range(5): + # 第i个表被作为主预测更新 + grp.add_watch_point( + dut, + {"_".join([f"table{i + 1}", "update", "as", "provider"]): is_update_table_as_provider(i)}, + name=" ".join([f"Table{i + 1}", "Update", "as", "Provider"]), + ) + # 第i个表被作为替代预测更新 + grp.add_watch_point( + dut, + {"_".join([f"table{i + 1}", "update", "as", "alt"]): is_update_table_as_alt(i)}, + name=" ".join([f"Table{i + 1}", "Update", "as", "Alt"]), + ) + + # 更新最长表的时候,更新/不更新替代预测 + for update_alt in range(2): + s = ["update", "provider", "and", "alt"] if update_alt else ["only", "update", "provider"] + grp.add_watch_point( + dut, + {"_".join(s): is_update_table_as_provider(update_alt)}, + name=" ".join([x.capitalize() for x in s]) + ) + + # tickCtr达到最大值,触发重置useful位 + grp.add_watch_point(dut, {"reset_us": is_reset_us}, name="Reset Useful Bit") + + # 申请新表项成功/失败 + for success in range(2): + s = "succeed" if success else "fail" + grp.add_watch_point( + dut, + {"allocate_" + s: is_allocate_succeed_or_fail(success)}, + name="Allocate " + s.capitalize() + ) + # 在正确的条件下us被置为1 + grp.add_watch_point(dut, {"us_set_1": is_set_us_correct}, name="Provider us bit Set 1") + + return grp \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/test_alloc_train.py b/ut_frontend/bpu/ittage/test/test_alloc_train.py new file mode 100644 index 0000000..580a31c --- /dev/null +++ b/ut_frontend/bpu/ittage/test/test_alloc_train.py @@ -0,0 +1,73 @@ +""" + Test for allocate entry + Author: yzcc +""" + +import toffee_test + +from dut.ITTage import DUTITTage +from ..util.common import UpdateReq +from ..util.meta_parser import MetaParser + +from .chk_helper import get_cov_grp_of_other_train, get_cov_grp_of_us_train +from ..env.ittage_wrapper import ITTageWrapper + + +def test_alloc_train(ittage_wrapper: ITTageWrapper): + pins = ittage_wrapper + + # Start + pins.xclock.Step(1000) + + pc = 0x114514 + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + + meta_wrap.allocate_valid = 0 + meta_wrap.allocate_bits = 0 + + for i in range(1000): + req = UpdateReq(pc, meta_wrap.value, pred_target + 0x4, 0, 1) + pins.update(req.asdict()) + + # Check + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + assert meta_wrap.provided == 0 and meta_wrap.altProvided == 0 and pred_target == 0 + + fake_meta = MetaParser(0) + + # provider is unconfident and providing an incorrect target + fake_meta.provided = 1 + fake_meta.provider = 3 + fake_meta.providerCtr = 0 + fake_meta.providerTarget = 0x114514 + + # altProvider is unconfident and providing a correct target + fake_meta.altProvided = 1 + fake_meta.altProvider = 1 + fake_meta.altProviderCtr = 0 + # altDiffers = s3_finalAltPred != s3_tageTaken_dup(3) + # = Mux(altProvided, altProviderInfo.ctr(ITTageCtrBits-1), True) != True + fake_meta.altDiffers = 1 + fake_meta.altTargetCtr = 0x1919810 + + pins.update(UpdateReq(0x123, fake_meta.meta, 0x1919810, 1, 0).asdict()) + + assert not (pins.dut.ITTage_tables_3_io_update_valid.value + and pins.dut.ITTage_tables_3_io_update_u.value + and pins.dut.ITTage_tables_3_io_update_uValid.value), "provider shouldn't be set useful" + + +@toffee_test.fixture +async def ittage_wrapper(toffee_request: toffee_test.ToffeeRequest): + dut: DUTITTage = toffee_request.create_dut(DUTITTage, "clock") + wrapper = ITTageWrapper(dut) + toffee_request.add_cov_groups([ + get_cov_grp_of_other_train(dut), + get_cov_grp_of_us_train(dut) + ]) + + yield wrapper \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/test_alt_pred.py b/ut_frontend/bpu/ittage/test/test_alt_pred.py new file mode 100644 index 0000000..d9241f3 --- /dev/null +++ b/ut_frontend/bpu/ittage/test/test_alt_pred.py @@ -0,0 +1,74 @@ +""" + Test for alternative prediction + Author: yzcc +""" + +import toffee_test +from random import randint +from toffee import CovGroup + +from dut.ITTage import DUTITTage +from ..util.common import UpdateReq +from ..util.meta_parser import MetaParser + +from .chk_helper import get_cov_grp_of_alt_pred +from ..env.ittage_wrapper import ITTageWrapper + + +def test_alt_pred(ittage_wrapper: ITTageWrapper): + pins = ittage_wrapper + # Start + pins.xclock.Step(1000) + + # Test: use T1~T4 as alt_pred + for tab in range(4): + pc = tab * 4 + + # Alloc Longest + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + + meta_wrap.allocate_bits = 4 + req = UpdateReq(pc, meta_wrap.value, pred_target + randint(1, 0x114514), 0, 1) + pins.update(req.asdict()) + pins.xclock.Step(10) + + # Alloc Second Longest + meta_wrap.allocate_bits = tab + req = UpdateReq(pc, meta_wrap.value, pred_target + randint(1, 0x114514), 0, 1) + pins.update(req.asdict()) + pins.xclock.Step(10) + + # Set longest to unconfident + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + + meta_wrap.provided = 1 + meta_wrap.provider = 4 + meta_wrap.providerCtr = 0b01 + req = UpdateReq(pc, meta_wrap.value, pred_target + 0x1, 0, 1) + pins.update(req.asdict()) + pins.xclock.Step(10) + + pins.update(req.asdict()) + pins.xclock.Step(10) + + # Pred and Check + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + assert meta_wrap.altProvided == 1 and meta_wrap.providerCtr == 0, "should use alternative pred" + + pins.xclock.Step(100) + + +@toffee_test.fixture +async def ittage_wrapper(toffee_request: toffee_test.ToffeeRequest): + dut: DUTITTage = toffee_request.create_dut(DUTITTage, "clock") + wrapper = ITTageWrapper(dut) + toffee_request.add_cov_groups([ + get_cov_grp_of_alt_pred(dut) + ]) + + yield wrapper \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/test_main_pred.py b/ut_frontend/bpu/ittage/test/test_main_pred.py new file mode 100644 index 0000000..cd799e7 --- /dev/null +++ b/ut_frontend/bpu/ittage/test/test_main_pred.py @@ -0,0 +1,48 @@ +""" + Test the main prediction func + Author: yzcc +""" + +import asyncio +import toffee_test +from random import randint + +from dut.ITTage import DUTITTage +from ..util.common import UpdateReq +from ..util.meta_parser import MetaParser + +from .chk_helper import get_cov_grp_of_main_pred +from ..env.ittage_wrapper import ITTageWrapper + +@toffee_test.testcase +async def test_main_pred(ittage_wrapper: ITTageWrapper): + pins = ittage_wrapper + + # Start + pins.reset() + + for tab in range(5): + pc = tab + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + + meta_wrap.allocate_bits = tab + + req = UpdateReq(pc, meta_wrap.value, pred_target + randint(1, 0x114514), 0, 1) + pins.update(req.asdict()) + + # Check + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + assert meta_wrap.provided == 1 and meta_wrap.provider == tab, f"T{tab} should be hit" + +@toffee_test.fixture +async def ittage_wrapper(toffee_request: toffee_test.ToffeeRequest): + dut: DUTITTage = toffee_request.create_dut(DUTITTage, "clock") + wrapper = ITTageWrapper(dut) + toffee_request.add_cov_groups([ + get_cov_grp_of_main_pred(dut) + ]) + + yield wrapper diff --git a/ut_frontend/bpu/ittage/test/test_random.py b/ut_frontend/bpu/ittage/test/test_random.py new file mode 100644 index 0000000..3ebaa6b --- /dev/null +++ b/ut_frontend/bpu/ittage/test/test_random.py @@ -0,0 +1,52 @@ +""" + Random Test + Author: yzcc +""" + +import random + +import toffee_test +from toffee import CovGroup + +from dut.ITTage import DUTITTage +from ..util.common import UpdateReq + +from .chk_helper import get_cov_grp_of_main_pred, get_cov_grp_of_us_train, get_cov_grp_of_other_train +from ..env.ittage_wrapper import ITTageWrapper + + +def test_random(ittage_wrapper: ITTageWrapper): + pins = ittage_wrapper + + # Start Test + pins.reset() + + random.seed(19260817) + pc = 0x114514 + for ite in range(10000): + pc += random.randint(0, 0x3) * 2 + + # predict + dut_output = pins.predict(0, pc, True) + meta = dut_output["last_stage_meta"] + pred_target = dut_output["pred0"]["jalr_target"] + + # update + if random.randint(0, 1): + req = UpdateReq(pc, meta, pred_target, 0, 0) + else: + req = UpdateReq(pc, meta, pred_target + 0x1, 0, 1) + pins.update(req.asdict()) + + +@toffee_test.fixture +async def ittage_wrapper(toffee_request: toffee_test.ToffeeRequest): + dut: DUTITTage = toffee_request.create_dut(DUTITTage, "clock") + wrapper = ITTageWrapper(dut) + toffee_request.add_cov_groups([ + get_cov_grp_of_main_pred(dut), + get_cov_grp_of_us_train(dut), + get_cov_grp_of_other_train(dut) + ]) + + yield wrapper \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/test_reset.py b/ut_frontend/bpu/ittage/test/test_reset.py new file mode 100644 index 0000000..f47121d --- /dev/null +++ b/ut_frontend/bpu/ittage/test/test_reset.py @@ -0,0 +1,27 @@ +import toffee_test + +from toffee import CovGroup + +from dut.ITTage import DUTITTage +from .chk_helper import get_cov_grp_of_main_pred +from ..env.ittage_wrapper import ITTageWrapper + + +def test_reset(ittage_wrapper: ITTageWrapper): + pins = ittage_wrapper + + dut_output = pins.predict(0, 0x123, True) + + for i in range(4): + assert dut_output[f"pred{i}"]["jalr_target"] == 0 + + +@toffee_test.fixture +async def ittage_wrapper(toffee_request: toffee_test.ToffeeRequest): + dut: DUTITTage = toffee_request.create_dut(DUTITTage, "clock") + wrapper = ITTageWrapper(dut) + toffee_request.add_cov_groups([ + get_cov_grp_of_main_pred(dut), + ]) + + yield wrapper diff --git a/ut_frontend/bpu/ittage/test/test_saturation_train.py b/ut_frontend/bpu/ittage/test/test_saturation_train.py new file mode 100644 index 0000000..40b3435 --- /dev/null +++ b/ut_frontend/bpu/ittage/test/test_saturation_train.py @@ -0,0 +1,75 @@ +""" + Test the saturation of the training + Author: yzcc +""" + +import toffee_test + +from dut.ITTage import DUTITTage +from ..util.common import UpdateReq +from ..util.meta_parser import MetaParser + +from .chk_helper import get_cov_grp_of_train_saturation, get_cov_grp_of_other_train +from ..env.ittage_wrapper import ITTageWrapper + + +def test_saturation_train(ittage_wrapper: ITTageWrapper): + pins = ittage_wrapper + + # Start + pins.xclock.Step(1000) + + pc = None + for tab in range(5): + # Up Saturating + pc = tab + + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + + meta_wrap.provided = 1 + meta_wrap.provider = tab + meta_wrap.providerCtr = 0b11 # up bound + req = UpdateReq(pc, meta_wrap.value, pred_target, 0, 0) + pins.update(req.asdict()) + + pins.xclock.Step(10) + + # Check + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + assert meta_wrap.provided == 1 and meta_wrap.provider == tab and meta_wrap.providerCtr == 0b11, f"T{tab} up saturation fails" + + # Down Saturating + pc = tab + 47 + + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + + meta_wrap.allocate_valid = 0 + meta_wrap.provided = 1 + meta_wrap.provider = tab + meta_wrap.providerCtr = 0b00 + req = UpdateReq(pc, meta_wrap.value, pred_target + 1, 0, 1) + pins.update(req.asdict()) + + pins.xclock.Step(10) + + # Check + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + assert meta_wrap.provided == 1 and meta_wrap.provider == tab and meta_wrap.providerCtr == 0b00, f"T{tab} down saturation fails" + + +@toffee_test.fixture +async def ittage_wrapper(toffee_request: toffee_test.ToffeeRequest): + dut: DUTITTage = toffee_request.create_dut(DUTITTage, "clock") + wrapper = ITTageWrapper(dut) + toffee_request.add_cov_groups([ + get_cov_grp_of_train_saturation(dut), + get_cov_grp_of_other_train(dut), + ]) + + yield wrapper \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/test/test_src_pred.py b/ut_frontend/bpu/ittage/test/test_src_pred.py new file mode 100644 index 0000000..33b674b --- /dev/null +++ b/ut_frontend/bpu/ittage/test/test_src_pred.py @@ -0,0 +1,96 @@ +""" + Src of prediction from: + 1. Main prediction + 2. Alt prediction + 3. FTB prediction + Author: yzcc +""" + +import toffee_test +from toffee import CovGroup +from ..util.common import UpdateReq +from ..util.meta_parser import MetaParser + +from .chk_helper import get_cov_grp_of_other_pred +from ..env.ittage_wrapper import ITTageWrapper + +from dut.ITTage import DUTITTage + + +def test_src_pred(ittage_wrapper: ITTageWrapper): + pins = ittage_wrapper + + # Start + pins.xclock.Step(1000) + + pc = 0x0 + # Test: Use Main Pred - 2 + dut_output = pins.predict(0, pc, True) # get meta, alloc + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + + meta_wrap.allocate_bits = 4 # update + req = UpdateReq(pc, meta_wrap.value, 0x114514, 0, 1) + pins.update(req.asdict()) + pins.xclock.Step(10) + + dut_output = pins.predict(0, pc, True) + assert dut_output["pred0"]["jalr_target"] == 0x114514, "Target should from main prediction" + + # Test: Use Main Pred - 1 + fake_meta = MetaParser(0) + # except provider is unconfident + fake_meta.provided = 1 + fake_meta.provider = 3 + fake_meta.providerCtr = 0 + fake_meta.providerTarget = 0x1919810 + # except altProvider is invalid + fake_meta.altProvided = 0 + fake_meta.altProvidedCtr = 0x114514 + + pins.update(UpdateReq(0x123, fake_meta.meta, 0xFF000, 1, 1).asdict()) + pins.in_bundle.pred3.jalr_target.value = 0xF # T0 Target + pins.predict(1, 0x123) + dut_output = pins.out_bundle.as_dict() + assert dut_output['pred0']['jalr_target'] in {0xF, 0xFF000}, "Predict Target is not from known sources" + pins.in_bundle.pred3.jalr_target.value = 0 + + # Test: Use Alt Pred + # Alloc Second Longest + meta_wrap.allocate_bits = 1 + req = UpdateReq(pc, meta_wrap.value, 0x1919810, 0, 1) + pins.update(req.asdict()) + pins.xclock.Step(10) + + # Set longest to unconfident + dut_output = pins.predict(0, pc, True) + meta_wrap = MetaParser(dut_output["last_stage_meta"]) + pred_target = dut_output["pred0"]["jalr_target"] + + meta_wrap.provided = 1 + meta_wrap.provider = 4 + meta_wrap.providerCtr = 0b01 + req = UpdateReq(pc, meta_wrap.value, pred_target + 0x1, 0, 1) + pins.update(req.asdict()) + pins.xclock.Step(10) + + pins.update(req.asdict()) + pins.xclock.Step(10) + + dut_output = pins.predict(0, pc, True) + assert dut_output["pred0"]["jalr_target"] == 0x1919810, "Target should from alt prediction" + + # Test: Use FTB Prerd + pc = 0x114 + dut_output = pins.predict(0, pc, True) + assert dut_output["pred0"]["jalr_target"] == 0x0, "Target should from ftb" + + +@toffee_test.fixture +async def ittage_wrapper(toffee_request: toffee_test.ToffeeRequest): + dut: DUTITTage = toffee_request.create_dut(DUTITTage, "clock") + wrapper = ITTageWrapper(dut) + toffee_request.add_cov_groups([ + get_cov_grp_of_other_pred(dut) + ]) + + yield wrapper \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/util/__init__.py b/ut_frontend/bpu/ittage/util/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ut_frontend/bpu/ittage/util/common.py b/ut_frontend/bpu/ittage/util/common.py new file mode 100644 index 0000000..45cf9f5 --- /dev/null +++ b/ut_frontend/bpu/ittage/util/common.py @@ -0,0 +1,97 @@ +__all__ = ['gen_dummy_update_req', 'UpdateReq', 'get_folded_hist'] + +from ..env.global_history import GlobalHistory + + +def gen_dummy_update_req(pc, meta): + update_req = {} + update_req["valid"] = 1 + update_req["bits_pc"] = pc + + update_req["ftb_entry"] = {} + update_req["ftb_entry"]["tailSlot_offset"] = 0 + update_req["ftb_entry"]["tailSlot_sharing"] = 0 + update_req["ftb_entry"]["tailSlot_valid"] = 1 + update_req["ftb_entry"]["isRet"] = 0 + update_req["ftb_entry"]["isJalr"] = 1 + + update_req["cfi"] = {} + update_req["cfi"]["valid"] = 1 + update_req["cfi"]["bits"] = 0 + + update_req["bits_jmp_taken"] = 1 + update_req["bits_mispred_mask_2"] = 1 + update_req["bits_meta"] = meta + return update_req + + +def get_folded_hist(hist: int) -> dict: + ghv = GlobalHistory(hist) + return { + "hist_14_folded_hist": ghv.get_fh(8, 8), + "hist_13_folded_hist": ghv.get_fh(9, 13), + "hist_12_folded_hist": ghv.get_fh(4, 4), + "hist_10_folded_hist": ghv.get_fh(9, 32), + "hist_6_folded_hist": ghv.get_fh(9, 16), + "hist_4_folded_hist": ghv.get_fh(8, 13), + "hist_3_folded_hist": ghv.get_fh(8, 32), + "hist_2_folded_hist": ghv.get_fh(8, 16), + } + + +class FtbEntry: + def __init__(self): + self.tailSlot_offset = 0 + self.tailSlot_sharing = 0 + self.tailSlot_valid = 1 + self.isRet = 0 + self.isJalr = 1 + + +class CfiReq: + def __init__(self): + self.valid = 1 + self.bits = 0 + + +class UpdateReq: + def __init__(self, pc: int, meta: int, full_target: int, hist: int, mis_pred: int): + self.valid = 1 + self.bits_pc = pc + + self.ftb_entry = FtbEntry() + + self.cfi = CfiReq() + + self.bits_jmp_taken = 1 + self.bits_mispred_mask_2 = mis_pred + self.bits_meta = meta + self.hist = hist + + self.bits_full_target = full_target + + def asdict(self) -> dict: + update_req = {} + update_req["valid"] = self.valid + update_req["bits_pc"] = self.bits_pc + + update_req["ftb_entry"] = {} + update_req["ftb_entry"]["tailSlot_offset"] = self.ftb_entry.tailSlot_offset + update_req["ftb_entry"]["tailSlot_sharing"] = self.ftb_entry.tailSlot_sharing + update_req["ftb_entry"]["tailSlot_valid"] = self.ftb_entry.tailSlot_valid + update_req["ftb_entry"]["isRet"] = self.ftb_entry.isRet + update_req["ftb_entry"]["isJalr"] = self.ftb_entry.isJalr + + update_req["cfi"] = {} + update_req["cfi"]["valid"] = self.cfi.valid + update_req["cfi"]["bits"] = self.cfi.bits + + update_req["bits_jmp_taken"] = self.bits_jmp_taken + update_req["bits_mispred_mask_2"] = self.bits_mispred_mask_2 + update_req["bits_meta"] = self.bits_meta + update_req["bits_full_target"] = self.bits_full_target + + # update_req["folded_hist"] = get_folded_hist(self.hist) + update_req["bits_ghist"] = self.hist + + return update_req \ No newline at end of file diff --git a/ut_frontend/bpu/ittage/util/meta_parser.py b/ut_frontend/bpu/ittage/util/meta_parser.py new file mode 100644 index 0000000..6a8a94b --- /dev/null +++ b/ut_frontend/bpu/ittage/util/meta_parser.py @@ -0,0 +1,137 @@ +__all__ = ['MetaParser'] + +class MetaParser: + def __init__(self, meta: int) -> None: + self.value = meta + pass + + def bits(self, high, low): + assert low <= high + mask = (1 << (high + 1)) - 1 + return (self.value & mask) >> low + + def bit(self, bit): + return (self.value >> bit) & 1 + + @property + def meta(self) -> int: + return self.value + + @property + def provided(self) -> int: + return self.bit(117) + + @provided.setter + def provided(self, value: int): + mask = ~(1 << 117) + self.value = (self.value & mask) | (value << 117) + + @property + def provider(self): + """The provider property.""" + return self.bits(116, 114) + + @provider.setter + def provider(self, value): + mask = ~(0b111 << 114) + self.value = (self.value & mask) | (value << 114) + + @property + def altProvided(self): + """The altProvided property.""" + return self.bit(113) + + @altProvided.setter + def altProvided(self, value): + mask = ~(1 << 113) + self.value = (self.value & mask) | (value << 113) + + @property + def altProvider(self): + """The altProvider property.""" + return self.bits(112, 110) + + @altProvider.setter + def altProvider(self, value): + mask = ~(0b111 << 110) + self.value = (self.value & mask) | (value << 110) + + @property + def altDiffers(self): + """The altDiffers property.""" + return self.bit(109) + + @altDiffers.setter + def altDiffers(self, value): + mask = ~(1 << 109) + self.value = (self.value & mask) | (value << 109) + + @property + def providerU(self): + """The providerU property.""" + return self.bit(108) + + @providerU.setter + def providerU(self, value): + mask = ~(1 << 108) + self.value = (self.value & mask) | (value << 108) + + @property + def providerCtr(self): + """The providerCtr property.""" + return self.bits(107, 106) + + @providerCtr.setter + def providerCtr(self, value): + mask = ~(0b11 << 106) + self.value = (self.value & mask) | (value << 106) + + @property + def altProviderCtr(self): + """The altProviderCtr property.""" + return self.bits(105, 104) + + @altProviderCtr.setter + def altProviderCtr(self, value): + mask = ~(0b11 << 104) + self.value = (self.value & mask) | (value << 104) + + @property + def allocate_valid(self): + """The allocate_valid property.""" + return self.bit(103) + + @allocate_valid.setter + def allocate_valid(self, value): + mask = ~(1 << 103) + self.value = (self.value & mask) | (value << 103) + + @property + def allocate_bits(self): + """The allocate_bits property.""" + return self.bits(102, 100) + + @allocate_bits.setter + def allocate_bits(self, value): + mask = ~(0b111 << 100) + self.value = (self.value & mask) | (value << 100) + + @property + def providerTarget(self): + """The providerTarget property.""" + return self.bits(95, 50) + + @providerTarget.setter + def providerTarget(self, value): + mask = ~(0X3FFFFFFFFFFFF << 50) + self.value = (self.value & mask) | (value << 50) + + @property + def altProviderTarget(self): + """The altProviderTarget property.""" + return self.bits(49, 0) + + @altProviderTarget.setter + def altProviderTarget(self, value): + mask = ~(0X3FFFFFFFFFFFF << 0) + self.value = (self.value & mask) | (value << 0)