From a91c0f127f17eec427d1e5971ca76967ecb6d90c Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Mon, 21 Jul 2025 13:23:36 +1000 Subject: [PATCH] Implement the SB_NOT (useful) and SB_AND_OR (not so useful) circuits --- scripts/blocks.py | 66 ++++++++++++++++++++++++- scripts/circuits.py | 115 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 159 insertions(+), 22 deletions(-) diff --git a/scripts/blocks.py b/scripts/blocks.py index 168a50f..6206b39 100755 --- a/scripts/blocks.py +++ b/scripts/blocks.py @@ -8,7 +8,9 @@ SYMBOL_TYPE_FET = 0 SYMBOL_TYPE_GATE = 1 SYMBOL_TYPE_XOR = 2 SYMBOL_TYPE_TG_LATCH = 3 -N_SYMBOL_TYPES = 4 +SYMBOL_TYPE_SB_NOT = 4 +SYMBOL_TYPE_SB_AND_OR = 5 +N_SYMBOL_TYPES = 5 dump_nets = False if len(sys.argv) >= 2 and sys.argv[1] == '--dump_nets': @@ -118,6 +120,38 @@ with open(symbols_txt) as fin: (d_net, le_net, len_net, q_net, qn_net) ) ) + elif symbol_type == SYMBOL_TYPE_SB_NOT: + assert len(fields) == 5 + a_net, oen_net, y_net = fields[2:] + + for net in [a_net, oen_net, y_net]: + if net not in nets: + nets[net] = set() # blocks (of symbols) that the net visits + nets[net].add(block) + + symbols.append( + ( + symbol_type, + block, + (a_net, oen_net, y_net) + ) + ) + elif symbol_type == SYMBOL_TYPE_SB_AND_OR: + assert len(fields) == 8 + a0_net, a1_net, b0_net, b1_net, oen_net, y_net = fields[2:] + + for net in [a0_net, a1_net, b0_net, b1_net, oen_net, y_net]: + if net not in nets: + nets[net] = set() # blocks (of symbols) that the net visits + nets[net].add(block) + + symbols.append( + ( + symbol_type, + block, + (a0_net, a1_net, b0_net, b1_net, oen_net, y_net) + ) + ) else: assert False @@ -253,6 +287,36 @@ for block, block_symbols in sorted(blocks.items()): fout.write(f' "{node:s}" -> "{net_node:s}" [label="Q"]\n') net_node = make_net_node(qn_net) fout.write(f' "{node:s}" -> "{net_node:s}" [label="/Q"]\n') + elif symbol_type == SYMBOL_TYPE_SB_NOT: + _, _, (a_net, oen_net, y_net) = symbols[i] + + node = f'sb_not:{q_net:s}' + fout.write(f' "{node:s}" [shape="invhouse", label="SB_NOT"]\n') + + net_node = make_net_node(a_net) + fout.write(f' "{net_node:s}" -> "{node:s}" [label="A"]\n') + net_node = make_net_node(oen_net) + fout.write(f' "{net_node:s}" -> "{node:s}" [label="/OE"]\n') + net_node = make_net_node(y_net) + fout.write(f' "{node:s}" -> "{net_node:s}" [label="Y"]\n') + elif symbol_type == SYMBOL_TYPE_SB_AND_OR: + _, _, (a0_net, a1_net, b0_net, b1_net, oen_net, y_net) = symbols[i] + + node = f'sb_and_or:{q_net:s}' + fout.write(f' "{node:s}" [shape="invhouse", label="SB_AND_OR"]\n') + + net_node = make_net_node(a0_net) + fout.write(f' "{net_node:s}" -> "{node:s}" [label="A0"]\n') + net_node = make_net_node(a1_net) + fout.write(f' "{net_node:s}" -> "{node:s}" [label="A1"]\n') + net_node = make_net_node(b0_net) + fout.write(f' "{net_node:s}" -> "{node:s}" [label="B0"]\n') + net_node = make_net_node(b1_net) + fout.write(f' "{net_node:s}" -> "{node:s}" [label="B1"]\n') + net_node = make_net_node(oen_net) + fout.write(f' "{net_node:s}" -> "{node:s}" [label="/OE"]\n') + net_node = make_net_node(y_net) + fout.write(f' "{node:s}" -> "{net_node:s}" [label="Y"]\n') else: assert False fout.write('}\n') diff --git a/scripts/circuits.py b/scripts/circuits.py index aaf31c3..d1cb4ea 100755 --- a/scripts/circuits.py +++ b/scripts/circuits.py @@ -8,13 +8,19 @@ SYMBOL_TYPE_FET = 0 SYMBOL_TYPE_GATE = 1 SYMBOL_TYPE_XOR = 2 SYMBOL_TYPE_TG_LATCH = 3 -N_SYMBOL_TYPES = 4 +SYMBOL_TYPE_SB_NOT = 4 +SYMBOL_TYPE_SB_AND_OR = 5 +N_SYMBOL_TYPES = 6 CIRCUITS = [ # XOR gate as follows: - # int = a NOR b - # q = (a AND b) NOR int - # virtual nets are 0 = a, 1 = b, 2 = int, 3 = out + # int = a NOR b + # q = (a AND b) NOR int + # virtual nets are: + # 0 = a + # 1 = b + # 2 = int + # 3 = out ( [ (SYMBOL_TYPE_GATE, (3, [[0, 1], [2]])), @@ -26,8 +32,16 @@ CIRCUITS = [ [False, False, True, False], ), # transmission-gate latch with d, le, /le, q, /q as follows: - # fb = le ? d : q, /q = NOT fb, q = NOT /q - # virtual nets are 0 = d, 1 = le, 2 = /le, 3 = fb, 4 = /q, 5 = q + # fb = le ? d : /le ? q : Z + # /q = NOT fb + # q = NOT /q + # virtual nets are: + # 0 = d + # 1 = le + # 2 = /le + # 3 = fb + # 4 = /q + # 5 = q ( [ (SYMBOL_TYPE_FET, (1, [0, 3])), @@ -40,13 +54,64 @@ CIRCUITS = [ ], [False, False, False, True, False, False] ), + # inverting superbuffer with a, /oe, y as follows: + # h = /oe NOR a + # l = /oe NOR h + # y = h ? VCC : l ? GND : Z + # virtual nets are: + # -2 = VCC + # -1 = GND + # 0 = a + # 1 = /oe + # 2 = h + # 3 = l + # 4 = y + ( + [ + (SYMBOL_TYPE_GATE, (2, [[1], [0]])), + (SYMBOL_TYPE_GATE, (3, [[1], [2]])), + (SYMBOL_TYPE_FET, (2, [-2, 4])), + (SYMBOL_TYPE_FET, (3, [-1, 4])), + ], + [ + (SYMBOL_TYPE_SB_NOT, (0, 1, 4)), + ], + [False, False, True, True, False], + ), + # non-inverting superbuffer with a0, a1, b0, b1, /oe, y as follows: + # l = /oe NOR (a0 AND a1) NOR (b0 AND b1) + # h = /oe NOR l + # y = l ? GND : h ? VCC : Z + # virtual nets are: + # -4 = VCC + # -1 = GND + # 0 = a0 + # 1 = a1 + # 2 = b0 + # 3 = b1 + # 4 = /oe + # 5 = l + # 6 = h + # 7 = y + ( + [ + (SYMBOL_TYPE_GATE, (5, [[4], [0, 1], [2, 3]])), + (SYMBOL_TYPE_GATE, (6, [[4], [5]])), + (SYMBOL_TYPE_FET, (5, [-1, 7])), + (SYMBOL_TYPE_FET, (6, [-2, 7])), + ], + [ + (SYMBOL_TYPE_SB_AND_OR, (0, 1, 2, 3, 4, 7)), + ], + [False, False, False, False, False, True, True, False], + ), ] if len(sys.argv) < 3: print(f'usage: {sys.argv[0]:s} symbols.txt net_gnd,net_vcc') sys.exit(1) symbols_txt = sys.argv[1] -[net_gnd, net_vcc] = sys.argv[2].split(',') +global_nets = sys.argv[2].split(',') nets = {} symbols = [] @@ -132,7 +197,7 @@ class Match(Exception): for circuit_find, circuit_replace, circuit_internal in CIRCUITS: assert len(circuit_find) circuit_symbols = [-1] * len(circuit_find) - circuit_nets = [None] * len(circuit_internal) + circuit_nets = global_nets[::-1] + [None] * len(circuit_internal) # recurse into symbol template looking for nets that already know (as we # have unified against them already) and use them to narrow candidate set @@ -144,9 +209,9 @@ for circuit_find, circuit_replace, circuit_internal in CIRCUITS: if isinstance(t, tuple) or isinstance(t, list): candidates1 = candidate_symbols(t) else: # FIX THIS - #print('circuit_nets[t]', circuit_nets[t]) - if circuit_nets[t] is not None: - candidates1 = nets[circuit_nets[t]] + gt = len(global_nets) + t + if circuit_nets[gt] is not None: + candidates1 = nets[circuit_nets[gt]] else: continue #print('candidates1', candidates1) @@ -170,11 +235,12 @@ for circuit_find, circuit_replace, circuit_internal in CIRCUITS: # all nets flagged as internal are not connected to another symbol symbols_internal = set(circuit_symbols) for j in range(len(circuit_internal)): + gj = len(global_nets) + j if ( circuit_internal[j] and - len(nets[circuit_nets[j]] - symbols_internal) + len(nets[circuit_nets[gj]] - symbols_internal) ): - #print('rejecting net', circuit_net[j]) + #print('rejecting net', circuit_nets[gj]) return #print('match') raise Match() @@ -228,19 +294,20 @@ for circuit_find, circuit_replace, circuit_internal in CIRCUITS: return elif isinstance(t, int): assert isinstance(a, str) - if circuit_nets[t] != a: - if circuit_nets[t] is None: + gt = len(global_nets) + t + if circuit_nets[gt] != a: + if circuit_nets[gt] is None: #print('trying net', t, a) stack = (i, template, actual, stack) - circuit_nets[t] = a + circuit_nets[gt] = a match(level, stack) #print('failed net', t, a) - circuit_nets[t] = None + circuit_nets[gt] = None #else: - # print('rejecting circuit_nets[t]', circuit_nets[t]) + # print('rejecting circuit_nets[gt]', circuit_nets[gt]) return #else: - # print('matched circuit_nets[t]', circuit_nets[t]) + # print('matched circuit_nets[gt]', circuit_nets[gt]) else: assert False level -= 1 @@ -252,7 +319,7 @@ for circuit_find, circuit_replace, circuit_internal in CIRCUITS: if isinstance(template, list): return [substitute(t) for t in template] if isinstance(template, int): - return circuit_nets[template] + return circuit_nets[len(global_nets) + template] assert False # outer search is special, as it keeps track of symbol we are up to, @@ -286,7 +353,7 @@ for circuit_find, circuit_replace, circuit_internal in CIRCUITS: # continue search circuit_symbols = [-1] * len(circuit_find) - circuit_nets = [None] * len(circuit_internal) + circuit_nets = global_nets[::-1] + [None] * len(circuit_internal) for i in range(len(symbols)): symbol_type = symbols[i][0] @@ -315,3 +382,9 @@ for i in range(len(symbols)): elif symbol_type == SYMBOL_TYPE_TG_LATCH: [_, block, (d_net, le_net, len_net, q_net, qn_net)] = symbols[i] print(symbol_type, block, d_net, le_net, len_net, q_net, qn_net) + elif symbol_type == SYMBOL_TYPE_SB_NOT: + [_, block, (a_net, oen_net, y_net)] = symbols[i] + print(symbol_type, block, a_net, oen_net, y_net) + elif symbol_type == SYMBOL_TYPE_SB_AND_OR: + [_, block, (a0_net, a1_net, b0_net, b1_net, oen_net, y_net)] = symbols[i] + print(symbol_type, block, a0_net, a1_net, b0_net, b1_net, oen_net, y_net) -- 2.34.1