The idea of linking multiple inputs to a single gear is really brilliant. You must direct me to the post where it was first mentioned.
Thank Dorf3000 for this idea.
Anyway I was inspired to create a scheme for a single stage carry look ahead adder. The idea was that I could rearrange the gears in the sum circuit such that the C gears were at the root of the logic tree, or in other words closest to the power source. In this manner, the availability of the power supply can substitute for the triggered gear. So I could directly hook up the adder to the output of the carry logic circuit.
However this necessitates the inclusion of an inverse carry logic circuit so that the inverse c gears can also be similarly substituted.
This was the result.
(Big Intimidating Image)
I used a colouring convention here to indicate the default state of the gear, which also indicates whether it is pretoggled or not. The light coloured gears are by default disengaged so they are the pretoggled ones.
I was reading your posts a little more carefully because I was wondering how your adder worked. Then I realized that the single gear labeled S was a triple input gear that substituted for the whole adder. I was pretty astounded.
Yes, I liked that part too...
So I was inspired once again to replace most of my adder's logic with double input gears. The amount of optimization is really staggering.
(Smaller Intimidating Image)
This modified circuit is identical in function to the previous one and has far fewer gears.
The gears marked A/B # are your pretoggled double input XOR gates. The gears marked AB # are the same but they are not pretoggled. I discovered that this configuration combines an AND gate and a NOR gate, which just so happens to be applied in the adder.
I believe I have really outdone myself this time.
Yes. Yes you have. Fewer gears and single stage adding is awesome. It means my computer architecture will be even safer. I plan on using a four phase cycle for it: Instruction fetch, Operand Fetch, Instruction Pointer Increment, then Execute. A single stage adder means all of the things I'm planning on pre-calculating while the timer is progressing through the fetch and increment stages will be completely guaranteed to be done by the execute phase is reached. More on this later on...
EDIT: I found the post! Hmm.. I think in most cases it won't be necessary for the inputs to arrive at exactly the same moment. Here's something you can try to see if it breaks. You can link a lever multiple times to the same object before the first link job is completed. I tried linking a gear twice to the same lever to see what would happen. Pulling it didn't do anything as expected. You could try it with more linkings and see if the relationship holds up.
Yeah, that was just me worried that the gear might not toggle if two signals are received at the exact same time step. I tested and verified that the gear toggles correctly, though I never thought to just use a doubly linked lever.
I noticed you intend to create a display device. 32x16 right?
Yup. In a bit I'll show off the instruction set, the register set, the memory's address space, and my timing cycle.
My concern is that with only 8-bits you may have insufficient memory to store an image to display. I'm not entirely sure how your data scheme works but my computer was also 8-bits and it faces a number of constraints.
The 8-bit instruction size allowed for 8 instructions and 32 memory addresses. With 8-bits each, this comes to a grand total of 256 bits. A 32x16 display has 512 pixels! If you cut down the number of instructions to 4 and the addresses to 64, that comes to 512 bits of memory, at the cost of a truncated instruction set and having no room for programs!
My instructions will be 8 bits for the opcode, and some instructions will have an additional 8-bit operand. Specifically, memory addresses will be 8, not 5, bits. This gives me 256 addressable bytes, or 2048 bits of addressable memory. I
do notplan on constructing every last one of these immediately. Thus I needed to have the bus designed and constructed so that I could, like real memory chips, "plug in" a new bank of memory when I decided to make more. It also means one of the bus devices will be a 512 bit monochrome display. Initially, I'm going to place the display in bank 11, and have only one bank of RAM at 00. That first bank of RAM will actually be slightly special, too, as it will also have a couple General Purpose Input bytes and a couple General Purpose Output bytes. GPI will be linkable to any lever or pressure plate anywhere. Such as a lever for controlling the computer. It'll be like a custom configurable keyboard, of sorts. The GPO will be used for general operation of hatches, bridges, doors, etc. I'm putting these in for completeness, more than any other reason. More on the structure later.
Well I think your computer's architecture is rather unusual. Your bus design seems to incorporate separate paths for data and address/instructions I think, which doesn't fit into the Von Neumann model my computer used. Could you elaborate on your overall computer design?
However adding even more memory is a big challenge. My design for memory cells is still a tremendous real estate hog. This is mainly because it uses pumps in its operation. I was thinking a fluid logic inspired system could potentially be more efficient, as it could use hatches or doors, which could take much less space. Its all about the management of the water sitting on the pressure plate, which is just a single tile.
Yeah, real estate is going to be the big problem on this one. I'll be upping the z-levels between layers greatly in my world-gen when I actually move out of design and into building. I'll probably end up wanting a good 20 layers of solid rock available to play with. I'll also be turning off HFS for this. Now that I think about it, isolated from everything but dwarves would also be a good idea, though that usually results in untamed wilds, and knowing DF2010's military hit and miss bugginess, I want as little fighting to do as possible.
Now... The Instruction Set (Preliminary, not QUITE set in stone yet)
One Byte Instructions
NOP:00000000 - No Operation (WE:-, RE:-,Length:1)
HLT:00000001 - Halt Computer (WE:-, RE:-,Length:1)
SHL:0x000010 - Shift Left Logical (x2) (WE:R0, RE:RSLT,Length:1)
SHR:0x000011 - Shift Right Arithmetic (/2) (WE:R0, RE:RSLT,Length:1)
NOT:0x000100 - Bitwise Not (WE:R0, RE:RSLT,Length:1)
AND:0x000101 - Bitwise And (WE:R0, RE:RSLT,Length:1)
OR:0x000110 - Bitwise Or (WE:R0, RE:RSLT,Length:1)
XOR:0x000111 - Bitwise Xor (WE:R0, RE:RSLT,Length:1)
ADD:0x001000 - Add, R0 = R0 + R1 (WE:R0, RE:RSLT,Length:1)
SUB:0x001001 - Subtract, R0 = R0 – R1 (WE:R0, RE:RSLT,Length:1)
SWP:0x001010 - Swap Registers, R0, R1 = R1, R0 (WE:-, RE:-,Length:1)
NNC:00001011 - Increment Index Register (WE:N, RE:NP,Length:1)
NDC:00001100 - Decrement Index Register (WE:N, RE:NM,Length:1)
Machine Code including x as the second bit disables the WE and RE signals for that operation, which turns ALU commands into test commands that do not subsequently affect the final product of R0.Two Byte Instructions
LDR [mem]:10000001 [m] - Load Register From Memory (WE:R0, RE:MEM[OP],Length:2)
STR [mem]:10000010 [m] - Store Register To Memory (WE:MEM[OP], RE:R0,Length:2)
LDI [mem]:10000101 [m] - Load Indexed Register From Memory (WE:R0, RE:MEM[OP+N],Length:2)
STI [mem]:10000110 [m] - Store Indexed Register To Memory (WE:MEM[OP+N], RE:R0,Length:2)
LDC [const]:10001000 [c] - Load Register From Constant (WE:R0, RE:OP,Length:2)
NDX [const]:10001001 [c] - Load Index From Constant (WE:N, RE:OP,Length:2)
JMP [m]:11000000 [m] - Jump, IP <= OP (WE:IP, RE:OP,Length:2)
JN [m]:11000001 [m] - Jump Negative, R0 < 0 ? IP <= OP (WE:IP, RE:OP,Length:2)
JZ [m]:11000010 [m] - Jump Zero, R0 = 0 ? IP <= OP (WE:IP, RE:OP,Length:2)
Note that Jumping instructions that test for a condition have an extra requirement for the RE and WE to occur, specifically that the test passes. If it doesn't pass, the jump instruction will be a glorified NOP, as expected.Now for the registers:
IP - Instruction Pointer, 8-bit, Memory Access Code: 00, points at the next instruction to fetch in memory
IP+1 - Instruction Pointer +1, 8-bit, Memory Access Code: 01, Virtual register always maintained at IP+1 via a dedicated Adder.
IPI - Instruction Pointer Incremented, 8-bit, Virtual register always maintained at IP+L, where L = Instruction Length.
N - Index Register, 8-bit, used for indexed memory access.
NP - Index Plus One, 8-bit, Virtual register always maintained at N+1 via a dedicated adder.
NM - Index Minus One, 8-bit, Virtual register always maintained at N-1 via a dedicated adder.
IR - Instruction Register, 8-bit, Contains the Opcode of the current instruction to execute.
OP - Operand Register, 8-bit, Memory Access Code: 10, Contains the operand of the current instruction to execute.
OP+N - Indexed Operand, 8-bit, Memory Access Code: 11, Virtual register always maintained at OP+N via a dedicated adder.
R0 - Register Zero, 8-bit, used directly by the ALU, can be semantically swapped with R1 via a simple logic gate.
R1 - Register One, 8-bit, used directly by the ALU, can be semantically swapped with R0 via a simple logic gate.
RSLT - Result Register, 8-bit, Virtual register maintained by the ALU to be the correct result of ALU instructions.
NFLAG - Negative Flag, 1-bit, Virtual "register" maintained by the ALU to be whether the result < 0. Equal to RSLT's MSB.
ZFLAG - Zero Flag, 1-bit, Virtual "register" maintained by the ALU to be whether the result = 0. Done with an 8 input NOR gate.
Registers with a Memory Access Code are registers that can be used to address memory. Addresses are 8-bits.
Virtual registers are Read Only, and can never be selected for a WE with any instruction. They are maintained by special circuitry to perform their useful functions.
Memory Structure:
Bus Device 00
0-31: DPROM - Dwarf Programmable Read Only Memory. Essentially a bank of 32 levers properly hooked up to the memory system.
31-59: RAM - Standard Random Access Memory. Hybrid Logic Memory Cells hooked into the memory system.
60-61: GPI - General Purpose Input. Reprogrammable buffers that can be hooked up to any desired input signal (lever, plate).
62-63: GPO - General Purpose Output. Hybrid Logic Cells Driving additional Buffers that can be reprogrammed to control arbitrary mechanisms.
Bus Device 01
64-127: RAM - Initially will be unused.
Bus Device 10
128-191: RAM - Initially will be unused.
Bus Device 11
192-255: MGA - Monochrome Graphics Adapter. Hybrid Logic Memory Cells preconfigured to drive a set of colored hatches for monochrome display. Arranged in rows, 4 bytes per row, 16 rows. 32x16 pixel.
Timing Cycle
As stated earlier, the timing cycle will be 4 phase to allow for operation as fast as possible.
IR < MEM[IP]
OP < MEM[IP+1]
IP < IPI
EXECUTE
The Execute phase branches out, based on what opcode is in IR. For instructions with a RE and WE specified, this is activated here, like so:
{WE} < {RE}
This works because every section of the CPU is running constantly. Specifically, all virtual registers are updated as soon as possible, and the ALU updates values the moment either R0 or R1 changes, either due to the ALU R0 < RSLT bus write, or due to the SWP instruction. The design of the ALU does
not update RSLT if IR contains a jump instruction. By the time the updated register is needed, it has been pre-calculated.