この文書はまだ翻訳されていません。本文は英語のまま表示されています。
How this chip is built
Generated by tools/export-idioms.py. Every count is derived from
web/*.json; the why lines are authored and marked as such, because a
person's reading and a measurement must not be laundered into each other.
A chip designer in 1975 had no library to call. Every structure here is built from one component (a transistor that conducts when its gate is high) and one trick (a resistor to the supply that something can pull down). What follows is the vocabulary that fell out of those two things, counted.
1. There is exactly one kind of gate
NMOS builds logic one way: a pullup holds the output high, a network of transistors to ground can beat it, so the output is low when the network conducts. Transistors in parallel are the ORs, in series are the ANDs, and the pullup inverts the lot. Every static gate on this die is therefore an inverted sum of products.
There is no AND gate and no OR gate anywhere on this chip. To get an AND you build a NOR and invert its inputs, or you invert its output. That single fact explains most of what the die looks like.
| shape | count |
|---|---|
| inverter | 534 |
| nor | 354 |
| nand | 39 |
| aoi | 91 |
| dynamic (no pullup at all, see idiom 3) | 142 |
Why (authored). A pullup costs silicon and burns current whenever the gate is low. Series transistors are slow, because each one adds resistance. So the cheap gate is a wide NOR and the expensive one is a deep NAND, which is exactly the ratio the die shows: 354 NORs against 39 NANDs. The technology's cost model is visible in the gate mix.
2. Storage is a ring you can break
The chip has 386 nodes that no gate drives. They hold values, and they do it in a small number of shapes:
| shape | count | what it is |
|---|---|---|
latch | 236 | a clocked switch and a gate, no feedback: transparent while the clock is high, then holding on charge |
ring | 53 | two inverters in a loop with a switch in it: a real memory cell |
chain | 27 | storage joined only to storage, with no gate between |
mux | 25 | three or more sources arbitrating for one wire |
gated | 24 | a gate on one side, no clock |
precharge | 21 | driven high by the clock, then pulled down or left holding |
Every single ring is two inverters deep. 53 of 53, no exceptions.
A register bit on this chip is: invert it, invert it again, and close the
loop through a pass transistor. Open the transistor and the value
circulates forever. Shut it and the bit is free to be written from a bus.
Examples: x2, #ABL7, y0, x4, #ABH3, x1, #ABL1, y6.
Why (authored). A static RAM cell needs six transistors. This needs four, and two of those are the pullups you would need anyway. The price is that the value leaks away if the loop is left open too long, which is why this processor has a MINIMUM clock speed as well as a maximum. The 6502 forgets if you stop it.
3. Dynamic logic: let the clock do the work
142 gates have no pullup at all. A clocked transistor pulls the node high on one phase and the logic either pulls it down on the next or leaves it holding its charge. Same trick as the ring, applied to a gate instead of a memory cell.
Why (authored). Half the transistors and none of the standing current, in exchange for having to keep moving. Almost every control line on this chip works this way.
4. One wire, many drivers: the bus
A bus here is not a component. It is a wire that nothing drives, precharged high by the clock, with a pass transistor to every possible source. The decoder opens exactly one.
| sources on one wire | how many wires |
|---|---|
| 1 | 238 |
| 2 | 96 |
| 3 | 9 |
| 4 | 8 |
| 5 | 1 |
| 6 | 13 |
| 7 | 7 |
| 11 | 6 |
| 12 | 2 |
The widest wire on the chip is sb0, with 12 sources, and this is the
list rather than a summary of it: every one is a pass transistor with a
decode line of its own.
| control line | reaches |
|---|---|
dpc0_YSB | #564 |
dpc11_SBADD | alua0 |
dpc1_SBY | y0 |
dpc20_ADDSB06 | alu0 |
dpc23_SBAC | a0 |
dpc24_ACSB | #146 |
dpc25_SBDB | idb0 |
dpc27_SBADH | adh0 |
dpc2_XSB | #1169 |
dpc3_SBX | x0 |
dpc4_SSB | #332 |
dpc6_SBS | s0 |
Read the names and the convention falls out: they come in pairs, one
to put a value on the wire and one to take it off. YSB/SBY, SBAC/ACSB, XSB/SBX, SSB/SBS. Those names are
not ours: they are Hanson's SOURCE/DEST from the MOS blueprints, and
docs/atlas.md traces where they came from.
Why (authored). Twelve sources through twelve transistors is far cheaper than a twelve-input multiplexer built out of gates, and it is why the decode PLA has so many outputs: every one of those pass transistors needs somebody to say when. The bus is cheap and the control of it is the expensive part.
5. Where the opcode rules actually live
There is no lookup table and no microcode ROM in the usual sense. There is a PLA: a grid where the instruction register's eight bits and their complements run one way, and 122 product-term wires run the other. A term has a pulldown transistor wherever it cares about a bit, so a term fires when the opcode matches its pattern, and a term that does not test a bit simply has no transistor there and matches both ways.
| product terms | 122 |
| terms the die gives a name | 121 |
| terms gated by IR bit 0 or 1 directly | 48 |
| control lines out | 46 |
| of those traced back to terms | 32 |
The undocumented opcodes are the lesson. Nothing on this chip checks
whether an opcode is legal. LDA and LDX are two rows of the grid, and
for 8 opcodes both rows match at once ($A3 $A7 $AB $AF $B3 $B7 $BB $BF), so both fire and the chip
loads A and X from the same fetch. That is LAX: not a feature and not a
bug, just what a grid does when two patterns overlap. Every one of those
opcodes has low two bits 11, which is the bit neither row constrains.
Why (authored). A PLA is a decoder you can edit with a mask change, and it costs one transistor per condition rather than a gate per instruction. The cost is that it does not know what an instruction IS. It matches patterns, and every pattern it can match, it will.
6. Nothing counts the cycles
The chip has no cycle counter. It has a shift register of 6 stages, and an instruction ends when a product term resets it. So an instruction's length is not stored anywhere: it is how many cycles went by before something stopped the chain.
Measured over all 256 opcodes: 56 take 2 cycles, 27 take 3 cycles, 64 take 4 cycles, 27 take 5 cycles, 39 take 6 cycles, 19 take 7 cycles, 12 take 8 cycles, and 12 opcodes never finish at all because nothing ever resets their chain. Those are the JAM opcodes, and they are not a special case in the silicon. They are the absence of one.
Why (authored). A counter needs comparators and a table of lengths. A shift register needs one transistor per stage and the decoder you already built. When the answer is 'do nothing special', that is usually what the silicon does.
7. Eight of everything, except where it matters
The datapath is eight copies of one bit slice. The exceptions are where the design is, so here is every one of them, found by comparing the eight bits of each measured bus and reporting any that differs from its siblings. Nothing in this list was looked up.
| bus | bit | how it differs from its siblings |
|---|---|---|
ab | 0 | its gate has 3 pulldown legs where the others have 4 |
adl | 0 | driven by a dynamic where the others are bus |
adl | 1 | driven by a dynamic where the others are bus |
adl | 2 | driven by a dynamic where the others are bus |
alu | 7 | reached by dpc19_ADDSB7 and they are not; not reached by dpc20_ADDSB06 |
db | 1 | its gate has 8 pulldown legs where the others have 9 |
db | 3 | its gate has 8 pulldown legs where the others have 9 |
db | 5 | its gate has 8 pulldown legs where the others have 9 |
db | 7 | its gate has 5 pulldown legs where the others have 9 |
idb | 5 | not reached by H1x1 |
p | 5 | does not exist |
p | 4 | driven by an inverter where the others are bus; reached by H1x1 and they are not; not reached by cp1 |
sb | 0 | reached by dpc23_SBAC and they are not |
sb | 4 | reached by dpc23_SBAC and they are not |
sb | 7 | reached by dpc19_ADDSB7 and they are not; not reached by dpc20_ADDSB06 |
15 exceptions across 24 buses. Four are worth reading closely, because each is a whole feature of the instruction set showing up as one wire that is not like its neighbours.
The shifter. Bit 7 of sb and of alu is opened by dpc19_ADDSB7
where bits 0 to 6 share dpc20_ADDSB06. Two control lines instead of one,
for the one bit that has to be treated separately when a value is rotated.
The decimal adjust. sb0 and sb4 reach the accumulator directly under
dpc23_SBAC; the other six bits do not, and the die has a second set of
wires named dasb for exactly those six. BCD correction adds six, which is
0110 in binary, so bits 0 and 4 can never change and the designers did
not run them through the adjusting circuit. The instruction set's decimal
mode is visible as two wires taking a shortcut.
The interrupt vectors. adl0, adl1 and adl2 are driven by gates
named 0/ADL0..2; every other bit of that bus is a pure wire nothing
drives. Three bits, because the six vector addresses a 6502 can fetch
($FFFA and $FFFB for NMI, $FFFC and $FFFD for reset, $FFFE and
$FFFF for IRQ and BRK) differ only in their low three bits. The rest
of the address is all ones and can come from anywhere; the part that
selects which interrupt you are taking is exactly three wires.
The flag that is not stored. p has no bit 5, and idb5 is the only
data bus bit that H1x1 does not reach. H1x1 is the line that puts the
status register on the bus, and it cannot put a bit there that does not
exist. Bit 4 of p is odd too: an inverter rather than storage, because B
is not a stored flag at all but a reading of why the chip is pushing P.
Why (authored). Regularity is free to lay out and free to verify. So you build eight identical slices and then spend your cleverness on the two or three places where identical is wrong. Look for the exceptions; that is where the designer was thinking.
Go and watch one
Every idiom above is on the running chip. These links open the page that draws it, at the thing itself. Each parameter below is checked against the target page's own source before this file is written, because this project has already shipped a link carrying a parameter no page ever read, and a dead deep link looks exactly like a broken feature.
| what to look at | where |
|---|---|
| the two-inverter ring, one register at a time | /tracer?reg=x |
| the widest bus, and the lines that reach it | /tracer?bus=sb |
| the decimal adjust: the six bits that take the long way | /tracer?sb=dasb |
| the flag that is not stored | /tracer?flag=B |
| the shifter's own bit slice | /chipmap?sel=alu:bit7 |
| the timing chain as cells, not as a counter | /tracer?chain=T3 |
| the PLA row that LDA and LAX share | /decode?term=28 |
| one gate, and what makes it | /schematic?signal=sb0 |
docs/atlas.md gives the address rubric, so anything above can be looked up
by name. A register cell is regs:x:#1 (x2). The chip map draws every container
the tracer lights them half-cycle by half-cycle.
And the other direction, which is the one that makes it stick: write a
program for it. Die Runner is a 6502 ROM whose screen is a page of its own
memory, run on this simulation rather than on an emulator of it, so every
frame is the real decode PLA matching real patterns and the real bus
arbitrating between the sources listed above. games/README.md.