forked from XS-MLVP/UnityChipForXiangShan
Initial encapsulation of internal signals for `Tage_SC`, and decoupling the functionality of `tage_predict` and `tage_train` from the raw DUT pins.
This commit is contained in:
parent
676079f8e2
commit
c9ef4856fb
|
|
@ -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 *
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Reference in New Issue