Skip to content
Open
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
5 changes: 4 additions & 1 deletion src/bcc/backend/code_template_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ def build_code_template_unit(m: Circuit) -> None:
& (~head_skip)
& head_ready
)
block_ifu = macro_active_i | start_fire
# Keep IFU blocked until the parent macro commit retires and hands off its
# redirect/next-PC state. Dropping the block as soon as template uops finish
# lets the IFU run ahead on stale PCs during the macro_wait_commit window.
block_ifu = macro_active_i | macro_wait_commit_i | start_fire

ph_init = c(0, width=2)
ph_mem = c(1, width=2)
Expand Down
54 changes: 54 additions & 0 deletions tests/pyc/tb_code_template_unit_wait_block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from __future__ import annotations

from pycircuit import Tb, testbench

from bcc.backend.code_template_unit import build_code_template_unit as build # noqa: E402


@testbench
def tb(t: Tb) -> None:
t.timeout(16)

for cyc in range(8):
t.drive("base_can_run", 0, at=cyc)
t.drive("head_is_macro", 0, at=cyc)
t.drive("head_skip", 0, at=cyc)
t.drive("head_valid", 0, at=cyc)
t.drive("head_done", 0, at=cyc)
t.drive("macro_active_i", 0, at=cyc)
t.drive("macro_wait_commit_i", 0, at=cyc)
t.drive("macro_phase_i", 0, at=cyc)
t.drive("macro_op_i", 0, at=cyc)
t.drive("macro_end_i", 0, at=cyc)
t.drive("macro_stacksize_i", 0, at=cyc)
t.drive("macro_reg_i", 0, at=cyc)
t.drive("macro_i_i", 0, at=cyc)
t.drive("macro_sp_base_i", 0, at=cyc)
t.drive("macro_uop_uid_i", 0, at=cyc)
t.drive("macro_uop_parent_uid_i", 0, at=cyc)

# Handoff window: template uops are done, but the parent macro commit has
# not retired yet. IFU must stay blocked and no new start may fire.
t.drive("base_can_run", 1, at=0)
t.drive("head_is_macro", 1, at=0)
t.drive("head_valid", 1, at=0)
t.drive("head_done", 1, at=0)
t.drive("macro_wait_commit_i", 1, at=0)
t.expect("start_fire", 0, at=0)
t.expect("block_ifu", 1, at=0)

# Active template execution also blocks IFU.
t.drive("macro_wait_commit_i", 0, at=1)
t.drive("macro_active_i", 1, at=1)
t.expect("start_fire", 0, at=1)
t.expect("block_ifu", 1, at=1)

# Once both the active body and the handoff wait clear, IFU may run again.
t.drive("macro_active_i", 0, at=2)
t.drive("head_is_macro", 0, at=2)
t.drive("head_valid", 0, at=2)
t.drive("head_done", 0, at=2)
t.expect("start_fire", 0, at=2)
t.expect("block_ifu", 0, at=2)

t.finish(at=3)
49 changes: 49 additions & 0 deletions tests/test_ctu_handoff_guard.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/tools/lib/workspace_paths.sh"

PYC_ROOT_DIR="$(linxcore_resolve_pyc_root "${ROOT_DIR}" || true)"
if [[ -z "${PYC_ROOT_DIR}" || ! -d "${PYC_ROOT_DIR}" ]]; then
echo "error: cannot locate pyCircuit; set PYC_ROOT=..." >&2
exit 2
fi

# shellcheck disable=SC1090
source "${PYC_ROOT_DIR}/flows/scripts/lib.sh"
pyc_find_pycc

OUT_DIR="${ROOT_DIR}/out/pyc/code_template_unit_wait_block"
rm -rf "${OUT_DIR}" >/dev/null 2>&1 || true
mkdir -p "${OUT_DIR}"

PYTHONPATH="$(pyc_pythonpath):${ROOT_DIR}/src" PYTHONDONTWRITEBYTECODE=1 PYCC="${PYCC}" \
python3 -m pycircuit.cli build \
"${ROOT_DIR}/tests/pyc/tb_code_template_unit_wait_block.py" \
--out-dir "${OUT_DIR}" \
--target both \
--jobs "${PYC_SIM_JOBS:-4}" \
--logic-depth "${PYC_SIM_LOGIC_DEPTH:-128}" \
--run-verilator

CPP_BIN="$(
python3 - "${OUT_DIR}/project_manifest.json" <<'PY'
import json
import sys
from pathlib import Path

p = Path(sys.argv[1])
data = json.loads(p.read_text(encoding="utf-8"))
print(data.get("cpp_executable", ""))
PY
)"

if [[ -z "${CPP_BIN}" || ! -x "${CPP_BIN}" ]]; then
echo "error: missing cpp_executable for CTU handoff guard: ${CPP_BIN}" >&2
exit 3
fi

(cd "${OUT_DIR}" && "${CPP_BIN}")

echo "ctu handoff guard: ok"