102 lines
3.4 KiB
Markdown
102 lines
3.4 KiB
Markdown
# Implementation of brainfuck as a processor
|
|
|
|
## The processor
|
|
|
|
### VHDL / FPGA
|
|
|
|
#### Instruction vs. clock cycle
|
|
|
|
Every instruction cycle is lasting two clock cycles and is divided into two phases:
|
|
|
|
1. Execution
|
|
2. Write back
|
|
|
|
During **execution**, the alu computes the updated pointer position and cell value, or assigns the new values from and to the pins.
|
|
The branch disables the program counter during this cycle and executes the first step of the branch commands [ and ].
|
|
|
|
During the second cycle, the **write back** cycle, the registers are updated, the branch restores the stack and reenables the program counter.
|
|
When processing an branch-instruction, the jump signal is also set and the stack is updated.
|
|
|
|
#### Brainfuck logic
|
|
|
|
The brainfuck logic consists of three parts
|
|
|
|
1. An array with ~60k byte-sized registers as required by the brainfuck language (actually, twice the required cells)
|
|
2. A pointer with the size of two bytes to address this array, also required by brainfuck
|
|
3. The ALU computing the follwing instructions: ><+-,.
|
|
|
|
#### Instruction set and memory
|
|
|
|
The instruction memory can hold up to 256 instructions, which are currently hardcoded in the instruction memory source.
|
|
|
|
The instructions are direct translations of the 8 brainfuck operands:
|
|
|
|
| Brainfuck | Binary |
|
|
| --------- | ------ |
|
|
| > | 000 |
|
|
| < | 001 |
|
|
| + | 010 |
|
|
| - | 011 |
|
|
| , | 100 |
|
|
| . | 101 |
|
|
| [ | 110 |
|
|
| ] | 111 |
|
|
|
|
Every instruction is calculated in two clock cycles, or one instruction cycle.
|
|
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
## The compiler
|
|
|
|
The compiler located in the directory *bfpcompiler* can be used to create the machine code for the different destinations.
|
|
|
|
### Building the compiler
|
|
|
|
Assuming the root directory as current location, use the follwing commands to build the executable:
|
|
|
|
```shell
|
|
cd bfpcompiler
|
|
make
|
|
```
|
|
|
|
The executable will be located in the directory *bfpcompiler*.
|
|
|
|
### Usage
|
|
|
|
The executable can be called as
|
|
|
|
```shell
|
|
./bfc [-o filename] [-d device="logisim"] filename.bf
|
|
```
|
|
|
|
### Syntax check
|
|
|
|
The compiler is proofen to detect any error in an entered program.
|
|
This is fairly easy, as only loop errors (wrong order or count of brackets) could make a program invalid.
|
|
|
|
The compiler reacts to the following problems:
|
|
|
|
| Problem | Reaction |
|
|
| --------------------------------------- | -------- |
|
|
| Closing bracket outside loop | ERROR |
|
|
| Loop not closed at the end of a program | ERROR |
|
|
| Loop opened inside another loop | WARNING |
|
|
|
|
The last warning occurs, because the logisim implementation of the processor is not capable of processing nested loops.
|
|
It can be safely ignored on other devices.
|
|
|
|
### Code is correct by proof
|
|
|
|
The proof is located at *bfpcompiler/proof.md* and will be expanded on the whole compiler.
|
|
The proofs cover three claims:
|
|
|
|
- The compiler is working absolutely memory safe
|
|
- Every program accepted by the compiler is a valid brainfuck program
|
|
- The compiled program is working in the same way, as the entered brainfuck code
|
|
|
|
## Repository location
|
|
|
|
The original repository with the most recent code is located at [My personal gitlab](https://gitlab.schnick.duckdns.org/schnick/bfpu).
|
|
|
|
As this instance has some problems with staying online, the master-branch is mirrored to Github at [this repository](https://github.com/yannickreiss/brainfuck_processor).
|