#!/usr/bin/env python3 """Pack decoder 1's extracted weights (engine/rr/dec1_ref.py --extract) for engine/rr/dec1_m.comp. usage: dec1_pack.py WEIGHTS.npz OUT.bin OUT.h enc1_pack.py's layout (transposed products, columns in the consumer's k order) plus the expand (dec0_pack.py): 256 columns, four sub-positions of 64 channels each permuted to slot order. """ import os import sys import numpy as np sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from enc1_ref import inter # noqa: E402 from enc1_pack import a_tiles, b_tiles, cubic_table # noqa: E402 I32, I64, I96 = inter(32), inter(64), inter(96) I256 = [64 * (j // 64) + I64[j % 64] for j in range(256)] def main(): src, out_bin, out_h = sys.argv[1:4] w = dict(np.load(src)) e = {'we': ('A', w['we'][:, I256]), 'be': ('H', w['be'][I256])} for h in range(2): e[f'wk{h}'] = ('A', np.vstack([w[f'wk{h}a'], w[f'wk{h}b']])[:, I32]) e[f'wv{h}'] = ('B', np.vstack([w[f'wv{h}a'], w[f'wv{h}b']])[:, I32]) e[f'wo{h}'] = ('A', w[f'wo{h}'][:, I64]) e[f'bias{h}'] = ('H', w[f'bias{h}'][np.ix_(I64, I96)].T) for b in range(8): e[f'w1_{b}'] = ('A', w[f'w1_{b}'][:, I32]) e[f'b1_{b}'] = ('H', w[f'b1_{b}'][I32]) e[f'w2_{b}'] = ('A', w[f'w2_{b}'][:, I64]) e['wh'], e['bh'] = ('A', w['wh']), ('H', w['bh']) e['gain0'] = ('H', w['gain0']) for k in ('table7', 'gain14', 'table16'): e[k] = ('H', w[k][I64]) e['cubic'] = ('U', cubic_table()) blob, defines = bytearray(), [] for name, (kind, a) in e.items(): while len(blob) % 256: blob.append(0) off = len(blob) if kind == 'A': blob += a_tiles(a).tobytes() elif kind == 'B': blob += b_tiles(a).tobytes() elif kind == 'U': blob += np.ascontiguousarray(a, np.uint16).tobytes() else: blob += np.ascontiguousarray(a, np.float16).tobytes() defines.append(f'#define W_{name.upper()} {off}u // {kind} {a.shape}') open(out_bin, 'wb').write(bytes(blob)) open(out_h, 'w').write('// generated by engine/rr/dec1_pack.py\n' + '\n'.join(defines) + '\n') print(f'{len(blob)} bytes, {len(e)} entries') if __name__ == '__main__': main()