{"id":13694146,"url":"https://github.com/djhworld/simple-computer","last_synced_at":"2025-05-16T05:06:14.093Z","repository":{"id":50380370,"uuid":"186473531","full_name":"djhworld/simple-computer","owner":"djhworld","description":"the scott CPU from \"But How Do It Know?\" by J. Clark Scott","archived":false,"fork":false,"pushed_at":"2020-10-21T20:59:12.000Z","size":705,"stargazers_count":1910,"open_issues_count":2,"forks_count":163,"subscribers_count":44,"default_branch":"master","last_synced_at":"2025-04-08T15:08:11.138Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/djhworld.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-13T18:21:44.000Z","updated_at":"2025-04-08T12:05:03.000Z","dependencies_parsed_at":"2022-07-30T23:37:57.376Z","dependency_job_id":null,"html_url":"https://github.com/djhworld/simple-computer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djhworld%2Fsimple-computer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djhworld%2Fsimple-computer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djhworld%2Fsimple-computer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djhworld%2Fsimple-computer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/djhworld","download_url":"https://codeload.github.com/djhworld/simple-computer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471061,"owners_count":22076585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T17:01:25.426Z","updated_at":"2025-05-16T05:06:14.076Z","avatar_url":"https://github.com/djhworld.png","language":"Go","readme":"# Simple Computer\n\nWhilst reading [_But How Do It Know?_](http://buthowdoitknow.com/) by J. Clark Scott I felt compelled to write something to simulate the computer the book describes. \n\nStarting from NAND gates, and moving up through to registers, RAM, the ALU, the control unit and adding I/O support, I eventually ended up with a fully functional machine. \n\nAll the components of the system are based on logic gates and the way they are connected together via the system bus.   \n\nFor a write up about this project, see my blog post about it here https://djharper.dev/post/2019/05/21/i-dont-know-how-cpus-work-so-i-simulated-one-in-code/\n\n![text writer](_programs/screenshots/text-writer.png)\n\n\n# Specs\n\n- `~0.006mhz` \n  - at least on my machine\n- 16-bit \n  - the book describes an 8-bit CPU for simplicity but I wanted more RAM and there is only one system bus\n- 65K RAM\n- 240x160 screen resolution \n- 4x 16-bit registers (`R0`, `R1`, `R2`, `R3`)\n\nMissing features\n\n- Interrupts, so you have to write awful polling code\n  - The book does shortly describe how to extend the system to support interrupts but would involve a lot more wiring \n- Stack pointer register + stack + stack manipulation instructions so nested `CALL` instructions won't work and registers may be left in an inconsistent state\n- Hard drive\n- Subtract instruction\n- `MOV` instruction\n- Floating point math (lol)\n- Everything else you could think of from a modern CPU\n\nBonus features\n\n- No Meltdown/SPECTRE risk\n- Can easily overwrite any portion of memory without any protective mode getting in the way\n- Currently incapable of accessing the internet \n  - I can see how you might write a simple networking I/O adapter, although I'd imagine it would be tedious writing the assembly to get bytes in and out of it 🤔\n\n\n# Instructions\n\n\n| Instruction    | Type      | Description   | Example |\n| -------------- | --------- | ------------- | ------------- |\n| `LOAD Ra, Rb`   | Machine   | Load value of memory address in register A into register B | `LOAD R1, R2` |\n| `STORE Ra, Rb`  | Machine   | Store value of register B into memory address in register A | `STORE R3, R1` |\n| `DATA Ra, \u003cVALUE\u003e`  | Machine   | Put `\u003cVALUE\u003e`  into register A. `\u003cVALUE\u003e` can either be a symbol, prefixed with `%` (e.g. `%LINE-X`) or a numeric value (e.g. `0x00F2` or `23`)  | `DATA R3, %KEYCODE` |\n| `JR Ra`  | Machine   | Jump to instruction in memory address in register A | `JR R2` |\n| `JMP \u003cLABEL\u003e`  | Machine   | Jump to instruction in memory address for `\u003cLABEL\u003e` | `JMP startloop` |\n| `JMP[CAEZ]+ \u003cLABEL\u003e`  | Machine  | Jump to instruction in memory address for `\u003cLABEL\u003e` if flags register for any combination of `CAEZ` is true | `JMPEZ endloop` |\n| `CLF`  | Machine  | Clear contents of flags register | `CLF` |\n| `IN \u003cMODE\u003e, Ra`  | Machine  | Request input from IO device to Register A | `IN Data, R3` |\n| `OUT \u003cMODE\u003e, Ra`  | Machine  | Send output to IO device for register A | `OUT Addr, R2` |\n| `ADD Ra, Rb`   | Machine  | 16 bit addition of two registers | `ADD R0, R2` |\n| `SHR Ra`   | Machine  | Shift right register A | `SHR R0` |\n| `SHL Ra`   | Machine  | Shift left register A | `SHL R0` |\n| `NOT Ra`   | Machine  | Bitwise NOT on register A | `NOT R2` |\n| `AND Ra, Rb`   | Machine  | Bitwise AND on two registers | `AND R2, R3` |\n| `OR Ra, Rb`   | Machine  | Bitwise OR on two registers | `OR R0, R1` |\n| `XOR Ra, Rb`   | Machine  | Bitwise XOR on two registers | `XOR R1, R0` |\n| `CMP Ra, Rb`   | Machine  | Compare register A and register B (will set flags register) | `CMP R1, R2` |\n| `CALL \u003cLABEL\u003e`   | Pseudo | Call a subroutine. This will jump to the subroutine, on completion, the subroutine should jump back and continue from the next instruction. Note: there is no stack functionality here so all registers may be in a different state at the end of the subroutine. | `CALL pollKeyboard` |\n\n# I/O devices\n\nThe following I/O devices are supported by the computer.\n\n\n| Device | Address |\n| -------------- | ------------- | \n| Keyboard |  `0x000F` |\n| Display |  `0x0007` |\n\n\n# Memory layout\n\nThere is no memory management unit or protected areas of memory.\n\nHowever the [assembler](cmd/assembler/) and simulator will start executing user code from offset `0x0500`\n\n# Assembler\n\nMachine code can be written in text and assembled using a crude assembler I wrote.\n\nSee [assembler](cmd/assembler/) for more information.\n\n# Compiler\n\n[@realkompot](https://github.com/realkompot) made an awesome compiler https://github.com/realkompot/llvm-project-scott-cpu for this using LLVM that produces working binaries to run on the simulator, check out the cool little snake game example https://github.com/realkompot/llvm-project-scott-cpu/tree/scott-cpu/_scott-cpu\n\n# Building\n\nRequirements\n\n* go 1.12+\n* GLFW 3.2+\n\n\nBuilding:\n\n```\nmake\n```\n\nThere are some unit tests that take 30-45 seconds to run through, by running \n\n```\nmake test\n```\n\n# Running\n\nThe computer can be run using the wrapper tool I wrote that utilises GLFW for I/O functionality.\n\nExample of running the `brush.bin` program\n\n```\n./bin/simulator -bin _programs/brush.bin\n```\n\n\n# Example programs\n\nYou can see some example programs I wrote under [_programs/](/_programs/), note the ASM code I wrote for these is very bad and I lost my sanity a bit when writing them.\n\n\n# Why bother? \n\nI'm taking myself on a journey, a hardware journey you might say. I want to understand how computers work at a lower level but not quite low enough for the physics/digital electronics side of things. \n\nJust enough to see all the pieces of the system interacting. I remember doing a lot of this stuff in school but I'd say my education seemed to focus on the concepts (Von-Neumann architecture, fetch-decode-execute) rather than the actual construction of a CPU. \n\nThis simple computer is the start of that journey, it's actually been a very rewarding little project.\n\nI hope to move onto playing around with X86/ARM/RISC-V next although I suspect it will be quite a leap (of faith)\n\n","funding_links":[],"categories":["Go","Programming Language Tutorials"],"sub_categories":["For Scala"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjhworld%2Fsimple-computer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdjhworld%2Fsimple-computer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjhworld%2Fsimple-computer/lists"}