Creating a Basic Bits Machine
Oh, the excitement of starting a new project! There’s promise, there’s ideas, there’s no reason to believe this will succeed, but who cares?! Still, I should contain myself. Yes, be methodical, orderly, and... Screw that, I want to write some code! No no, first come up with a plan. Oh, alright then.
The plan is to build a Basic Bits Machine. I previously referred to it as a virtual machine, but that term is already so overloaded that it won’t do to add yet another meaning. So, what is a Basic Bits Machine? Well, it’s a virtual machine. That is to say, it’s a piece of software that simulates the working of a machine. The purpose of this all is to build a little sandbox in which you can experiment with a fundamental piece of computer technology. For example, I could build a Basic Bits Machine to toy around with 3D graphics, or one to learn about floating point operations, or parallel processing. Which leads to an obvious question.
Picking a machine
It’s worth noting that none of the options I just laid out has a direct parallel in hardware. Maybe the 3D Graphics Machine is like a GPU, and the Floating Point Machine is like an FPU, and the Parallel Processing Machine is like a multicore CPU, but... well okay, I guess those machines do have direct parallels, but I can also come up with ones that don’t. A Unicode Machine. There! Point is... nope, no point. Moving on.
I have a bit of trouble imagining what those machines would be like, though. A Floating Point Machine that does just floating point operations? How would that work? What kind of programs could you write with it? I don’t know. A Unicode Machine? Wouldn’t know where to start. There’s one type of machine that I can imagine: a processor! (A Processor Machine?)
If I want to imagine how a processor works, all I have to do, is look at how a processor works. That’s what I mean with there being a direct parallel. See, I knew I had a point there somewhere. Of course, it’s more generic than, say, a Unicode Machine and maybe that makes it a little less special, but there’s something to be said for starting with what I know. So, I’m going to build the Basic Bits Virtual CPU Machine. Ugh, naming things.
Architecture
There’s a balance I need to strike between being like a real CPU and being easy to understand. Machine codes, registers, RAM, I/O, those are all in, because they’re all necessary for even the simplest CPU. But instruction pipelines, caches, SIMD operations? Sure, modern CPUs all have them, but those are a bit too advanced for what I have in mind. Those deserve their own Basic Bits Machines!
When discussing the architecture I have in mind, there is a reasonable chance that I’m going to throw terminology at you that’s mostly unfamiliar. After all, I’m building this Basic Bits Machine to show you how a CPU works, which I wouldn’t do if I were assuming you knew all of this stuff already. I will explain everything in due time, but not all in this one article. Just read this as a teaser of what’s to come. Unless you already know all of this stuff, in which case you can leave a comment telling me to stop patronizing you and that I’m a fool for thinking there’s anyone who doesn’t already know all of this.
- An 8-bit CPU, because dealing with single bytes is a good starting point.
- Two general purpose registers, and an instruction pointer, and a stack pointer, and probably some flags.
- RAM. Probably not much, because that forces you to be creative. Or I’ll make it configurable. Don’t know yet.
- A small instruction set. Integer math, bitwise operations, conditional jumps, stack operations, memory access, direct I/O.
- Clock speed will probably be configurable. One cycle per instruction.
In terms of I/O, I’m thinking eight input pins and eight output pins. Of course, those pins need to connect to something. I would love to make it possible to add your own input and output devices as plugins, but I’ll start simple: eight buttons, and eight LEDs.
I considered not adding direct support for a stack—so no stack pointer and no pop and push instructions—because you can implement a stack yourself if you want. However, that wouldn’t be an accurate representation of how you normally program a CPU. Besides I want to be able to do things like highlight the stack in the memory view, show the stack view, warn on stack overflow, and those are hard to do if every program has a custom stack.
Here’s some stuff I consider to be out of scope for my machine: caches, interrupts, exceptions, security rings/modes, instruction pipeline, multithreading, SIMD, floating points.
Where do programs come from?
I haven’t decided yet where the machine gets the code it needs to run. When you’re dealing with a microcontroller, you typically flash your program to ROM, but I kind of like the idea of having everything in RAM. In that case, the common thing to do is load the program from a disk. That would require that I add some kind of permanent storage. That could be a fun I/O plugin, but I’d rather not add it as a special case. I’m leaning towards ‘flashing’ your program to RAM. That seems like the simplest model to me.
And I will build it with...
The sane thing to do, would be to build this as a web app. That would make it easily accessible everywhere. Problem is, I think I’d enjoy it more to build this as a desktop app. If subjective preferences isn’t your thing, I also have some rationalizations.
- I don’t know how a plugin system would work for a web app.
- A web app comes with the expectation that it works on mobile, and I don’t want to support that. Typing code on a mobile device isn’t a great experience.
The main challenge with a desktop app, is in building the user interface. I’d like to support Windows, Mac, and Linux and I don’t much feel like dealing with each of their native GUI libraries. Something like C# would be an option, though. On the other hand, I want the machine to feel more like a toy than an application, so I’m probably going with a custom look-and-feel. That makes C an option, because I could do custom rendering with OpenGL or some such. That would mean I’d have to do my own text rendering, which I’ll admit is a bit daunting. That’s a tough decision! So, I’ll postpone it.
Where to start?
“Can I please write some code now?”
“In which language?”
“...”
“Come back when you have...”
“I’ll write a prototype!”
“’Scuse me?”
“A prototype. I’ll just write a small part of the machine to test the idea and then I throw the code away afterwards and start again for real in the right language.”
“Well, I think that would...”
“’kay, bye!”
“...not be the best of... Oh. Alright then.”