"""Compare two `aiorders` dumps under lane BP's proven noise mask. The mask comes from lane BP's L/A pair, which wrote BYTE-IDENTICAL autosaves: any word that differs between two runs with identical outputs cannot be a word the applier reads (rule 26 (d) / lane CB's argument). """ import re, sys, collections # list -> set of word indices that are PROVEN NOISE (BP section 3.4) NOISE = { 1: {1, 5, 8, 11}, 3: set(range(4, 12)), 5: set(range(8, 12)), 7: set(range(2, 12)), 8: set(range(1, 12)), 10: set(range(2, 12)), 12: set(range(5, 12)), 14: set(range(2, 12)), 23: set(range(2, 12)), } ELEM = re.compile( r'aielem blk=(\d+) pid=(\d+) list=(\d+) idx=(\d+) node=(0x[0-9a-f]+) words=(\d+) .*hex=\[ ([0-9a-f ]+)\]') LISTS = re.compile(r'ailists seq=(\d+) blk=(\d+) pid=(\d+) nonEmpty=(\d+) sizes\(1\.\.27\)=\[([ 0-9]+)\]') BLK = re.compile(r'aiblk seq=(\d+) blk=(\d+)/(\d+) at=(0x[0-9a-f]+) pid=(\d+) rate=([^ ]+) target=([^ ]+) boost=([^ ]+) g4=([^ ]+) f3=([^ ]+) civ=(\d+)') BATCH = re.compile(r'---- aibatch seq=(\d+) blocks=(0x[0-9a-f]+) n=(\d+) stride=(0x[0-9a-f]+) ----') def parse(path): elems, lists, blks, batches = {}, {}, {}, [] nodes = {} for line in open(path): m = ELEM.search(line) if m: blk, pid, lst, idx, node, nw, hexs = m.groups() key = (int(blk), int(pid), int(lst), int(idx)) elems[key] = hexs.split() nodes[key] = node continue m = LISTS.search(line) if m: seq, blk, pid, ne, sizes = m.groups() lists[(int(seq), int(blk), int(pid))] = (int(ne), tuple(int(x) for x in sizes.split())) continue m = BLK.search(line) if m: g = m.groups() blks[(int(g[0]), int(g[1]), int(g[4]))] = ('rate=' + g[5], 'boost=' + g[7], 'g4=' + g[8], 'f3=' + g[9], 'civ=' + g[10]) continue m = BATCH.search(line) if m: batches.append((int(m.group(1)), int(m.group(3)), m.group(4))) return elems, lists, blks, batches, nodes def main(a, b, na='A', nb='B'): ea, la, ba, bta, noda = parse(a) eb, lb, bb, btb, nodb = parse(b) print(f'== structure ==') print(f' batches {na}: {bta}') print(f' batches {nb}: {btb}') print(f' elements {na}: {len(ea)} {nb}: {len(eb)}') print(f' blocks {na}: {len(ba)} {nb}: {len(bb)}') ka, kb = set(ea), set(eb) if ka != kb: print(f' !! element key sets DIFFER: only-{na}={sorted(ka-kb)} only-{nb}={sorted(kb-ka)}') else: print(f' element (blk,pid,list,idx) key sets: IDENTICAL') if la != lb: print(' !! ailists sizes differ:') for k in sorted(set(la) | set(lb)): if la.get(k) != lb.get(k): print(f' {k}: {la.get(k)} vs {lb.get(k)}') else: print(' per-list sizes (all blocks): IDENTICAL') # A gate whose SET flag is 0 carries an UNINITIALISED payload (lane L4's noise class, named # as such in lane BP section 3.4). Compare only gates that are actually set. def setonly(t): return tuple(f for f in t if not re.match(r'[a-z0-9]+=0:', f)) gates_diff = [k for k in sorted(set(ba) | set(bb)) if setonly(ba.get(k, ())) != setonly(bb.get(k, ()))] if gates_diff: print(' !! aiblk gate fields differ:') for k in gates_diff: print(f' {k}: {setonly(ba.get(k, ()))} vs {setonly(bb.get(k, ()))}') else: print(' aiblk SET gate fields (rate/boost/g4/f3/civ): IDENTICAL ' '(unset gates carry uninitialised payloads - lane L4)') print(f'\n== word diffs, masked ==') masked = [] noise_hits = collections.Counter() for k in sorted(ka & kb): blk, pid, lst, idx = k wa, wb = ea[k], eb[k] for i, (x, y) in enumerate(zip(wa, wb)): if x == y: continue if i in NOISE.get(lst, set()): noise_hits[lst] += 1 else: masked.append((blk, pid, lst, idx, i, x, y)) if not masked: print(' NONE. Every differing word is inside the proven noise set.') for blk, pid, lst, idx, i, x, y in masked: print(f' blk={blk} pid={pid} list={lst:>2} idx={idx} word{i} ' f'{na}=0x{x} ({int(x,16)}) {nb}=0x{y} ({int(y,16)})') print(f' (differing words inside the noise set, by list: {dict(sorted(noise_hits.items()))})') print(f'\n== list 10 element order (systemId, fleetId) ==') for nm, e in ((na, ea), (nb, eb)): row = [(k[3], int(e[k][0], 16), int(e[k][1], 16)) for k in sorted(e) if k[2] == 10 and k[1] == 32] print(f' {nm}: ' + ' '.join(f'({s},{f})' for _, s, f in row)) print(f'\n== list 8 element order (word0) ==') for nm, e in ((na, ea), (nb, eb)): row = [(k[3], int(e[k][0], 16)) for k in sorted(e) if k[2] == 8 and k[1] == 32] print(f' {nm}: ' + ' '.join(f'idx{i}={v}' for i, v in row)) if __name__ == '__main__': main(*sys.argv[1:])