This commit is contained in:
2026-01-02 16:53:31 -08:00
parent 9b5c4bc698
commit 96b0ee0966
+20 -26
View File
@@ -443,8 +443,8 @@ class SQTTState:
self.packets, self.cycle, self.inst_count = [], 0, 0
self.wave_id, self.simd, self.cu = wave_id, simd, cu
self.vgpr: dict[int, tuple[int, int]] = {} # reg -> (ready_cycle, chain_depth)
self.pending: list[tuple[int, AluSrc]] = [] # (completion_cycle, alu_src) - scheduled
self.deferred: list[tuple[int | None, int | None, int]] = [] # (src_vgpr, dst, depth) - waiting for warmth
self.pending: list[int] = [] # completion cycles for scheduled ALUEXECs
self.deferred: list[tuple[int | None, int | None]] = [] # (src_vgpr, dst) - waiting for warmth
self.last_valu_dispatch, self.immediate_cycles = -100, []
def emit(self, pkt_class, **kwargs): self.packets.append(pkt_class(_time=self.cycle, **kwargs))
@@ -453,35 +453,31 @@ class SQTTState:
self.emit(WAVESTART, wave=self.wave_id, simd=self.simd, cu_lo=self.cu & 0x7, flag7=self.cu >> 3)
for _ in range(WAVESTART_TO_INST_CYCLES): self.tick()
def _last_pending(self): return max((c for c, _ in self.pending), default=self.cycle - 1)
def _schedule(self, completion: int, dst: int | None):
"""Schedule ALUEXEC at completion cycle (or later if queue busy)."""
completion = max(completion, self._last_pending() + 1)
self.pending.append((completion, AluSrc.VALU))
completion = max(completion, (max(self.pending) if self.pending else self.cycle - 1) + 1)
self.pending.append(completion)
self.pending.sort()
if dst is not None: self.vgpr[dst] = (completion, self.vgpr.get(dst, (0, 0))[1])
def _resolve_deferred(self):
"""Try to schedule first deferred instruction."""
if not self.deferred: return
src_vgpr, dst, depth = self.deferred[0]
if src_vgpr is None: # blocked by earlier deferred, schedule after pending
self._schedule(self._last_pending() + 1, dst)
src_vgpr, dst = self.deferred[0]
if src_vgpr is None:
self._schedule((max(self.pending) if self.pending else self.cycle - 1) + 1, dst)
self.deferred.pop(0)
else:
source_ready = self.vgpr.get(src_vgpr, (0, 0))[0]
if source_ready <= self.cycle:
warm = sum(1 for c in self.immediate_cycles if c > source_ready) >= 2
if warm or self.cycle >= source_ready + 2:
latency = VALU_LATENCY - 1 if warm else FORWARD_DEEP_LATENCY
self._schedule(source_ready + latency, dst)
self._schedule(source_ready + (VALU_LATENCY - 1 if warm else FORWARD_DEEP_LATENCY), dst)
self.deferred.pop(0)
def tick(self):
self._resolve_deferred()
while self.pending and self.pending[0][0] <= self.cycle:
self.emit(ALUEXEC, src=self.pending.pop(0)[1])
while self.pending and self.pending[0] <= self.cycle:
self.pending.pop(0)
self.emit(ALUEXEC, src=AluSrc.VALU)
self.cycle += 1
def _get_src_vgprs(self, inst: Inst) -> list[int]:
@@ -491,9 +487,8 @@ class SQTTState:
return []
def _valu_latency(self, dispatch: int, source_ready: int, depth: int) -> int:
"""Compute VALU completion cycle. Returns -1 if must defer for warmth check."""
if depth == 0: return dispatch + VALU_LATENCY # independent
if depth >= FORWARD_DEPTH_LIMIT: return -1 # defer for warmth check
if depth == 0: return dispatch + VALU_LATENCY
if depth >= FORWARD_DEPTH_LIMIT: return -1
gap = source_ready - dispatch
if gap >= 2: return source_ready + (VALU_LATENCY - 1 if depth >= 2 else VALU_LATENCY)
if gap == 1: return source_ready + 7
@@ -507,14 +502,13 @@ class SQTTState:
def _process_snop(self, N: int):
has_pending = bool(self.pending)
bypass = REGCACHE_BYPASS_PENALTY if N >= REGCACHE_BYPASS_TIMEOUT and has_pending else 0
if bypass: self.pending = [(c + bypass, src) for c, src in self.pending]
if bypass: self.pending = [c + bypass for c in self.pending]
for _ in range(max(0, self.last_valu_dispatch + SNOP_PIPELINE_DELAY - self.cycle)): self.tick()
in_range = (SNOP_EXTRA_DELAY_MIN_PENDING <= N <= SNOP_EXTRA_DELAY_MAX_PENDING) if has_pending else \
(SNOP_EXTRA_DELAY_MIN <= N <= SNOP_EXTRA_DELAY_MAX and self.inst_count > 0)
extra = SNOP_EXTRA_DELAY_CYCLES if in_range else 0
for _ in range(N + extra + bypass): self.tick()
for _ in range(N + (SNOP_EXTRA_DELAY_CYCLES if in_range else 0) + bypass): self.tick()
self.emit(IMMEDIATE, wave=self.wave_id)
self.immediate_cycles.append(self.cycle)
self.tick()
@@ -529,11 +523,11 @@ class SQTTState:
self.last_valu_dispatch = dispatch
completion = self._valu_latency(dispatch, source_ready, depth)
if completion == -1: # defer for warmth check
self.deferred.append((src_vgpr, dst, depth))
completion = source_ready + VALU_LATENCY - 1 # optimistic for scoreboard
elif self.deferred: # blocked by earlier deferred
self.deferred.append((None, dst, depth))
if completion == -1:
self.deferred.append((src_vgpr, dst))
completion = source_ready + VALU_LATENCY - 1
elif self.deferred:
self.deferred.append((None, dst))
else:
self._schedule(completion, dst)