putianyi888
Terrarian
Hi, everyone! I've been working on this project for weeks, and recently since I saw the possibility that I could make it, I decided to post it to gather further ideas and suggestions.
Perhaps you don't understand what is a computer, or why I want to build a computer. I would explain at once.
I have seen many excellent mechanical works, like those giant hoiktronics by DicemanX and those minigames by TheRedStoneCrafter. But each complicated project has to be built from almost zero. A computer can handle some edited programmes. With a computer, one can build minigames or do calculations by simply programming.
I'm not updating this thread often. For all wiring schematics, world download and the latest progress on this project, please refer to https://github.com/putianyi889/Computer-in-Terraria
Structure of a Computer in Terraria
A computer in reality contains a CPU, an RAM, a hard disc and some i/o devices. In Terraria, things change a lot. First of all, there is no electricity so there is no such memory that loses data after blackout. What's more, there is no time delay during logical calculus, so register cannot be faster than RAM. In conclusion, a computer in terraria don't need to contain registers or a hard disc. Secondly, since a program is fixed once released, we can use ROM instead of RAM to store them. As I will show later, an ROM is much smaller than that of an RAM. Thirdly, there are a variety of i/o devices in Terraria, so I don't have to consider building them. All I need to do is to design a way for this computer to communicate with other devices.
Overall, a computer in terraria could only contain a CPU without registers, an ROM and an RAM.
How to transport data
To prevent wires from taking too much space, I use an important technique to transport multibit data through a single wire. There were posts of this technique before, and I'm just posting my design here. To understand this technique you may read this first.
Place A and place B are connected by a single yellow wire. Switching the lever at A will synchronize torchs at B with those at A, which means that the yellow wire carrys a 8-bit data. In my designs I mostly use the vertical version of this technique.
Current Progress and Some Notes
The following is my plan list and progress. Please feel free to ask any question. Any idea or suggestion would be appreciated.
(finished) RAM, ROM and Registers
(in progress) 8-bit CPU
@DRKV made me aware of the lag caused by trying to perform a great many operations in a tick. So before I continue building, I have to figure out how the lag works and try to predict the lag, so that I could know which kind of circuit is faster.
I placed a massive number (about 80*1117=89360) of torches in my test world and wired them to a conveyor belt engine which activates once per tick. Then I use my own stopwatch to measure the period of an in-game 5-second timer. While the engine is working, the period of a 5-second timer increases to around 18~20 seconds, depending on the lighting mode and video quality but not depending on frame skip or multicore lighting. Since the video settings don't make a big difference, I guess the lag is caused mainly by turning on or off the torches.
The lag also depends on hardware.
Reference
David Money Harris & Sarah L. Harris, Digital Design and Computer Architecture
Perhaps you don't understand what is a computer, or why I want to build a computer. I would explain at once.
I have seen many excellent mechanical works, like those giant hoiktronics by DicemanX and those minigames by TheRedStoneCrafter. But each complicated project has to be built from almost zero. A computer can handle some edited programmes. With a computer, one can build minigames or do calculations by simply programming.
I'm not updating this thread often. For all wiring schematics, world download and the latest progress on this project, please refer to https://github.com/putianyi889/Computer-in-Terraria
Structure of a Computer in Terraria
A computer in reality contains a CPU, an RAM, a hard disc and some i/o devices. In Terraria, things change a lot. First of all, there is no electricity so there is no such memory that loses data after blackout. What's more, there is no time delay during logical calculus, so register cannot be faster than RAM. In conclusion, a computer in terraria don't need to contain registers or a hard disc. Secondly, since a program is fixed once released, we can use ROM instead of RAM to store them. As I will show later, an ROM is much smaller than that of an RAM. Thirdly, there are a variety of i/o devices in Terraria, so I don't have to consider building them. All I need to do is to design a way for this computer to communicate with other devices.
Overall, a computer in terraria could only contain a CPU without registers, an ROM and an RAM.
How to transport data
To prevent wires from taking too much space, I use an important technique to transport multibit data through a single wire. There were posts of this technique before, and I'm just posting my design here. To understand this technique you may read this first.
Place A and place B are connected by a single yellow wire. Switching the lever at A will synchronize torchs at B with those at A, which means that the yellow wire carrys a 8-bit data. In my designs I mostly use the vertical version of this technique.
Current Progress and Some Notes
The following is my plan list and progress. Please feel free to ask any question. Any idea or suggestion would be appreciated.
(finished) RAM, ROM and Registers
ROM is used for coding. It can only be written by wiring. Registers stores variables. Each register can be read and write once per cycle. RAM stores variables that registers are to few to hold. Only one address in RAM can be read and write per cycle. Since communication between two registers is more convenient than that between two addresses in RAM, it's recommended to store most recently and frequently used variables in registers. The compact RAM design was created by @Programmatic .
(in progress) 8-bit CPU
(finished) 8-bit ALU (Wikipedia)
Measuring the LagALU is an essential part of CPU. It receives two 8-bit operands denoted by A and B and performs 14 operations: A+B, A-B, A&B, A|B, A^B, A>B, A<B, A>=B, A<=B, A==B, A!=B, A>>B, A<<B, A>>>B. There are still 2 operations left.
(finished) Return Address Stack
In MIPS, there is a register $ra containing a return address. It's used in case of function invoking. However, an instruction address is at least 10 bit long so that a register cannot hold it. Based on the role $ra plays in MIPS, I designed an address stack specifically for $ra. Sending an address to $ra means to push the address into the stack, while obtaining an address from $ra means to pop the address from the top.
(finished) Machine language
A machine language is designed to match a CPU, while a CPU is designed to read the machine language.
My current design is based on 8 bit MIPS (wiki).
There are some explicit data registers. I haven't decided how many explicit registers there should be, but there could be no more than 16 of them.
There are some implicit data registers:
R-type instruction is opcode(4)+rd(4)+funct(4)+rt(4)+rs(4). Data flow: $rs to $op1, $rt to $op2, ALUf set to funct, $ans to $rd, add 1 to $BTA, $BTA to $nPC. There are 16 different R-type instructions depending on funct(4).
J-type instruction is opcode(4)+jext(2)+address(14). There are 4 different J-type instructions depending on jext(2):
(in progress) Control Unit and Data PathMy current design is based on 8 bit MIPS (wiki).
There are some explicit data registers. I haven't decided how many explicit registers there should be, but there could be no more than 16 of them.
There are some implicit data registers:
$ad is the current address of the RAM; (finished)
$va is the value corresponding to $ad; (finished)
$im stores an immediate number; (finished)
$op1 and $op2 are two operands of the ALU; (finished)
$ans is the result from the ALU; (finished)
$mu1 and $mu2 are two operands of the multiplier;
$muh and $mul are the higher 8 digits and lower 8 digits of the product from the multiplier;
$di1 and $di2 are two operands of the divider;
$diq is the quotient from the divider;
$dir is the residue from the divider.
There are some implicit address registers:$va is the value corresponding to $ad; (finished)
$im stores an immediate number; (finished)
$op1 and $op2 are two operands of the ALU; (finished)
$ans is the result from the ALU; (finished)
$mu1 and $mu2 are two operands of the multiplier;
$muh and $mul are the higher 8 digits and lower 8 digits of the product from the multiplier;
$di1 and $di2 are two operands of the divider;
$diq is the quotient from the divider;
$dir is the residue from the divider.
$ra is the return address stack; (finished)
$addr is the last 10 bit of an instruction; (finished)
$PC is the current instruction address;
$nPC is the next instruction address; (finished)
$BTA denotes the branch-to address. (finished)
A general instruction is opcode(4)+whatever(16). At the start of each cycle, $nPC sends its address to $PC and the current instruction can be read from the ROM. It also sends the address to $BTA in order to compute the next instruction address.$addr is the last 10 bit of an instruction; (finished)
$PC is the current instruction address;
$nPC is the next instruction address; (finished)
$BTA denotes the branch-to address. (finished)
R-type instruction is opcode(4)+rd(4)+funct(4)+rt(4)+rs(4). Data flow: $rs to $op1, $rt to $op2, ALUf set to funct, $ans to $rd, add 1 to $BTA, $BTA to $nPC. There are 16 different R-type instructions depending on funct(4).
J-type instruction is opcode(4)+jext(2)+address(14). There are 4 different J-type instructions depending on jext(2):
j: jump. Data flow: $addr to $nPC.
jal: jump and link. Data flow: add 1 to $BTA, $BTA to $ra, $addr to $nPC.
jr: jump register. Data flow: $ra to $nPC.
jalr: jump register and link. Data flow: $ra to $nPC, add 1 to $BTA, $BTA to $ra.
I-type instruction is opcode(4)+imm(8)+rt(4)+rs(4).jal: jump and link. Data flow: add 1 to $BTA, $BTA to $ra, $addr to $nPC.
jr: jump register. Data flow: $ra to $nPC.
jalr: jump register and link. Data flow: $ra to $nPC, add 1 to $BTA, $BTA to $ra.
beq: branch equal. Data flow: $rs to $op1, $rt to $op2, set ALUf to ==, add 1 (if $ans==0$) or $im (if $ans==1) to $BTA, $BTA to $nPC.
bne: branch not equal. Data flow: $rs to $op1, $rt to $op2, set ALUf to !=, add 1 (if $ans==0$) or $im (if $ans==1) to $BTA, $BTA to $nPC.
ble: branch less equal. Data flow: $rs to $op1, $rt to $op2, set ALUf to <=, add 1 (if $ans==0$) or $im (if $ans==1) to $BTA, $BTA to $nPC.
bgt: branch greater. Data flow: $rs to $op1, $rt to $op2, set ALUf to >, add 1 (if $ans==0$) or $im (if $ans==1) to $BTA, $BTA to $nPC.
sb: save byte. Data flow: $rs to $op1, $im to $op2, set ALUf to +, $ans to $ad, $rt to $va, RAM write, add 1 to $BTA, $BTA to $nPC.
lb: load byte. Data flow: $rs to $op1, $im to $op2, set ALUf to +, $ans to $ad, RAM read, $va to $rt, add 1 to $BTA, $BTA to $nPC.
addi: add immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to +, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
slti: smaller than immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to <, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
andi: and immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to &, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
ori: or immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to |, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
xori: xor immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to ^, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
R-type-ext instruction is opcode(4)+rd(4)+ru(4)+rt(4)+rs(4).bne: branch not equal. Data flow: $rs to $op1, $rt to $op2, set ALUf to !=, add 1 (if $ans==0$) or $im (if $ans==1) to $BTA, $BTA to $nPC.
ble: branch less equal. Data flow: $rs to $op1, $rt to $op2, set ALUf to <=, add 1 (if $ans==0$) or $im (if $ans==1) to $BTA, $BTA to $nPC.
bgt: branch greater. Data flow: $rs to $op1, $rt to $op2, set ALUf to >, add 1 (if $ans==0$) or $im (if $ans==1) to $BTA, $BTA to $nPC.
sb: save byte. Data flow: $rs to $op1, $im to $op2, set ALUf to +, $ans to $ad, $rt to $va, RAM write, add 1 to $BTA, $BTA to $nPC.
lb: load byte. Data flow: $rs to $op1, $im to $op2, set ALUf to +, $ans to $ad, RAM read, $va to $rt, add 1 to $BTA, $BTA to $nPC.
addi: add immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to +, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
slti: smaller than immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to <, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
andi: and immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to &, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
ori: or immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to |, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
xori: xor immediate. Data flow: $rs to $op1, $im to $op2, set ALUf to ^, $ans to $rt, add 1 to $BTA, $BTA to $nPC.
mult: multiply. Data flow: $rs to $mu1, $rt to $mu2, activate multiplier, $muh to $rd, $mul to $ru.
div: divide. Data flow: $rs to $div1, $rt to $div2, activate divider, $diq to $rd, $dir to $ru.
There are 16 different opcodes. R-type takes 1. J-type takes 1. I-type takes 11. R-type-ext takes 2. There is an opcode left for drivers, e.g. display.div: divide. Data flow: $rs to $div1, $rt to $div2, activate divider, $diq to $rd, $dir to $ru.
The control unit reads an instruction and activates every part of CPU at a proper time, helping them work together.
(in progress) Multiplier and Divider
@ekinator has designed them, but I want to make them more compact. I would still use his design whenever the compact versions haven't come out.
@DRKV made me aware of the lag caused by trying to perform a great many operations in a tick. So before I continue building, I have to figure out how the lag works and try to predict the lag, so that I could know which kind of circuit is faster.
I placed a massive number (about 80*1117=89360) of torches in my test world and wired them to a conveyor belt engine which activates once per tick. Then I use my own stopwatch to measure the period of an in-game 5-second timer. While the engine is working, the period of a 5-second timer increases to around 18~20 seconds, depending on the lighting mode and video quality but not depending on frame skip or multicore lighting. Since the video settings don't make a big difference, I guess the lag is caused mainly by turning on or off the torches.
The lag also depends on hardware.
David Money Harris & Sarah L. Harris, Digital Design and Computer Architecture
Last edited: