#!/usr/bin/python3 # Western Digital Pascal Microengine CP2161-x02 PLA 2 (Array 3 and 4) decoder # Eric Smith # http://www.brouhaha.com/~eric/retrocomputing/wd/microengine/microcode/ import argparse import re import sys from collections import namedtuple and_by_row = { } or_by_row = { } decode = { '00': 'X', '01': '0', '10': '1', '11': '?' } OrRow = namedtuple('OrRow', ['addr', 'tsr', 'ltsr', 'lta', 'lra']) def load_and(f): for line in f: line = line.strip() m = re.match("([0-9][0-9]):", line) if not m: continue row = int(m.group(1)) line = line[3:] line = line.replace(' ', '') if ((row < 16 and len(line) != 26) or (row >= 16 and len(line) != 28)): continue ts = decode[line[2:4]] + decode[line[0:2]] tn = line[4:11] tn0c = tn.count('0') tn1c = tn.count('1') assert (tn0c == 7) or (tn0c == 2 and tn1c == 5) q = line[11] assert q == '0' line = line[12:] if row >= 16: tr = [None] * 8 for i in range(8): tr[[3, 2, 1, 0, 4, 5, 6, 7][i]] = decode[line[i*2:i*2+2]] tr = tr[::-1] else: tr = [None] * 7 for i in range(7): tr[6-i] = decode[line[i*2:i*2+2]] tr = ''.join(tr) assert row not in and_by_row and_by_row[row] = [ts, int(tn, 2), int(q, 2), tr] def load_or(f): for line in f: line = line.strip() m = re.match("([0-9][0-9]):", line) if not m: continue row = int(m.group(1)) line = line[len(m.group(1))+1:] line = line.replace(' ', '') assert len(line) == 17 addr_permuted = line[6:11] + line[5::-1] t = OrRow(addr = int(addr_permuted, 2), tsr = int(line[11] + line[14] + line[13], 2) ^ 7, ltsr = int(line[12]), lta = int(line[15], 2), lra = int(line[16], 2)) if t.lta == 1: assert t.lra == 0 if t.lra == 1: assert t.lta == 0 and t.addr == 0 if t.ltsr == 0: assert t.tsr == 7 assert row not in or_by_row or_by_row[row] = t def dump(): ka = set(and_by_row.keys()) ko = set(or_by_row.keys()) assert ka == ko for row in sorted(ka): or_row = or_by_row[row] #print(row, or_row) print('%02d: ' % row, end='') print('%s %02x %d %08s ' % tuple(and_by_row[row]), end='') if or_row.lra == 1: print('[RTN]', end='') if or_row.lta == 1: print(' %03x ' % or_row.addr, end='') if or_row.ltsr == 1: print(' tsr=%d' % or_row.tsr, end='') print() def dump_for_sim(): for tr_num in range(0x01, 0x80): for row in range(100): interrupt = row < 16 and_row = and_by_row[row] or_row = or_by_row[row] if and_row[1] != tr_num: continue tr_val = int(and_row[0].replace('X', '0') , 2) tr_mask = int(and_row[0].replace('0', '1').replace('X', '0'), 2) val = int(and_row[3].replace('X', '0') , 2) mask = int(and_row[3].replace('0', '1').replace('X', '0'), 2) print("t%02x: %d %d %d %02x %02x %d %d %03x %d %d" % (tr_num, tr_val, tr_mask, interrupt, val, mask, or_row.tsr, or_row.ltsr, or_row.addr, or_row.lta, or_row.lra)) 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='array3.txt', dest='andplanef') parser.add_argument('-or', type=argparse.FileType('r'), nargs='?', default='array4.txt', dest='orplanef') args = parser.parse_args() load_and(args.andplanef) load_or(args.orplanef) if args.sim: dump_for_sim() else: dump()