The chip atlas: an address for every part
Generated by tools/export-atlas-doc.py from web/{groups,graph,schematic,timing}.json.
Nothing below is typed by hand. Regenerate after any change to the die data
or to a derivation, and the document follows.
Every node, transistor and wire on this die gets exactly one address, and a
prefix of an address is a valid way to name the set beneath it. The point is
an IP address rather than a hostname: the front routes, the back identifies.
8365 addresses: 1547 nodes, 3510 transistors, 3308 wires. All unique, all
parseable, checked by the generator before this file is written.
The rubric
<container> : <class> : <slot>
Parse from the right. The slot follows the last colon, the class the one
before it, and the container is everything left over. A fixed field count
does not work: container keys legitimately contain colons (alat:ADL/ABL),
and a bundle names two of them (regs:a~sbus:sb).
Why the separator is a colon
Measured, not chosen. Across the die's 707 names the punctuation in use is
# ( ) + - . / _; container keys add :. A colon appears in zero die
names, and kind:id is already how this project spells a container
everywhere else. . and / were both out: . is in 33 names and 14 keys,
/ in 47 and 5.
The three fields
| field | what it is | source |
|---|
| container | which derived group the part belongs to | the chip map's partition: 132 groups over 23 kinds, every node exactly once |
| class | the shape of the pulldown network, which in NMOS is the boolean function | schematic.json's recognised gates |
| slot | the die's own number for the part | segdefs.js / transdefs.js, by way of the read-only submodule |
The slot is the die's number, and that is the load-bearing decision
Every other field is a derivation, and derivations here move: the chip map
has already changed which kind owns a contested node, and the interrupt walk
has already changed its ownership rule. An address whose last field were
derived would break on every such improvement.
The generator proves the property rather than asserting it. Reversing the
kind ownership order re-owns 88 of 1547 nodes and moves 0 slots.
So a prefix is a claim that can be revised, and the slot is not. Strip an
address to its last field and the part is still findable.
The class vocabulary is closed, and it is 34 tokens
NMOS has no AND gate and no OR gate. A pullup holds the output high and a
pulldown network to ground beats it, so every static gate is an inverted sum
of products: legs in parallel are the ORs, transistors in series are the
ANDs. The leg profile is therefore a complete description of what the gate
computes, not a label for it. aoi2.1 is NOT((A AND B) OR C).
| class | count | reading |
|---|
inv | 534 | inverter |
bus | 386 | no gate drives it: a bus bit or a pass-only node |
nor2 | 165 | 2-input NOR |
dyn1 | 73 | precharged, 1 legs, no pullup |
nor3 | 53 | 3-input NOR |
aoi2.1 | 46 | AND-OR-invert, legs 2 and 1 deep |
nand2 | 39 | 2-deep NAND |
dyn3 | 36 | precharged, 3 legs, no pullup |
nor5 | 33 | 5-input NOR |
nor8 | 30 | 8-input NOR |
nor4 | 26 | 4-input NOR |
nor7 | 25 | 7-input NOR |
aoi2.2 | 25 | AND-OR-invert, legs 2 and 2 deep |
nor6 | 20 | 6-input NOR |
dyn4 | 9 | precharged, 4 legs, no pullup |
dyn7 | 7 | precharged, 7 legs, no pullup |
dyn5 | 6 | precharged, 5 legs, no pullup |
dyn9 | 4 | precharged, 9 legs, no pullup |
dyn2 | 3 | precharged, 2 legs, no pullup |
dyn8 | 3 | precharged, 8 legs, no pullup |
aoi2.2.2 | 3 | AND-OR-invert, legs 2 and 2 and 2 deep |
aoi2.1.1.1.1.1 | 2 | AND-OR-invert, legs 2 and 1 and 1 and 1 and 1 and 1 deep |
aoi2.2.2.1 | 2 | AND-OR-invert, legs 2 and 2 and 2 and 1 deep |
aoi2.2.2.2.1 | 2 | AND-OR-invert, legs 2 and 2 and 2 and 2 and 1 deep |
aoi2.2.1 | 2 | AND-OR-invert, legs 2 and 2 and 1 deep |
aoi2.2.2.2 | 2 | AND-OR-invert, legs 2 and 2 and 2 and 2 deep |
aoi2.1.1 | 2 | AND-OR-invert, legs 2 and 1 and 1 deep |
aoi2.2.1.1.1.1.1 | 2 | AND-OR-invert, legs 2 and 2 and 1 and 1 and 1 and 1 and 1 deep |
nor9 | 2 | 9-input NOR |
aoi2.1.1.1.1 | 1 | AND-OR-invert, legs 2 and 1 and 1 and 1 and 1 deep |
aoi2.1.1.1 | 1 | AND-OR-invert, legs 2 and 1 and 1 and 1 deep |
dyn6 | 1 | precharged, 6 legs, no pullup |
aoi2.1.1.1.1.1.1 | 1 | AND-OR-invert, legs 2 and 1 and 1 and 1 and 1 and 1 and 1 deep |
inert | 1 | no driver and no switch: provably unobservable |
The tail is long, and that is the die being irregular rather than the rule
being loose: 17 of the 34 classes hold fewer than five gates each, 11 of
those being AOI shapes that the ALU and the flag logic build once. The rest
are dyn2, dyn6, dyn8, dyn9, inert, nor9.
An address needs exactly one discriminator and it must be immutable. Anything
else true about a part is a tag: queryable, unordered, and free to change
without moving anything.
sbus:sb:bus:#1188 name=sb3 bit=3@sb depth=6
regs:x.SBX:dyn3:#1186 name=dpc3_SBX opens=8 precharged phase=phi1 depth=5 also=sbus:off also=dpc:phi1
regs:a:bus:#737 name=a0 bit=0@a depth=7
clock:gen:dyn5:#943 name=cclk opens=243 precharged depth=4
bit= uses the tracer's measured bus-stem rule (letters only, no not
complement, bit 0 named, at least seven of bits 0..7), which lands on 24
stems. depth= is hops from the nearest pin. phase= is measured by
running the chip. also= names a container that claims this node in the
overlapping layer but lost it in the partition.
Where the names come from
Worth stating because none of it is ours, and the answer is three deep. The
source is 6502_datapath.wiki in the preservation archive.
| scheme | example | what it is |
|---|
| Hanson | Y/SB, SB/X | SOURCE/DEST, from the block diagram drawn off the MOS blueprints |
| Balazs | R1x7, Dkx2 | a positional grid, off his own die photograph |
| JSSim, and so ours | dpc4_SSB | position prefix plus Hanson's name |
So half of a control-line name is a coordinate and half is a function. The
prefix is a real ordering: sorting the lines by their dpc index sorts them
left to right across the die, with six inversions in 43, all adjacent pairs.
Two indices are negative, dpc-1_ADL/ABL and dpc-2_ADH/ABH, because the
address latch loads sit left of where the datapath's numbering starts.
tools/check-dpc-vs-wiki.py re-asks the wiki's claims of the chip.
The entries
132 groups over 23 kinds, covering all 1547 nodes exactly once, plus 138
containers that overlap on purpose. n is the node count; a group with a
. in its id is a child of the one above it.
regs: registers
| address prefix | n | label |
|---|
regs:s | 32 | S |
regs:s.SS | 5 | SS |
regs:s.SBS | 4 | SBS |
regs:s.SADL | 5 | SADL |
regs:s.SSB | 5 | SSB |
regs:a | 24 | A |
regs:a.SBAC | 5 | SBAC |
regs:a.ACDB | 5 | ACDB |
regs:a.ACSB | 5 | ACSB |
regs:x | 24 | X |
regs:x.SBX | 5 | SBX |
regs:x.XSB | 5 | XSB |
regs:y | 24 | Y |
regs:y.SBY | 5 | SBY |
regs:y.YSB | 5 | YSB |
regs:shared.s.SS-s.SBS-a.SBAC-x.SBX-y.SBY | 1 | shared by s.SS, s.SBS, a.SBAC, x.SBX, y.SBY |
regs:shared.s.SS-s.SBS-a.SBAC-a.ACDB-a.ACSB-x.SBX-x.XSB-y.SBY-y.YSB | 1 | shared by s.SS, s.SBS, a.SBAC, a.ACDB, a.ACSB, x.SBX, x.XSB, y.SBY, y.YSB |
regs:shared.s.SS-s.SBS | 1 | shared by s.SS, s.SBS |
flags: status flags
| address prefix | n | label |
|---|
flags:C | 14 | C flag |
flags:Z | 11 | Z flag |
flags:I | 9 | I flag |
flags:D | 9 | D flag |
flags:B | 2 | B flag |
flags:V | 24 | V flag |
flags:N | 7 | N flag |
flags:shared | 3 | shared flag logic |
flags:out | 6 | P readout |
alat: address latches
| address prefix | n | label |
|---|
alat:abl | 56 | ABL |
alat:abh | 56 | ABH |
alat:ADL/ABL | 18 | ADL/ABL |
alat:ADH/ABH | 5 | ADH/ABH |
alat:low | 4 | ADL constants |
alat:high | 8 | ADH constants |
dbus: data bus
| address prefix | n | label |
|---|
dbus:idl | 32 | idl |
dbus:dor | 48 | dor |
dbus:idb | 8 | idb |
dbus:DL/ADH | 17 | DL/ADH |
dbus:DL/DB | 5 | DL/DB |
dbus:DL/ADL | 4 | DL/ADL |
dbus:SBDB | 5 | SBDB |
dbus:PCLDB | 7 | PCLDB |
dbus:PCHDB | 5 | PCHDB |
dbus:rw | 20 | rw |
irp: instruction register
| address prefix | n | label |
|---|
irp:pd | 24 | pd |
irp:load | 24 | load |
irp:ir | 16 | ir |
irp:pre | 7 | pre |
irp:irline3 | 2 | irline3 |
irp:clear | 1 | clear |
irp:fetch | 2 | fetch |
sbus: special bus
| address prefix | n | label |
|---|
sbus:sb | 8 | sb |
sbus:dasb | 12 | dasb |
sbus:SBADH | 7 | SBADH |
sbus:onto | 2 | onto |
sbus:off | 1 | off |
sdp: store pipeline
| address prefix | n | label |
|---|
sdp:detect | 4 | DETECT |
rdy: ready logic
| address prefix | n | label |
|---|
rdy:in | 4 | RDY receiver |
rdy:master | 1 | master |
rdy:copies | 8 | copies |
pcr: program counter
| address prefix | n | label |
|---|
pcr:pcl | 8 | pcl |
pcr:pch | 8 | pch |
pcr:pclp | 8 | pclp |
pcr:pchp | 8 | pchp |
pcr:PCLPCL | 6 | PCLPCL |
pcr:ADLPCL | 4 | ADLPCL |
pcr:PCLADL | 5 | PCLADL |
pcr:PCHPCH | 6 | PCHPCH |
pcr:ADHPCH | 4 | ADHPCH |
pcr:PCHADH | 6 | PCHADH |
pipe: pipeline latches
| address prefix | n | label |
|---|
pipe:named | 12 | named pipe latches |
pipe:unk | 19 | pipeUNK latches |
sync: SYNC
| address prefix | n | label |
|---|
sync:sync | 4 | SYNC generator |
clock: clock generator
| address prefix | n | label |
|---|
clock:gen | 16 | clock generator |
intr: interrupts
| address prefix | n | label |
|---|
intr:irq | 6 | IRQ path |
intr:nmi | 18 | NMI path |
intr:res | 6 | RES path |
intr:shared | 4 | shared interrupt path |
intr:vector | 3 | vector selection |
branch: branch logic
| address prefix | n | label |
|---|
branch:cross | 2 | branch: cross |
branch:direction | 8 | branch: direction |
branch:taken | 7 | branch: taken |
decimal: decimal correction
| address prefix | n | label |
|---|
decimal:bcd | 51 | decimal correction |
alu: ALU
| address prefix | n | label |
|---|
alu:bit0 | 10 | bit0 |
alu:bit1 | 11 | bit1 |
alu:bit2 | 11 | bit2 |
alu:bit3 | 11 | bit3 |
alu:bit4 | 10 | bit4 |
alu:bit5 | 11 | bit5 |
alu:bit6 | 11 | bit6 |
alu:bit7 | 11 | bit7 |
alu:shared | 7 | shared |
alu:a | 8 | a |
alu:b | 16 | b |
alu:cin | 14 | cin |
alu:cout | 7 | cout |
alu:vout | 4 | vout |
alu:in | 23 | in |
alu:fn | 25 | fn |
alu:out | 35 | out |
incr: PC incrementer
| address prefix | n | label |
|---|
incr:pc | 86 | PC incrementer |
chain: timing chain
| address prefix | n | label |
|---|
chain:T0 | 9 | T0 cell (clock1) |
chain:T1 | 1 | T1 cell (clock2) |
chain:T2 | 4 | T2 cell (t2) |
chain:T3 | 4 | T3 cell (t3) |
chain:T4 | 4 | T4 cell (t4) |
chain:T5 | 4 | T5 cell (t5) |
chain:shared | 3 | shared chain logic |
bus: internal bus
| address prefix | n | label |
|---|
bus:adl | 8 | adl |
bus:adh | 8 | adh |
stage: decode terms
| address prefix | n | label |
|---|
stage:T0 | 33 | T0 terms |
stage:T2 | 17 | T2 terms |
stage:T3 | 10 | T3 terms |
stage:T4 | 9 | T4 terms |
stage:T5 | 8 | T5 terms |
stage:T+ | 11 | T+ terms |
stage:any | 33 | any terms |
pins: pins
| address prefix | n | label |
|---|
pins:input | 6 | input pins |
pins:output | 16 | output pins |
pins:bidirectional | 8 | bidirectional pins |
rest: rest of a block
| address prefix | n | label |
|---|
rest:0 | 4 | rest of Unaccounted |
rest:3 | 26 | rest of Decode PLA |
rest:4 | 10 | rest of Control pipeline |
rest:5 | 4 | rest of Timing chain |
rest:6 | 7 | rest of Interrupts & vectors |
rest:8 | 3 | rest of ALU |
logic: static logic
| address prefix | n | label |
|---|
logic:0 | 40 | shared static logic |
logic:3 | 6 | gates driving Decode PLA |
logic:4 | 27 | gates driving Control pipeline |
logic:5 | 2 | gates driving Timing chain |
logic:6 | 9 | gates driving Interrupts & vectors |
logic:8 | 7 | gates driving ALU |
logic:12 | 9 | gates driving Data bus |
Containers that exist only in the overlapping layer
These claim no node in the partition, because everything in them is already
owned by a derivation that is more specific. They are still the honest answer
to "what is this node part of".
| container | n | why it is absorbed |
|---|
sbus:link | 1 | absorbed whole by the special bus |
sdp:sd1 | 4 | the address latches' ADL/ABL cone reads it and outranks it |
sdp:sd2 | 7 | same, one cycle later |
dpc:phi1 | 18 | a clock phase is not a fact about the wiring, so it is added last |
dpc:both | 26 | same |
dpc:unreached | 2 | same, for the lines the probe programs never raise |
122 nodes are in more than one container, at most 5. That number is not a
defect: a node in the decimal correction is also in an ALU slice, and saying
only one of those is a consequence of a drawing needing disjoint boxes.
What the address cannot tell you
- Direction. A pass transistor conducts both ways, so topology alone
cannot say which end is the source. Hanson's
SOURCE/DEST names are the
only record of it, and they are authored, not measured.
- Neighbourhood.
depth= is hops from a pin, which is a distance, not a
neighbourhood. "What is within two hops" is a query, not a coordinate.
- Which container is most interesting. The partition picks one owner so
a box can be drawn.
also= carries the rest.
- Anything about node 866. It classifies as
inert and that is correct:
it gates one transistor and nothing in the chip can drive it, so no run can
ever observe it.