Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test code of Frontend.BPU.ITTage #41

Merged
merged 1 commit into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions scripts/build_ut_frontend_bpu_ittage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Empty file.
48 changes: 48 additions & 0 deletions ut_frontend/bpu/ittage/env/bundle.py
Original file line number Diff line number Diff line change
@@ -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_")
26 changes: 26 additions & 0 deletions ut_frontend/bpu/ittage/env/global_history.py
Original file line number Diff line number Diff line change
@@ -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
134 changes: 134 additions & 0 deletions ut_frontend/bpu/ittage/env/ittage_wrapper.py
Original file line number Diff line number Diff line change
@@ -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__())
62 changes: 62 additions & 0 deletions ut_frontend/bpu/ittage/internal.yaml
Original file line number Diff line number Diff line change
@@ -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"
Empty file.
Loading
Loading