Add latch subcircuit (transmission gate latch found in e.g. 8085 block_alu22)
authorNick Downing <nick@ndcode.org>
Sun, 20 Jul 2025 14:50:45 +0000 (00:50 +1000)
committerNick Downing <nick@ndcode.org>
Sun, 20 Jul 2025 14:50:45 +0000 (00:50 +1000)
scripts/blocks.py
scripts/circuits.py

index 5fd139e..15aab6c 100755 (executable)
@@ -6,7 +6,8 @@ import sys
 SYMBOL_TYPE_FET = 0
 SYMBOL_TYPE_GATE = 1
 SYMBOL_TYPE_XOR = 2
-N_SYMBOL_TYPES = 3
+SYMBOL_TYPE_LATCH = 3
+N_SYMBOL_TYPES = 4
 
 if len(sys.argv) < 3:
   print(f'usage: {sys.argv[0]:s} symbols.txt dot_dir')
@@ -96,6 +97,22 @@ with open(symbols_txt) as fin:
         nets[net].add(block)
 
       symbols.append((symbol_type, block, (output_net, input_nets)))
+    elif symbol_type == SYMBOL_TYPE_LATCH:
+      assert len(fields) == 7
+      d_net, le_net, len_net, q_net, qn_net = fields[2:]
+
+      for net in [d_net, le_net, len_net, q_net, qn_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,
+          (d_net, le_net, len_net, q_net, qn_net)
+        )
+      )
     else:
       assert False
 
@@ -206,6 +223,22 @@ for block, block_symbols in sorted(blocks.items()):
           fout.write(f'  "{net_node:s}" -> "{node:s}"\n')
         net_node = make_net_node(output_net)
         fout.write(f'  "{node:s}" -> "{net_node:s}"\n')
+      elif symbol_type == SYMBOL_TYPE_LATCH:
+        _, _, (d_net, le_net, len_net, q_net, qn_net) = symbols[i]
+
+        node = f'latch:{q_net:s}'
+        fout.write(f'  "{node:s}" [shape="invhouse", label="LATCH"]\n')
+
+        net_node = make_net_node(d_net)
+        fout.write(f'  "{net_node:s}" -> "{node:s}" [label="D"]\n')
+        net_node = make_net_node(le_net)
+        fout.write(f'  "{net_node:s}" -> "{node:s}" [label="LE"]\n')
+        net_node = make_net_node(len_net)
+        fout.write(f'  "{net_node:s}" -> "{node:s}" [label="/LE"]\n')
+        net_node = make_net_node(q_net)
+        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')
       else:
         assert False
     fout.write('}\n')
index 63008f0..1ce083f 100755 (executable)
@@ -7,10 +7,14 @@ import sys
 SYMBOL_TYPE_FET = 0
 SYMBOL_TYPE_GATE = 1
 SYMBOL_TYPE_XOR = 2
-N_SYMBOL_TYPES = 3
+SYMBOL_TYPE_LATCH = 3
+N_SYMBOL_TYPES = 4
 
 CIRCUITS = [
-  # (a AND b) NOR (a NOR b) => a XOR b
+  # 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
   (
     [
       (SYMBOL_TYPE_GATE, (3, [[0, 1], [2]])),
@@ -21,6 +25,21 @@ CIRCUITS = [
     ],
     [False, False, True, False],
   ),
+  # 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
+  (
+    [
+      (SYMBOL_TYPE_FET, (1, [0, 3])),
+      (SYMBOL_TYPE_FET, (2, [3, 5])),
+      (SYMBOL_TYPE_GATE, (4, [[3]])),
+      (SYMBOL_TYPE_GATE, (5, [[4]])),
+    ],
+    [
+      (SYMBOL_TYPE_LATCH, (0, 1, 2, 5, 4)),
+    ],
+    [False, False, False, True, False, False]
+  ),
 ]
 
 if len(sys.argv) < 3:
@@ -293,3 +312,6 @@ for i in range(len(symbols)):
   elif symbol_type == SYMBOL_TYPE_XOR:
     [_, block, (output_net, input_nets)] = symbols[i]
     print(symbol_type, block, output_net, ' '.join(input_nets))
+  elif symbol_type == SYMBOL_TYPE_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)