#!/usr/bin/python3 # Western Digital Pascal Microengine CP2161-x02 PLA 1 (Array 1 and 2) decoder # Eric Smith # http://www.brouhaha.com/~eric/retrocomputing/wd/microengine/microcode/ import argparse import re import sys and_by_row = { } or_by_row = { } ucode = [0] * 2048 decode = { '00': 'X', '01': '0', '10': '1', '11': '?' } def load_and(f): for line in f: line = line.strip() m = re.match("([0-9][0-9]):", line) if not m: continue l = m.group(1) line = line[3:] line = line.replace(' ', '') if len(line) != 23: continue rni = int(line[0],2) line = line[1:] bits = [None] * 11 for i in range(11): j = [5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0][i] dibit = line[:2] line = line[2:] if j < 5: dibit = dibit[::-1] bits[j] = decode[dibit] addr = ''.join(bits) [::-1] #print("%02d %01d %s" % (l, rni, addr)) assert l not in and_by_row and_by_row[l] = [rni, addr] def load_or(f): for line in f: line = line.strip() m = re.match("([0-9][0-9]|rni):", line) if not m: continue l = m.group(1) line = line[len(l)+1:] line = line.replace(' ', '') assert len(line) == 7 # permute to array 3 column ordering l2 = line[0] + line[:0:-1] # and convert to integer stc = int(l2, 2) assert l not in or_by_row or_by_row[l] = stc def load_ucode(f): line_num = 0; expected_addr = 0 for line in f: line_num += 1 line = line.strip() line = line.replace(' ', '') m = re.match('([0-9a-f]{3}):([0-9a-f]{6})', line) if not m: print('error parsing microcode file line %d' % line_num) continue addr = int(m.group(1),16) uinst = int(m.group(2),16) if addr != expected_addr: print('microcode file out of sequence, line %d expected addr %03x, found %03x', line_num, expected_addr, addr) ucode[addr] = uinst expected_addr = addr + 1 def dump(): ka = and_by_row.keys() ko = or_by_row.keys() k = list(ka) + list(set(ko) - set(ka)) for r in sorted(k): if r == 'rni': rt = r else: rt = ' %s' % r print('%s: ' % rt, end='') if r in or_by_row.keys(): print('%02x' % or_by_row[r], end='') else: print(' ', end='') if r in and_by_row.keys(): print(' %d %s' % tuple(and_by_row[r]), end='') if re.match('^[01]+$', and_by_row[r][1]): print(' %03x' % int(and_by_row[r][1], 2), end='') print() def dump_for_sim(): tr_num_by_addr = [0x7f] * 2048 for r in range(88): rs = "%02d" % r addr_bits = and_by_row[rs][1] tr_num = or_by_row[rs] if tr_num == 0x7f: continue addr_bits = '^' + addr_bits.replace('X', '[01]') + '$' addr_re = re.compile(addr_bits) for addr in range(2048): addr_str = "{0:b}".format(addr).zfill(11) if addr_re.match (addr_str): tr_num_by_addr [addr] &= tr_num for addr in range(2048): print("%03x: %06x %02x" % (addr, ucode[addr], tr_num_by_addr[addr])) # the translation for RNI is considered by the simulator input format # to have an address of 0x800 print("%03x: %06x %02x" % (0x800, 0, or_by_row['rni'])) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--sim', action='store_true', help='dump in simulator input format') parser.add_argument('--and', type=argparse.FileType('r'), nargs='?', default='array1.txt', dest='andplanef') parser.add_argument('--or', type=argparse.FileType('r'), nargs='?', default='array2.txt', dest='orplanef') parser.add_argument('--ucode', type=argparse.FileType('r'), nargs='?', default='wd9000-141518.dump', dest='ucodef') args = parser.parse_args() load_and(args.andplanef) load_or(args.orplanef) load_ucode(args.ucodef) if args.sim: dump_for_sim() else: dump()