| 167 | # ============================================================================= |
| 168 | |
| 169 | class Kernel: |
| 170 | def __init__(self): self.instructions, self.labels, self.pos = [], {}, 0 |
| 171 | def label(self, name): self.labels[name] = self.pos |
| 172 | |
| 173 | def emit(self, inst, target=None): |
| 174 | self.instructions.append(inst) |
| 175 | inst._target, inst._pos = target, self.pos |
| 176 | self.pos += inst.size() |
| 177 | return inst |
| 178 | |
| 179 | def waitcnt(self, lgkm=None, vm=None): |
| 180 | """Wait for memory operations. lgkm=N waits until N lgkm ops remain, vm=N waits until N vmem ops remain.""" |
| 181 | vmcnt, lgkmcnt, expcnt = vm if vm is not None else 63, lgkm if lgkm is not None else 63, 7 |
| 182 | waitcnt = (expcnt & 0x7) | ((lgkmcnt & 0x3f) << 4) | ((vmcnt & 0x3f) << 10) |
| 183 | self.emit(s_waitcnt(simm16=waitcnt)) |
| 184 | |
| 185 | def finalize(self): |
| 186 | """Patch branch offsets and return the finalized instruction list.""" |
| 187 | for inst in self.instructions: |
| 188 | if inst._target is None: continue |
| 189 | offset_dwords = (self.labels[inst._target] - inst._pos - inst.size()) // 4 |
| 190 | if not -32768 <= offset_dwords <= 32767: raise ValueError(f"branch to '{inst._target}' offset {offset_dwords} exceeds simm16 range") |
| 191 | inst.simm16 = offset_dwords |
| 192 | return self.instructions |
| 193 | |
| 194 | |
| 195 | # ============================================================================= |
no outgoing calls
searching dependent graphs…