
Show HN: 8-bit CPU simulator in C - rzach
https://github.com/reutiteuti/logic
======
userbinator
Judging by the files and their contents, this is actually a _hardcoded gate-
level simulator_ , which is very different in structure from the traditional
loop-with-a-switch emulation that most people are probably expecting.

Advice for the author: if you use a netlist-based abstraction instead of
hardcoding the circuit in code, you will be able to simplify the code, and
make it much easier to modify and inspect.

~~~
rzach
Yeah, I know since it's gate-level it will be slow (and it's already been
tedious to code) but I wanted to get a better sense of how certain components
actually worked. Multibyte RAM, for example, is not demonstrated in the
NandGame which this is based off of. It has you put two registers together to
make a two-byte RAM and then it magically extends it to a 16KB RAM, only
saying that the design could be repeated recursively to get bigger RAM.
Figuring out how to do that was interesting and enlightening.

Having no experience with netlists other than briefly reading through the
Wikipedia page, it seems they are basically just a struct of subcomponents
which is what I'm using. How would I go about abstracting that?

------
rzach
It's not quite done. I'm still working on the memory components and the
instruction set. Feel free to uncomment the testing functions in test.c to see
the other components. Also feel free to give advice on ALU and instruction set
design.

------
simonblack
Is this a simulation of some theoretical 8-bit CPU, or is it a simulation of a
real, existing 8-bit CPU?

For what it's worth, there are many existing C-code emulations of actual 1970s
8-bit CPUs on the Net. (6800, 8080, Z80, 6502, etc, etc, etc.) Studying those
may assist you in managing to get past the tricky bits.

In my own Z80 emulation work, I have leaned heavily on 'Yaze' and 'Dasm', with
a few extra features and debugging of my own.

~~~
rzach
Thanks for the recommendations. I've briefly looked at the 6502 instruction
set. Part of the problem is that most of those real-world CPUs use multibyte
instructions, which I'm not opposed to, but I'm not sure how to actually
incorporate them into my current design (It would be a lot easier if I just
did a 6502 emulator without any of the logic gate stuff). Thus I'm trying to
come up with an instruction set that utilizes only 8 bits per instruction.

~~~
simonblack
I'm fairly rusty on 1970s CPUs, but digging back into the recesses of my
memory I have a feeling that the PDP-8 used single-byte instructions. (or
maybe I am remembering the EDUC-8 project that was based on the PDP-8.)

------
ls65536
This is neat! I had some thoughts recently about creating something similar as
well.

For a simple but still practical instruction set, you can probably sanely get
away with about two dozen or so different instructions, but at the expense of
having larger programs (by number of instructions) to accomplish the same
tasks compared to a more featureful instruction set.

Here's a fairly simple set that might be a reasonable place to start...

ALU: and, or, xor, complement, shift left/right, rotate left/right, add,
subtract, multiply, divide, compare (or just use subtract and set flags for
this one)

Memory: move (copy between registers), load and store (between memory and a
register), maybe also push and pop for sanity if you want to provide explicit
stack instructions.

Control flow: jump, branch (maybe depending on flags from ALU), call/return

It might also be helpful to look at the 8-bit AVR instruction set (quite
popular for small microcontrollers, including what you might find on many
Arduino boards). It contains about a hundred or so instructions, with all of
the above list present in one form or another (although many are just aliases
for some other instruction with the same opcode but otherwise fixed
parameters). In the case of AVR, where code size is often the limiting
constraint, having a larger vocabulary of instructions is useful for
expressing a program in the smallest amount of space possible, but it
certainly isn't necessary to have all of them just for completeness.

~~~
rzach
Hey, thanks for the recommendations! I'll definitely look into the AVR
instruction set. I'm not opposed to multibyte instructions but I'm trying for
8-bit instructions. I'm actually planning to use a special register that holds
the ALU input so that I have more space for instructions in the actual
instruction. It'll take more instructions since you'll have to set the ALU
each time you need it changed, but as it's not a physical microcontroller, I'm
not worried about running out of room. Do you think this is a feasible plan?

~~~
ls65536
It's certainly possible, but remember that with 8 bits you have just 256
different possible representations, and every instruction opcode with its set
of all distinct valid parameters will map to a number of those limited 256
states. For example, this makes it a big challenge to encode anything other
than very small ranges of immediate values inside an instruction.

Typically whenever there's a reference to an N-bit instruction set, it's
referring to the widths of the registers and data paths. Very often this is
not the same as the instruction size, and in many cases instructions may even
be of variable length.

So while it's much more restricting to commit yourself to only an 8-bit
instruction size, it should still be possible to build something with it.

------
CGamesPlay
Cool project! You might already know about this, but if you don't, this is an
excellent course on implementing an 8-bit computer, and might answer your
questions about the instruction set.
[https://eater.net/8bit](https://eater.net/8bit)

------
djhworld
I did something similar a year or so ago, a really fun and rewarding project
[https://djhworld.github.io/post/2019/05/21/i-dont-know-
how-c...](https://djhworld.github.io/post/2019/05/21/i-dont-know-how-cpus-
work-so-i-simulated-one-in-code)

I didn't go as far as writing my own OS, but I did develop some simple
functions to render characters on a screen and accept keyboard input.

~~~
rzach
This is pretty cool. I actually remember reading your article a few months
back. Once I'm finished with the actual computer I might try to write
something with Xlib render a terminal and maybe even a GUI for the OS (unless
anyone has a better, higher level alternative to Xlib?)

