diff --git a/ut_frontend/bpu/tagesc/bundle/__init__.py b/ut_frontend/bpu/tagesc/bundle/__init__.py index d82ccab..d4a4e2a 100644 --- a/ut_frontend/bpu/tagesc/bundle/__init__.py +++ b/ut_frontend/bpu/tagesc/bundle/__init__.py @@ -1,60 +1,2 @@ -from toffee import Bundle, Signal, Signals - -__all__ = ["BranchPredictReq", "BranchPredictionResp", "UpdateBundle", "CtrlBundle", "PipelineBundle"] - - -class CtrlBundle(Bundle): - tage_enable, sc_enable = Signals(2) - - -class PipelineBundle(Bundle): - # 0->BPU, 1->Tage, 3->SC - s0_fire_0, s1_fire_0, s2_fire_0 = Signals(3) - s0_fire_1, s1_fire_1, s2_fire_1 = Signals(3) - s0_fire_2, s1_fire_2, s2_fire_2 = Signals(3) - s0_fire_3, s1_fire_3, s2_fire_3 = Signals(3) - - -class FoldedHistoryBundle(Bundle): - [hist_0_folded_hist, hist_1_folded_hist, hist_2_folded_hist, hist_3_folded_hist, - hist_4_folded_hist, hist_5_folded_hist, hist_6_folded_hist, hist_7_folded_hist, - hist_8_folded_hist, hist_9_folded_hist, hist_10_folded_hist, hist_11_folded_hist, - hist_12_folded_hist, hist_13_folded_hist, hist_14_folded_hist, hist_15_folded_hist, - hist_16_folded_hist, hist_17_folded_hist] = Signals(18) - - -class FTBSlotBundle(Bundle): - valid, sharing = Signals(2) - - -class FTBEntryBundle(Bundle): - always_taken_0, always_taken_1 = Signals(2) - br_slot = FTBSlotBundle.from_prefix("brSlots_0_") - tail_slot = FTBSlotBundle.from_prefix("tailSlot_") - - -class BranchPredictionBundle(Bundle): - br_taken_mask_0, br_taken_mask_1 = Signals(2) - - -class BranchPredictReq(Bundle): - bits_s0_pc_0, bits_s0_pc_1, bits_s0_pc_2, bits_s0_pc_3 = Signals(4) - fh_tage = FoldedHistoryBundle.from_prefix("bits_folded_hist_1_") - fh_sc = FoldedHistoryBundle.from_prefix("bits_folded_hist_3_") - - -class BranchPredictionResp(Bundle): - last_stage_meta = Signal() - s2 = BranchPredictionBundle.from_prefix(r"s2_full_pred_3_") - s3 = BranchPredictionBundle.from_prefix(r"s3_full_pred_3_") - - -class BranchPredictionUpdate(Bundle): - pc, meta, br_taken_mask_0, br_taken_mask_1, mispred_mask_0, mispred_mask_1 = Signals(6) - ghist = Signal() - ftb_entry = FTBEntryBundle.from_prefix("ftb_entry_") - - -class UpdateBundle(Bundle): - valid = Signal() - bits = BranchPredictionUpdate.from_prefix("bits_") +from .port import * +from .internal import * \ No newline at end of file diff --git a/ut_frontend/bpu/tagesc/test/checkpoints_tage_predict.py b/ut_frontend/bpu/tagesc/test/checkpoints_tage_predict.py index e05cd35..cfcae54 100644 --- a/ut_frontend/bpu/tagesc/test/checkpoints_tage_predict.py +++ b/ut_frontend/bpu/tagesc/test/checkpoints_tage_predict.py @@ -1,118 +1,104 @@ +__all__ = ["get_coverage_group_of_tage_predict"] + from toffee.funcov import CovGroup from comm import UT_FCOV -from dut.Tage_SC import DUTTage_SC -__all__ = ["get_coverage_group_of_tage_predict"] + + +from ut_frontend.bpu.tagesc.bundle.internal import StatusBundle def is_ti_provider(way: int, ti: int): - def ti_provider(dut: DUTTage_SC) -> bool: - provided = getattr(dut, f"Tage_SC_s2_provideds_{way}").value - provider = getattr(dut, f"Tage_SC_s2_providers_{way}").value - return dut.io_s1_ready.value and dut.io_s2_fire_1.value and provided and provider == ti - + def ti_provider(status: StatusBundle) -> bool: + s2_internal = status.internal.s2 + return status.s2_valid(1) and s2_internal.provided(way) and s2_internal.provider(way) == ti return ti_provider def is_hit_no_table(way: int): - def hit_no_table(dut: DUTTage_SC) -> bool: - provided = getattr(dut, f"Tage_SC_s2_provideds_{way}").value - return dut.io_s1_ready.value != 0 and dut.io_s2_fire_1.value != 0 and provided == 0 - + def hit_no_table(status: StatusBundle) -> bool: + s2_internal = status.internal.s2 + return status.s2_valid(1) and (not s2_internal.provided(way)) return hit_no_table -def is_all_slots_the_same_provider(dut: DUTTage_SC) -> bool: - provided_0 = dut.Tage_SC_s2_provideds_0.value - provided_1 = dut.Tage_SC_s2_provideds_1.value - valid = provided_0 and provided_1 - provider_0 = dut.Tage_SC_s2_providers_0.value - provider_1 = dut.Tage_SC_s2_providers_1.value - return dut.io_s1_ready.value and dut.io_s2_fire_1.value and valid and provider_0 == provider_1 +def is_all_slots_the_same_provider(status: StatusBundle) -> bool: + valid = all(status.internal.s2.provided(w) for w in range(2)) + provider = status.internal.s2.provider + return status.s2_valid(1) and valid and provider(0) == provider(1) def is_hit_multiple_tables(way: int): - def hit_multiple_tables(dut: DUTTage_SC) -> bool: - provided = getattr(dut, f"Tage_SC_s2_provideds_{way}").value - count = sum([getattr(dut, f"Tage_SC_tables_{i}_io_resps_{way}_valid").value for i in range(4)]) - return dut.io_s1_ready.value and dut.io_s2_fire_1.value and provided and count > 1 - + def hit_multiple_tables(status: StatusBundle) -> bool: + provided = status.internal.s2.provided(way) + count = status.internal.tage_table.hit_count(way) + return status.s2_valid(1) and provided and count > 1 return hit_multiple_tables def is_ti_unconf_provider(way: int, t_i: int, use_alt: int): - def ti_unconf_provider(dut: DUTTage_SC) -> bool: - provided = getattr(dut, f"Tage_SC_s2_provideds_{way}").value - provider = getattr(dut, f"Tage_SC_s2_providers_{way}").value - unconfident = getattr(dut, f"Tage_SC_s2_providerResps_{way}_ctr").value in {0b011, 0b100} - alt_used = getattr(dut, f"Tage_SC_s2_altUsed_{way}").value - return (dut.io_s1_ready.value and dut.io_s2_fire_1.value and provided and provider == t_i - and unconfident and alt_used == use_alt) - + def ti_unconf_provider(status: StatusBundle) -> bool: + provided = status.internal.s2.provided(way) + provider = status.internal.s2.provider(way) + unconfident = status.internal.s2.provider_weak(way) + alt_used = status.internal.s2.alt_used(way) + return status.s2_valid(1) and provided and provider == t_i and unconfident and alt_used == use_alt return ti_unconf_provider def is_provider_unconf_and_multiple_hit(way: int, use_alt: int): - def provider_unconf_and_multiple_hit(dut: DUTTage_SC) -> bool: - provided = getattr(dut, f"Tage_SC_s2_provideds_{way}").value - # provider = getattr(dut, f"Tage_SC_s2_providers_{way}") - unconfident = getattr(dut, f"Tage_SC_s2_providerResps_{way}_ctr").value in {0b011, 0b100} - alt_used = getattr(dut, f"Tage_SC_s2_altUsed_{way}").value - count = sum([getattr(dut, f"Tage_SC_tables_{i}_io_resps_{way}_valid").value for i in range(4)]) - return (dut.io_s1_ready.value and dut.io_s2_fire_1.value and provided and count > 0 - and unconfident and alt_used == use_alt) - + def provider_unconf_and_multiple_hit(status: StatusBundle) -> bool: + provided = status.internal.s2.provided(way) + unconfident = status.internal.s2.provider_weak(way) + alt_used = status.internal.s2.alt_used(way) + count = status.internal.tage_table.hit_count(way) + return status.s2_valid(1) and provided and count > 1 and unconfident and alt_used == use_alt return provider_unconf_and_multiple_hit def is_all_slots_use_same_unconf_provider_and_both(use_alt: int): - def all_slots_use_same_unconf_provider(dut: DUTTage_SC) -> bool: - provided_0 = dut.Tage_SC_s2_provideds_0.value - provided_1 = dut.Tage_SC_s2_provideds_1.value - provider_0 = dut.Tage_SC_s2_providers_0.value - provider_1 = dut.Tage_SC_s2_providers_1.value - alt_used_0 = dut.Tage_SC_s2_altUsed_0.value - alt_used_1 = dut.Tage_SC_s2_altUsed_1.value - valid = provided_0 and provided_1 and alt_used_0 and alt_used_1 - return dut.io_s1_ready.value and dut.io_s2_fire_1.value and valid and (provider_0 == provider_1) - + def all_slots_use_same_unconf_provider(status: StatusBundle) -> bool: + s2 = status.internal.s2 + provider = s2.provider + valid = all([s2.provided(w) and s2.alt_used(w) for w in range(2)]) + return status.s2_valid(1) and valid and (provider(0) == provider(1)) return all_slots_use_same_unconf_provider -def get_coverage_group_of_tage_predict(dut: DUTTage_SC) -> CovGroup: +def get_coverage_group_of_tage_predict(status: StatusBundle) -> CovGroup: slot_name = ["br_slot_0", "tail_slot"] group = CovGroup(UT_FCOV("../UT_Tage_SC")) # Tn is provider - group.add_watch_point(dut, { + group.add_watch_point(status, { "_".join([f"T{i}", "provider", slot_name[w]]): is_ti_provider(w, i) for i in range(4) for w in range(2) }, name="Tn is Provider") - group.add_watch_point(dut, { + group.add_watch_point(status, { "_".join([slot_name[w], "miss"]): is_hit_no_table(w) for w in range(2) }, name="All Tn Miss") # Multi tables hit - group.add_watch_point(dut, { + group.add_watch_point(status, { slot_name[w]: is_hit_multiple_tables(w) for w in range(2) }, name="Multi Tables Hit") # All slots miss all tables group.add_watch_point( - dut, {"no_slot_hits": is_hit_no_table(w) for w in range(2)}, name="No Slot Hits" + status, {"no_slot_hits": is_hit_no_table(w) for w in range(2)}, name="No Slot Hits" ) # All slots are the same provider group.add_watch_point( - dut, {"same_provider": is_all_slots_the_same_provider}, + status, {"same_provider": is_all_slots_the_same_provider}, name="All Slots use the Same Provider" ) # Tn is unconfident provider and use/doesn't use alt alt_use_str = ["NOT use_alt", "use_alt"] for use_alt in range(2): group.add_watch_point( - dut, + status, {slot_name[w]: is_ti_unconf_provider(w, i, use_alt) for i in range(4) for w in range(2)}, name=" ".join(["Tn is Unconfident Provider and ", alt_use_str[use_alt]]), ) @@ -120,7 +106,7 @@ def get_coverage_group_of_tage_predict(dut: DUTTage_SC) -> CovGroup: for use_alt in range(2): point_name = f"Multiple Tables Hit&Provider is Unconf and {alt_use_str[use_alt]}" group.add_watch_point( - dut, + status, {slot_name[w]: is_provider_unconf_and_multiple_hit(w, use_alt) for w in range(2)}, name=point_name ) @@ -129,7 +115,7 @@ def get_coverage_group_of_tage_predict(dut: DUTTage_SC) -> CovGroup: for use_alt in range(2): point_name = f"All Slots Use the Same Unconfident Provider and {alt_use_str[use_alt]}" group.add_watch_point( - dut, + status, {"valid": is_all_slots_use_same_unconf_provider_and_both(use_alt)}, name=point_name ) diff --git a/ut_frontend/bpu/tagesc/test/checkpoints_tage_train.py b/ut_frontend/bpu/tagesc/test/checkpoints_tage_train.py index e579562..1059bb2 100644 --- a/ut_frontend/bpu/tagesc/test/checkpoints_tage_train.py +++ b/ut_frontend/bpu/tagesc/test/checkpoints_tage_train.py @@ -1,11 +1,11 @@ +__all__ = ["get_coverage_group_of_tage_train"] + from toffee.funcov import CovGroup from comm import UT_FCOV -from dut.Tage_SC import DUTTage_SC +from ..bundle.internal import StatusBundle from ..util.meta_parser import MetaParser -__all__ = ["get_coverage_group_of_tage_train"] - slot_name = ["br_slot_0", "tail_slot"] @@ -14,112 +14,101 @@ def get_idx(pc: int, way: int): def is_update_t0_saturing_ctr(way: int, up_or_down: int): - def update_t0_saturing(dut: DUTTage_SC) -> bool: + def update_t0_saturing(status: StatusBundle) -> bool: v = 0b11 if up_or_down else 0 - w_idx = get_idx(dut.io_update_bits_pc.value, way) - valid = dut.io_s1_ready.value and dut.Tage_SC_bt_bt_io_w_req_valid.value \ - and ((dut.Tage_SC_bt_bt_io_w_req_bits_waymask.value >> w_idx) & 1) - old_ctr = getattr(dut, f"Tage_SC_bt_oldCtrs_{way}").value - new_ctr = getattr(dut, f"Tage_SC_bt_newCtrs_{way}").value - taken = getattr(dut, f"Tage_SC_bt_io_update_takens_{w_idx}").value - return valid and new_ctr == v and old_ctr == v and (taken == up_or_down) - + pc = status.update.bits.pc.value + base_table = status.internal.base_table + valid = status.pipline.s1_ready.value and base_table.write_valid() \ + and base_table.write_mask(pc, way) + old_ctr = base_table.old_ctr(way) + new_ctr = base_table.new_ctr(way) + update_taken = base_table.update_taken(pc, way) + return valid and new_ctr == v and old_ctr == v and (update_taken == up_or_down) return update_t0_saturing -def is_update_tn_saturing_ctr(way: int, t_i: int, up_or_down: int): - def update_tn_saturing(dut: DUTTage_SC) -> bool: - for b in range(4): - silent = getattr(dut, f"Tage_SC_tables_{t_i}_per_bank_not_silent_update_{b}_{way}").value == 0 - - w_idx = get_idx(dut.io_update_bits_pc.value, way) - update_mask = getattr(dut, f"Tage_SC_tables_{t_i}_io_update_mask_{w_idx}").value != 0 - valid = dut.io_s1_ready.value and update_mask - taken = getattr(dut, f"Tage_SC_tables_{t_i}_io_update_takens_{w_idx}").value - if valid and silent and (taken == up_or_down): - return True - return False - +def is_update_tn_saturing_ctr(way: int, ti: int, up_or_down: int): + def update_tn_saturing(status: StatusBundle) -> bool: + pc = status.update.bits.pc.value + tage_table = status.internal.tage_table + has_silent = tage_table.has_silent(ti, way) + mask = tage_table.get_table(ti).update_mask(pc, way) + valid = status.pipline.s1_ready.value and mask + taken = tage_table.get_table(ti).update_taken(pc, way) + return valid and has_silent and (taken == up_or_down) return update_tn_saturing def is_allocate_new_entry(way: int, except_success_or_failure: int): - """ - #WARNING: 目前的判断逻辑还是按照Chisel代码进行的, 所以可用表项信息失效的bug依旧存在. - """ - need_to_allocates = ["Tage_SC_needToAllocate", "Tage_SC_needToAllocate_1"] - - def allocate_new_entry(dut: DUTTage_SC) -> bool: - valid = getattr(dut, f"Tage_SC_updateValids_{way}").value and dut.io_update_valid.value - need_to_allocate = getattr(dut, need_to_allocates[way]).value - with MetaParser(dut.io_update_bits_meta.value) as meta_parser: + # WARNING: 目前的判断逻辑还是按照Chisel代码进行的, 所以可用表项信息失效的bug依旧存在. + def allocate_new_entry(status: StatusBundle) -> bool: + valid = status.internal.update.valid(way) and status.update.valid.value and status.pipline.s1_ready.value + need_to_allocate = status.internal.need_to_allocate(way) + with MetaParser(status.update.bits.meta.value) as meta_parser: allocatable_count = sum([x.value for x in meta_parser.allocates]) - return dut.io_s1_ready.value and valid and need_to_allocate \ + return valid and need_to_allocate \ and ((allocatable_count > 0) if except_success_or_failure else (allocatable_count == 0)) return allocate_new_entry def is_allocate_as_provider_predict_incorrectly(way: int): - def allocate_as_provider(dut: DUTTage_SC) -> bool: - with MetaParser(dut.io_update_bits_meta.value) as meta_parser: - incorrect = getattr(dut, "Tage_SC_updateProviderCorrect" + ("_1" if way else "")).value == 0 - valid = dut.io_s1_ready.value and dut.io_update_valid.value and meta_parser.providers_valid[ - way].value and incorrect + def allocate_as_provider(status: StatusBundle) -> bool: + with MetaParser(status.update.bits.meta.value) as meta_parser: + incorrect = not status.internal.update.provider_correct(way) + valid = status.pipline.s1_ready.value and status.update.valid.value \ + and meta_parser.providers_valid[way].value and incorrect return valid - return allocate_as_provider def is_update_predict_from_tagged(way: int): - def update_predict_from_tagged(dut: DUTTage_SC) -> bool: - with MetaParser(dut.io_update_bits_meta.value) as meta_parser: - valid = getattr(dut, f"Tage_SC_updateValids_{way}").value and dut.io_update_valid.value + def update_predict_from_tagged(status: StatusBundle) -> bool: + with MetaParser(status.update.bits.meta.value) as meta_parser: + valid = status.internal.update.valid(way) and status.update.valid.value provided = meta_parser.providers_valid[way].value alt_used = meta_parser.altUsed[way].value return valid and provided and not alt_used - return update_predict_from_tagged def is_update_use_alt_on_na_ctrs(way: int): - def update_use_alt_on_na_ctrs(dut: DUTTage_SC) -> bool: - with MetaParser(dut.io_update_bits_meta.value) as meta_parser: - valid = getattr(dut, f"Tage_SC_updateValids_{way}").value and dut.io_s1_ready.value + def update_use_alt_on_na_ctrs(status: StatusBundle) -> bool: + with MetaParser(status.update.bits.meta.value) as meta_parser: + valid = status.internal.update.valid(way) and status.update.valid.value provided = meta_parser.providers_valid[way].value weak = meta_parser.providerResps_ctr[way].value in {0b100, 0b011} alt_diff = (meta_parser.basecnts[way].value >= 0b10) != (meta_parser.providerResps_ctr[way].value >= 0b100) return valid and provided and weak and alt_diff - return update_use_alt_on_na_ctrs def is_reset_us(way: int): - def reset_us(dut: DUTTage_SC) -> bool: - valid = dut.io_s1_ready.value != 0 - bank_tick_ctr = getattr(dut, f"Tage_SC_bankTickCtrs_{way}").value - reset_u = getattr(dut, f"Tage_SC_updateResetU_{way}").value != 0 + def reset_us(status: StatusBundle) -> bool: + valid = status.pipline.s1_ready.value + bank_tick_ctr = status.internal.bank_tick_ctr(way) + reset_u = status.internal.update.reset_u(way) return valid and reset_u and bank_tick_ctr == 0x7f return reset_us def is_update_always_taken(way: int): - def update_always_taken(dut: DUTTage_SC) -> bool: - always_taken = getattr(dut, f"io_update_bits_ftb_entry_always_taken_{way}").value != 0 - return dut.io_s1_ready.value != 0 and dut.io_update_valid.value != 0 and always_taken - + def update_always_taken(status: StatusBundle) -> bool: + always_taken = getattr(status.update.bits.ftb_entry, f"always_taken_{way}").value + valid = status.pipline.s1_ready.value and status.update.valid.value + return valid and always_taken return update_always_taken -def get_coverage_group_of_tage_train(dut: DUTTage_SC) -> CovGroup: +def get_coverage_group_of_tage_train(status: StatusBundle) -> CovGroup: g = CovGroup(UT_FCOV("../UT_Tage_SC")) # T0 up/down saturing update for up_or_down in range(2): s = "up saturing" if up_or_down else "down saturing" g.add_watch_point( - dut, + status, {slot_name[w]: is_update_t0_saturing_ctr(w, up_or_down) for w in range(2)}, name=" ".join(["T0", s.capitalize()]) ) @@ -127,7 +116,7 @@ def get_coverage_group_of_tage_train(dut: DUTTage_SC) -> CovGroup: for up_or_down in range(2): s = "up saturing" if up_or_down else "down saturing" g.add_watch_point( - dut, + status, {"_".join([f"T{i}", slot_name[w]]): is_update_tn_saturing_ctr(w, i, up_or_down) for i in range(4) for w in range(2)}, name=" ".join(["Tn", s.capitalize()]) @@ -146,27 +135,26 @@ def get_coverage_group_of_tage_train(dut: DUTTage_SC) -> CovGroup: alloc_as_provider_mis_pred[f"{slot_name[w]} provider incorrect"] \ = is_allocate_as_provider_predict_incorrectly(w) - g.add_watch_point(dut, alloc, name="Tn Allocate " + cond) - g.add_watch_point(dut, alloc_as_provider_mis_pred, name="Tn Allocate As Provider MisPredict " + cond) + g.add_watch_point(status, alloc, name="Tn Allocate " + cond) + g.add_watch_point(status, alloc_as_provider_mis_pred, name="Tn Allocate As Provider MisPredict " + cond) # Reset useful counter - g.add_watch_point(dut, {slot_name[w]: is_reset_us(w) for w in range(2)}, name="Reset us") + g.add_watch_point(status, {slot_name[w]: is_reset_us(w) for w in range(2)}, name="Reset us") # Train Information's `always_taken` Bit is True - g.add_watch_point(dut, {slot_name[w]: is_update_always_taken(w) for w in range(2)}, name="Always Taken is True") - + g.add_watch_point(status, {slot_name[w]: is_update_always_taken(w) for w in range(2)}, name="Always Taken is True") g.add_watch_point( - dut, + status, { - slot_name[0]: lambda d: d.Tage_SC_updateValids_0.value and d.io_s0_fire_1.value, - slot_name[1]: lambda d: d.Tage_SC_updateValids_1.value and d.io_s0_fire_1.value, + slot_name[0]: lambda d: d.internal.update.valid(0) and d.pipline.s0_fire_1.value, + slot_name[1]: lambda d: d.internal.update.valid(1) and d.pipline.s0_fire_1.value, }, name="Update When Predict" ) # useAltOnNaCtrs update g.add_watch_point( - dut, + status, {"_".join([slot_name[w], "useAltOnNaCtrs", "update"]): is_update_use_alt_on_na_ctrs(w) for w in range(2)}, name="Update useAltOnNaCtrs" ) diff --git a/ut_frontend/bpu/tagesc/test/test_random.py b/ut_frontend/bpu/tagesc/test/test_random.py index 6cfade5..0d51455 100644 --- a/ut_frontend/bpu/tagesc/test/test_random.py +++ b/ut_frontend/bpu/tagesc/test/test_random.py @@ -8,6 +8,7 @@ from dut.Tage_SC import DUTTage_SC from .checkpoints_sc_predict import get_coverage_group_of_sc_predict from .checkpoints_tage_predict import get_coverage_group_of_tage_predict from .checkpoints_tage_train import get_coverage_group_of_tage_train +from ..bundle.internal import StatusBundle from ..env.fake_global_history import TageSCFakeGlobalHistory from ..env.tage_sc_env import TageSCEnv @@ -37,9 +38,10 @@ async def test_random(tage_sc_env: TageSCEnv, pc_bound: int): async def tage_sc_env(toffee_request: toffee_test.ToffeeRequest): import asyncio dut = toffee_request.create_dut(DUTTage_SC, "clock") + status = StatusBundle.from_prefix("").bind(dut) toffee_request.add_cov_groups([ - get_coverage_group_of_tage_predict(dut), - get_coverage_group_of_tage_train(dut), + get_coverage_group_of_tage_predict(status), + get_coverage_group_of_tage_train(status), get_coverage_group_of_sc_predict(dut), ]) toffee.start_clock(dut) diff --git a/ut_frontend/bpu/tagesc/test/test_spec_case.py b/ut_frontend/bpu/tagesc/test/test_spec_case.py index 059cc50..a11352f 100644 --- a/ut_frontend/bpu/tagesc/test/test_spec_case.py +++ b/ut_frontend/bpu/tagesc/test/test_spec_case.py @@ -6,15 +6,16 @@ from .checkpoints_sc_predict import get_coverage_group_of_sc_predict from .checkpoints_sc_train import get_coverage_group_of_sc_train from .checkpoints_tage_predict import get_coverage_group_of_tage_predict from .checkpoints_tage_train import get_coverage_group_of_tage_train +from ..bundle.internal import StatusBundle from ..env.tage_sc_env import TageSCEnv from ..util.meta_parser import MetaParser @toffee_test.testcase -async def test_tage_tn_saturing_ctr_update(tage_sc_dut: DUTTage_SC): - env = TageSCEnv(tage_sc_dut) +async def test_tage_tn_saturing_ctr_update(test_env: TageSCEnv): + env = test_env await env.reset_dut() - await tage_sc_dut.AStep(1) + await test_env.__dut__.AStep(1) pc = 0x80000002 with MetaParser(0) as parser: for x in parser.providers_valid: @@ -28,7 +29,7 @@ async def test_tage_tn_saturing_ctr_update(tage_sc_dut: DUTTage_SC): x.value = ti await env.train_agent.exec_update(pc, 1, 1, 1, parser.value, 0, 0, 0, 1, 1, 0, 0) for w in range(2): - assert getattr(tage_sc_dut, f"Tage_SC_tables_{ti}_per_bank_update_wdata_0_{w}_ctr").value == 0, \ + assert getattr(test_env.__dut__, f"Tage_SC_tables_{ti}_per_bank_update_wdata_0_{w}_ctr").value == 0, \ f"TageTable{ti} down saturation-update failed!" # ctr up saturing @@ -40,21 +41,21 @@ async def test_tage_tn_saturing_ctr_update(tage_sc_dut: DUTTage_SC): for x in parser.providers: x.value = ti await env.train_agent.exec_update(pc, w, 1, 1, parser.value, 0, w, 1, 1, 1, 0, 0) - assert getattr(tage_sc_dut, f"Tage_SC_tables_{ti}_per_bank_update_wdata_0_{w}_ctr").value == 0b111, \ + assert getattr(test_env.__dut__, f"Tage_SC_tables_{ti}_per_bank_update_wdata_0_{w}_ctr").value == 0b111, \ f"TageTable{ti} up saturation-update failed!" @toffee_test.testcase -async def test_bank_tick_ctrs(tage_sc_dut: DUTTage_SC): - env = TageSCEnv(tage_sc_dut) +async def test_bank_tick_ctrs(test_env: TageSCEnv): + env = test_env async def expect_reset_u(way: int): - await tage_sc_dut.AStep(1) - assert getattr(tage_sc_dut, f"Tage_SC_updateResetU_{way}").value == 1, "ResetU should be high!" + await test_env.__dut__.AStep(1) + assert getattr(test_env.__dut__, f"Tage_SC_updateResetU_{way}").value == 1, "ResetU should be high!" ##### Test Code Start ##### await env.reset_dut() - await tage_sc_dut.AStep(1) + await test_env.__dut__.AStep(1) pc = 0x80000002 with MetaParser(0) as parser: for x in parser.allocates: @@ -75,13 +76,13 @@ async def test_bank_tick_ctrs(tage_sc_dut: DUTTage_SC): x.value = 0xf for w in range(2): await env.train_agent.exec_update(pc, w, 1, 1, parser.value, 2, w, 1, 1, 1, 0, 0) - bank_tick_ctrs = [getattr(tage_sc_dut, f"Tage_SC_bankTickCtrs_{w}").value for w in range(2)] + bank_tick_ctrs = [getattr(test_env.__dut__, f"Tage_SC_bankTickCtrs_{w}").value for w in range(2)] assert sum(bank_tick_ctrs) == 0, "BankTickCtrs is not down saturation update" @toffee_test.testcase -async def test_tage_alt_predict_keep_true_and_false(tage_sc_dut: DUTTage_SC): - env = TageSCEnv(tage_sc_dut) +async def test_tage_alt_predict_keep_true_and_false(test_env: TageSCEnv): + env = test_env await env.reset_dut() # Alt prediction is false, provider is true with MetaParser(0) as parser: @@ -100,7 +101,7 @@ async def test_tage_alt_predict_keep_true_and_false(tage_sc_dut: DUTTage_SC): await env.train_agent.exec_update(i * 2, 1, 1, 1, parser.value, 0, 0, 0, 1, 1, 0, 0) for w in range(2): for i in range(128): - ctr_val = getattr(tage_sc_dut, f"Tage_SC_useAltOnNaCtrs_{w}_{i}").value + ctr_val = getattr(test_env.__dut__, f"Tage_SC_useAltOnNaCtrs_{w}_{i}").value assert ctr_val == 0xf, f"useAltOnNaCtrs_{w}_{i} should be 0xf!" # Alt prediction is true, provider is false for x in parser.basecnts: @@ -112,17 +113,17 @@ async def test_tage_alt_predict_keep_true_and_false(tage_sc_dut: DUTTage_SC): await env.train_agent.exec_update(i * 2, 1, 1, 1, parser.value, 0, 0, 0, 1, 1, 0, 0) for w in range(2): for i in range(128): - ctr_val = getattr(tage_sc_dut, f"Tage_SC_useAltOnNaCtrs_{w}_{i}").value + ctr_val = getattr(test_env.__dut__, f"Tage_SC_useAltOnNaCtrs_{w}_{i}").value assert ctr_val == 0, f"useAltOnNaCtrs_{w}_{i} should be 0!" @toffee_test.testcase -async def test_sc_threshold_saturation_update(tage_sc_dut: DUTTage_SC): - env = TageSCEnv(tage_sc_dut) +async def test_sc_threshold_saturation_update(test_env: TageSCEnv): + env = test_env await env.reset_dut() pc = 0x80000004 - ctrs = [getattr(tage_sc_dut, f"Tage_SC_scThresholds_{i}_ctr") for i in range(2)] - thresholds = [getattr(tage_sc_dut, f"Tage_SC_scThresholds_{i}_thres") for i in range(2)] + ctrs = [getattr(test_env.__dut__, f"Tage_SC_scThresholds_{i}_ctr") for i in range(2)] + thresholds = [getattr(test_env.__dut__, f"Tage_SC_scThresholds_{i}_thres") for i in range(2)] with MetaParser(0) as parser: for x in parser.sc_ctrs: for y in x[1:]: @@ -170,8 +171,8 @@ async def test_sc_threshold_saturation_update(tage_sc_dut: DUTTage_SC): @toffee_test.testcase -async def test_sc_table_saturation(tage_sc_dut: DUTTage_SC): - env = TageSCEnv(tage_sc_dut) +async def test_sc_table_saturation(test_env: TageSCEnv): + env = test_env await env.reset_dut() pc = 0x1919810 # SC Table down saturation update @@ -191,7 +192,7 @@ async def test_sc_table_saturation(tage_sc_dut: DUTTage_SC): await env.train_agent.exec_update(pc, 1, 1, 1, parser.value, 2, 0, 0, 1, 1, 0, 0) for i in range(4): for w in range(2): - update_write_val = getattr(tage_sc_dut, f"Tage_SC_scTables_{i}_update_wdata_{w}").S() # read as signed + update_write_val = getattr(test_env.__dut__, f"Tage_SC_scTables_{i}_update_wdata_{w}").S() # read as signed assert update_write_val == -32, f"Slot{w} of SC Table{i} is not signed down saturation update" # SC Table up saturation update @@ -213,18 +214,18 @@ async def test_sc_table_saturation(tage_sc_dut: DUTTage_SC): for i in range(4): for w in range(2): - update_write_val = getattr(tage_sc_dut, f"Tage_SC_scTables_{i}_update_wdata_{w}").S() # read as signed + update_write_val = getattr(test_env.__dut__, f"Tage_SC_scTables_{i}_update_wdata_{w}").S() # read as signed assert update_write_val == 31, f"Slot{w} of SC Table{i} is not signed up saturation update" @toffee_test.testcase -async def test_sc_total_sum_correctness(tage_sc_dut: DUTTage_SC): +async def test_sc_total_sum_correctness(test_env: TageSCEnv): def get_total_sum(sc_sum: int, tage_ctr: int): sc_ctr_sum = sc_sum * 2 + 4 tage_ctr_centered = ((tage_ctr - 4) * 2 + 1) * 8 return sc_ctr_sum + tage_ctr_centered - env = TageSCEnv(tage_sc_dut) + env = test_env ##### Test Code Start ##### await env.reset_dut() pc = 0x80000000 @@ -242,9 +243,9 @@ async def test_sc_total_sum_correctness(tage_sc_dut: DUTTage_SC): update_tage_ctr = parser.providerResps_ctr sc_table_sum = sum([parser.sc_ctrs[w][i].S() for i in range(4)]) total_sum_attr = "Tage_SC_sumAboveThreshold_totalSum" + ("_1" if w else "") - real_val_xdata = getattr(tage_sc_dut, total_sum_attr) + real_val_xdata = getattr(test_env.__dut__, total_sum_attr) expect_val = get_total_sum(sc_table_sum, update_tage_ctr[w].value) - await tage_sc_dut.AStep(1) + await test_env.__dut__.AStep(1) assert expect_val == real_val_xdata.S(), "TotalSum in train is not correct" async with toffee.Executor() as _exec: @@ -255,15 +256,15 @@ async def test_sc_total_sum_correctness(tage_sc_dut: DUTTage_SC): # Test total sum of predict async def assert_predict_total_sum(w: int): _suffix = "_1" if w else "" - tage = getattr(tage_sc_dut, f"Tage_SC_s2_tagePrvdCtrCentered_r" + _suffix).value + tage = getattr(test_env.__dut__, f"Tage_SC_s2_tagePrvdCtrCentered_r" + _suffix).value tage_centered = ((tage - 4) * 2 + 1) * 8 - high_sc_sum = getattr(tage_sc_dut, f"Tage_SC_s2_scTableSums{_suffix}_1").S() - low_sc_sum = getattr(tage_sc_dut, f"Tage_SC_s2_scTableSums{_suffix}_0").S() + high_sc_sum = getattr(test_env.__dut__, f"Tage_SC_s2_scTableSums{_suffix}_1").S() + low_sc_sum = getattr(test_env.__dut__, f"Tage_SC_s2_scTableSums{_suffix}_0").S() expect_high = high_sc_sum + tage_centered expect_low = low_sc_sum + tage_centered - real_high = getattr(tage_sc_dut, "Tage_SC_s2_totalSums_1" + _suffix) - real_low = getattr(tage_sc_dut, "Tage_SC_s2_totalSums_0" + _suffix) - await tage_sc_dut.AStep(1) + real_high = getattr(test_env.__dut__, "Tage_SC_s2_totalSums_1" + _suffix) + real_low = getattr(test_env.__dut__, "Tage_SC_s2_totalSums_0" + _suffix) + await test_env.__dut__.AStep(1) assert expect_high == real_high.S() and expect_low == real_low.S(), "TotalSum in predict is not correct" async with toffee.Executor() as _exec: @@ -273,8 +274,8 @@ async def test_sc_total_sum_correctness(tage_sc_dut: DUTTage_SC): @toffee_test.testcase -async def test_update_when_predict(tage_sc_dut: DUTTage_SC): - env = TageSCEnv(tage_sc_dut) +async def test_update_when_predict(test_env: TageSCEnv): + env = test_env await env.reset_dut() async with toffee.Executor() as _exec: _exec(env.predict_agent.exec_predict(0x114514, 1)) @@ -289,8 +290,8 @@ async def test_update_when_predict(tage_sc_dut: DUTTage_SC): @toffee_test.testcase -async def test_always_taken(tage_sc_dut: DUTTage_SC): - env = TageSCEnv(tage_sc_dut) +async def test_always_taken(test_env: TageSCEnv): + env = test_env pc = 0x800013 await env.reset_dut() @@ -300,24 +301,25 @@ async def test_always_taken(tage_sc_dut: DUTTage_SC): async with toffee.Executor() as _exec: _exec(env.ctrl_agent.exec_activate()) _exec(env.predict_agent.exec_predict(pc, 1)) - await tage_sc_dut.AStep(1) + await test_env.__dut__.AStep(1) s3 = env.predict_agent.io_out.s3 assert (s3.br_taken_mask_1.value, s3.br_taken_mask_0.value) == (1, 1), "Predict result should be true" @toffee_test.fixture -async def tage_sc_dut(toffee_request: toffee_test.ToffeeRequest): +async def test_env(toffee_request: toffee_test.ToffeeRequest): import asyncio dut = toffee_request.create_dut(DUTTage_SC, "clock") + status = StatusBundle.from_prefix("").bind(dut) toffee_request.add_cov_groups([ - get_coverage_group_of_tage_predict(dut), - get_coverage_group_of_tage_train(dut), + get_coverage_group_of_tage_predict(status), + get_coverage_group_of_tage_train(status), get_coverage_group_of_sc_predict(dut), get_coverage_group_of_sc_train(dut), ]) toffee.start_clock(dut) - yield dut + yield TageSCEnv(dut) cur_loop = asyncio.get_event_loop() for task in asyncio.all_tasks(cur_loop):