From dfe2e3422d527dc56d17a6d9a69cc6452eb06e40 Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Tue, 22 Jul 2025 18:28:49 +1000 Subject: [PATCH] Improved graphs in pdf format, but multiple graphs per document not working yet (the first one goes to the pdf file and the rest to stdout and are not saved) --- .gitignore | 14 ++- 8085/Makefile | 57 +++++---- scripts/blocks.py | 307 +++++++++++++++++++--------------------------- 3 files changed, 167 insertions(+), 211 deletions(-) diff --git a/.gitignore b/.gitignore index 04a4cf6..c638ba7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,21 +10,23 @@ /8080/channels.txt /8080/nets.txt /8080/sizes.txt +/8085/*.dot /8085/buried.png -/8085/circuits.ps +/8085/circuits.pdf /8085/circuits.txt /8085/diff.png -/8085/dot +/8085/fets.pdf /8085/fets.txt +/8085/gates.pdf /8085/gates.txt /8085/layers.png /8085/layers_rev.png /8085/metal.png -/8085/node_gnd.png -/8085/node_phi0.png -/8085/node_phi1.png +/8085/net_gnd.png +/8085/net_phi0.png +/8085/net_phi1.png /8085/node_sizes.txt -/8085/node_vcc.png +/8085/net_vcc.png /8085/nodes.txt /8085/pads.png /8085/poly.png diff --git a/8085/Makefile b/8085/Makefile index 1d8b362..6df0645 100644 --- a/8085/Makefile +++ b/8085/Makefile @@ -10,12 +10,14 @@ COLOURS=0,5,5,1,2,4,6,3,7 all: \ -circuits.ps \ +circuits.pdf \ +gates.pdf \ +fets.pdf \ node_sizes.txt \ -node_gnd.png \ -node_vcc.png \ -node_phi0.png \ -node_phi1.png \ +net_gnd.png \ +net_vcc.png \ +net_phi0.png \ +net_phi1.png \ layers.png \ layers_rev.png #buried2.png \ @@ -25,38 +27,46 @@ layers_rev.png #poly2.png \ #vias2.png -# requires psutils package -circuits.ps: circuits.txt - rm -rf dot - ../scripts/blocks.py $< dot - for i in dot/*.dot; \ -do \ - dot -Tps2 -o dot/`basename $$i .dot`.ps $$i; \ -done - psmerge -o$@ dot/*.ps +circuits.pdf: circuits.dot + dot -Tpdf -o $@ $< + +circuits.dot: circuits.txt + ../scripts/blocks.py $< $@ circuits.txt: gates.txt ../scripts/circuits.py $< $@ GND,VCC +gates.pdf: gates.dot + dot -Tpdf -o $@ $< + +gates.dot: gates.txt + ../scripts/blocks.py $< $@ + gates.txt: fets.txt ../scripts/gates.py $< $@ GND,VCC +fets.pdf: fets.dot + dot -Tpdf -o $@ $< + +fets.dot: fets.txt + ../scripts/blocks.py $< $@ + fets.txt: nodes.txt ../scripts/fets.py $< $@ 1,4,5,6,7 node_sizes.txt: nodes.txt ../scripts/node_sizes.py $< >$@ -node_gnd.png: nodes.txt +net_gnd.png: nodes.txt ../scripts/node_image.py --adjacency $< GND $@ ${COLOURS} -node_vcc.png: nodes.txt +net_vcc.png: nodes.txt ../scripts/node_image.py --adjacency $< VCC $@ ${COLOURS} -node_phi0.png: nodes.txt +net_phi0.png: nodes.txt ../scripts/node_image.py --adjacency $< phi0 $@ ${COLOURS} -node_phi1.png: nodes.txt +net_phi1.png: nodes.txt ../scripts/node_image.py --adjacency $< phi1 $@ ${COLOURS} nodes.txt: \ @@ -149,20 +159,21 @@ vias2.png: vias1.png clean: rm -rf \ -dot \ buried.png \ diff.png \ layers.png \ layers_rev.png \ metal.png \ -node_gnd.png \ -node_phi0.png \ -node_phi1.png \ -node_vcc.png \ +net_gnd.png \ +net_phi0.png \ +net_phi1.png \ +net_vcc.png \ pads.png \ poly.png \ split_diff.png \ vias.png \ +circuits.pdf \ +circuits.dot \ circuits.txt \ fets.txt \ gates.txt \ diff --git a/scripts/blocks.py b/scripts/blocks.py index 6b24837..4c3ebbe 100755 --- a/scripts/blocks.py +++ b/scripts/blocks.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import os import sys SYMBOL_TYPE_FET = 0 @@ -27,11 +26,12 @@ if len(sys.argv) >= 2 and sys.argv[1] == '--dump_nets': dump_nets = True del sys.argv[1] if len(sys.argv) < 3: - print(f'usage: {sys.argv[0]:s} [--dump_nets] symbols.txt dot_dir') + print(f'usage: {sys.argv[0]:s} [--dump_nets] symbols.txt symbols.dot') sys.exit(1) symbols_txt = sys.argv[1] -dot_dir = sys.argv[2] +symbols_dot = sys.argv[2] +print('input') nets = {} blocks = {} symbols = [] @@ -123,33 +123,52 @@ if dump_nets: for block in sorted(net_blocks): print(net, block) -try: - os.mkdir(dot_dir) -except FileExistsError: - pass -for block, block_symbols in sorted(blocks.items()): - with open(f'{dot_dir:s}/{block:s}.dot', 'w') as fout: - fout.write(f'digraph "{block:s}" {{\n') - fout.write(f' title="{block:s}"\n') - - net_nodes = set() - disambiguator = 0 +print('output') +with open(symbols_dot, 'w') as fout: + for block, block_symbols in sorted(blocks.items()): + fout.write( + f'''digraph "{block:s}" {{ + title="{block:s}" + rankdir=LR +''' + ) + + next_node = 0 + def make_node(label, shape = None): + global next_node + node = next_node + next_node += 1 + attrs = [f'label="{label:s}"'] + if shape is not None: + attrs.append(f'shape={shape:s}') + fout.write(' {0:d} [{1:s}]\n'.format(node, ', '.join(attrs))) + return node + + local_nets = {} def make_net_node(net): - global disambiguator - - if len(nets[net]) > 1: - # global net, make a new copy each time - net_node = f'net:{net:s}:{disambiguator:d}' - disambiguator += 1 - shape = 'box' - else: + if net in local_nets: + return local_nets[net] + if len(nets[net]) <= 1: # local net, make a shared copy - net_node = f'net:{net:s}' + local_nets[net] = next_node shape = 'plaintext' - if net_node not in net_nodes: - net_nodes.add(net_node) - fout.write(f' "{net_node:s}" [shape={shape:s}, label="{net:s}"]\n') - return net_node + else: + shape = 'box' + return make_node(net, shape) + + def make_edge(node0, node1, label = None, arrowhead = None): + attrs = [] + if label is not None: + attrs.append(f'label="{label:s}"') + if arrowhead is not None: + attrs.append(f'arrowhead={arrowhead:s}') + fout.write( + ' {0:d} -> {1:d}{2:s}\n'.format( + node0, + node1, + '' if len(attrs) == 0 else ' [{0:s}]'.format(', '.join(attrs)) + ) + ) for i in block_symbols: symbol_type = symbols[i][0] @@ -166,24 +185,19 @@ for block, block_symbols in sorted(blocks.items()): r_matrix ) = symbols[i] - node = f'{symbol_type:d}:{channel:s}' label = channel if len(r_matrix) == 2: - label += f'\nR={r_matrix[1][0]:.3f}' + label += f'\\nR={r_matrix[1][0]:.3f}' else: - label += f'\nC={mass / 2e4:.3f}' - fout.write(f' "{node:s}" [label="{label:s}"]\n') - - net_node = make_net_node(poly_net) - fout.write(f' "{net_node:s}" -> "{node:s}"\n') + label += f'\\nC={mass / 2e4:.3f}' + node = make_node(label) + make_edge(make_net_node(poly_net), node) for diff_net in diff_nets: - net_node = make_net_node(diff_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [arrowhead=none]\n') + make_edge(node, make_net_node(diff_net), arrowhead = 'none') elif symbol_type == SYMBOL_TYPE_GATE: _, _, (y_net, expr) = symbols[i] - node = f'{symbol_type:d}:{y_net:s}' if len(expr) == 1: label = ( 'FALSE' @@ -192,82 +206,54 @@ for block, block_symbols in sorted(blocks.items()): if len(expr[0]) == 1 else 'NAND' ) - fout.write( - f' "{node:s}" [shape="invhouse", label="{label:s}"]\n' - ) + node = make_node(label, shape = 'cds') for a_net in expr[0]: - net_node = make_net_node(a_net) - fout.write(f' "{net_node:s}" -> "{node:s}"\n') + make_edge(make_net_node(a_net), node) else: label = 'TRUE' if len(expr) == 0 else 'NOR' - fout.write( - f' "{node:s}" [shape="invhouse", label="{label:s}"]\n' - ) + node = make_node(label, shape = 'cds') for j in range(len(expr)): - inner_node = f'{node:s}:{j:d}' if len(expr[j]) == 1: - net_node = make_net_node(expr[j][0]) - fout.write(f' "{net_node:s}" -> "{node:s}"\n') + inner_node = make_net_node(expr[j][0]) else: label = 'TRUE' if len(expr[j]) == 0 else 'AND' - fout.write( - f' "{inner_node:s}" [shape="invhouse", label="{label:s}"]\n' - ) + inner_node = make_node(label, shape = 'cds') for a_net in expr[j]: - net_node = make_net_node(a_net) - fout.write(f' "{net_node:s}" -> "{inner_node:s}"\n') - fout.write(f' "{inner_node:s}" -> "{node:s}"\n') - net_node = make_net_node(y_net) - fout.write(f' "{node:s}" -> "{net_node:s}"\n') + make_edge(make_net_node(a_net), inner_node) + make_edge(inner_node, node) + make_edge(node, make_net_node(y_net)) elif symbol_type == SYMBOL_TYPE_XOR: _, _, (a_net, b_net, y_net) = symbols[i] - node = f'{symbol_type:d}:{y_net:s}' - fout.write(f' "{node:s}" [shape="invhouse", label="XOR"]\n') + node = make_node('XOR', shape = 'cds') - net_node = make_net_node(a_net) - fout.write(f' "{net_node:s}" -> "{node:s}"\n') - net_node = make_net_node(b_net) - fout.write(f' "{net_node:s}" -> "{node:s}"\n') - net_node = make_net_node(y_net) - fout.write(f' "{node:s}" -> "{net_node:s}"\n') + make_edge(make_net_node(a_net), node) + make_edge(make_net_node(b_net), node) + make_edge(node, make_net_node(y_net)) elif symbol_type == SYMBOL_TYPE_TG_LATCH: _, _, (d_net, le_net, len_net, q_net, qn_net) = symbols[i] - node = f'{symbol_type:d}:{q_net:s}' - fout.write(f' "{node:s}" [shape="invhouse", label="TG_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') + node = make_node('TG_LATCH', shape = 'cds') + + make_edge(make_net_node(d_net), node, label = 'D') + make_edge(make_net_node(le_net), node, label = 'LE') + make_edge(make_net_node(len_net), node, label = '/LE') + make_edge(node, make_net_node(q_net), label = 'Q') + make_edge(node, make_net_node(qn_net), label = '/Q') elif symbol_type == SYMBOL_TYPE_TG_LATCH_FB: _, _, (d_net, le_net, len_net, q_net, qn_net, fb_net) = symbols[i] - node = f'{symbol_type:d}:{q_net:s}' - fout.write(f' "{node:s}" [shape="invhouse", label="TG_LATCH_FB"]\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') - net_node = make_net_node(fb_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [label="FB"]\n') + node = make_node('TG_LATCH_FB', shape = 'cds') + + make_edge(make_net_node(d_net), node, label = 'D') + make_edge(make_net_node(le_net), node, label = 'LE') + make_edge(make_net_node(len_net), node, label = '/LE') + make_edge(node, make_net_node(q_net), label = 'Q') + make_edge(node, make_net_node(qn_net), label = '/Q') + make_edge(node, make_net_node(fb_net), label = 'FB') elif ( symbol_type == SYMBOL_TYPE_TG_LATCH_CLR or symbol_type == SYMBOL_TYPE_TG_LATCH_SET @@ -278,139 +264,96 @@ for block, block_symbols in sorted(blocks.items()): (d_net, le_net, len_net, clr_set_net, q_net, qn_net) ) = symbols[i] - node = f'{symbol_type:d}:{q_net:s}' clr_set = ( 'CLR' if symbol_type == SYMBOL_TYPE_TG_LATCH_CLR else 'SET' ) label = f'TG_LATCH_{clr_set:s}' - fout.write( - f' "{node:s}" [shape="invhouse", label="{label:s}"]\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(clr_set_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="{clr_set:s}"]\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') + node = make_node(label, shape = 'cds') + + make_edge(make_net_node(d_net), node, label = 'D') + make_edge(make_net_node(le_net), node, label = 'LE') + make_edge(make_net_node(len_net), node, label = '/LE') + make_edge(make_net_node(clr_set_net), node, label = clr_set) + make_edge(node, make_net_node(q_net), label = 'Q') + make_edge(node, make_net_node(qn_net), label = '/Q') elif ( symbol_type == SYMBOL_TYPE_TG_LATCH_CLR_FB or symbol_type == SYMBOL_TYPE_TG_LATCH_SET_FB ): - ( - _, - _, - (d_net, le_net, len_net, clr_set_net, q_net, qn_net, fb_net) - ) = symbols[i] - - node = f'{symbol_type:d}:{q_net:s}' clr_set = ( 'CLR' - if symbol_type == SYMBOL_TYPE_TG_LATCH_CLR_FB else + if symbol_type == SYMBOL_TYPE_TG_LATCH_CLR else 'SET' ) label = f'TG_LATCH_{clr_set:s}_FB' - fout.write( - f' "{node:s}" [shape="invhouse", label="{label:s}"]\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(clr_set_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="{clr_set:s}"]\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') - net_node = make_net_node(fb_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [label="FB"]\n') + node = make_node(label, shape = 'cds') + + make_edge(make_net_node(d_net), node, label = 'D') + make_edge(make_net_node(le_net), node, label = 'LE') + make_edge(make_net_node(len_net), node, label = '/LE') + make_edge(make_net_node(clr_set_net), node, label = clr_set) + make_edge(node, make_net_node(q_net), label = 'Q') + make_edge(node, make_net_node(qn_net), label = '/Q') + make_edge(node, make_net_node(fb_net), label = 'FB') elif ( symbol_type == SYMBOL_TYPE_SUPER or symbol_type == SYMBOL_TYPE_NOT_SUPER ): _, _, (a_net, y_net) = symbols[i] - node = f'{symbol_type:d}:{y_net:s}' label = 'SUPER' if symbol_type == SYMBOL_TYPE_SUPER else 'NOT_SUPER' - fout.write(f' "{node:s}" [shape="invhouse", label="{label:s}"]\n') + node = make_node(label, shape = 'cds') - net_node = make_net_node(a_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="A"]\n') - net_node = make_net_node(y_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [label="Y"]\n') + make_edge(make_net_node(a_net), node) + make_edge(node, make_net_node(y_net)) elif ( symbol_type == SYMBOL_TYPE_SUPER_OE or symbol_type == SYMBOL_TYPE_NOT_SUPER_OE ): _, _, (a_net, oen_net, y_net) = symbols[i] - # note: need a better way to disambiguate when y net can be hi-Z - node = f'{symbol_type:d}:{oen_net:s}:{y_net:s}' - label = 'SUPER_OE' if symbol_type == SYMBOL_TYPE_SUPER else 'NOT_SUPER_OE' - fout.write(f' "{node:s}" [shape="invhouse", label="{label:s}"]\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') + label = ( + 'SUPER_OE' + if symbol_type == SYMBOL_TYPE_SUPER else + 'NOT_SUPER_OE' + ) + node = make_node(label, shape = 'cds') + + make_edge(make_net_node(a_net), node, 'A') + make_edge(make_net_node(oen_net), node, '/OE') + make_edge(node, make_net_node(y_net), 'Y') elif symbol_type == SYMBOL_TYPE_NOR_SUPER: _, _, (a_net, b_net, y_net) = symbols[i] - node = f'{symbol_type:d}:{y_net:s}' - fout.write(f' "{node:s}" [shape="invhouse", label="NOR_SUPER"]\n') + node = make_node('NOR_SUPER', shape = 'cds') - net_node = make_net_node(a_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="A"]\n') - net_node = make_net_node(b_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="B"]\n') - net_node = make_net_node(y_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [label="Y"]\n') + make_edge(make_net_node(a_net), node, 'A') + make_edge(make_net_node(b_net), node, 'B') + make_edge(node, make_net_node(y_net), 'Y') elif symbol_type == SYMBOL_TYPE_NOR_SUPER_HD: _, _, (a_net, b_net, y_net, hd_net) = symbols[i] - node = f'{symbol_type:d}:{y_net:s}' - fout.write(f' "{node:s}" [shape="invhouse", label="NOR_SUPER_HD"]\n') - - net_node = make_net_node(a_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="A"]\n') - net_node = make_net_node(b_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="B"]\n') - net_node = make_net_node(y_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [label="Y"]\n') - net_node = make_net_node(hd_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [label="HD"]\n') + node = make_node('NOR_SUPER_HD', shape = 'cds') + + make_edge(make_net_node(a_net), node, 'A') + make_edge(make_net_node(b_net), node, 'B') + make_edge(node, make_net_node(y_net), 'Y') + make_edge(node, make_net_node(hd_net), 'HD') elif ( symbol_type == SYMBOL_TYPE_MUX2 or symbol_type == SYMBOL_TYPE_MUX2_NOT ): _, _, (a_net, b_net, s_net, y_net) = symbols[i] - node = f'{symbol_type:d}:{y_net:s}' label = 'MUX2' if symbol_type == SYMBOL_TYPE_MUX2 else 'MUX2_NOT' - fout.write(f' "{node:s}" [shape="invhouse", label="{label:s}"]\n') - - net_node = make_net_node(a_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="A"]\n') - net_node = make_net_node(b_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="B"]\n') - net_node = make_net_node(s_net) - fout.write(f' "{net_node:s}" -> "{node:s}" [label="S"]\n') - net_node = make_net_node(y_net) - fout.write(f' "{node:s}" -> "{net_node:s}" [label="Y"]\n') + node = make_node(label, shape = 'cds') + + make_edge(make_net_node(a_net), node, 'A') + make_edge(make_net_node(b_net), node, 'B') + make_edge(make_net_node(s_net), node, 'S') + make_edge(node, make_net_node(y_net), 'Y') else: assert False fout.write('}\n') -- 2.34.1