Files
wipforth/README.md
Camden Dixie O'Brien 2a3949e09f Make terminal xHEAD and xTAIL registers 32 bits
This enables waiting on them with memory.atomic.wait32 (there is no
wait8) which is needed to avoid spinning when waiting for a key.
2026-03-02 18:51:42 +00:00

74 lines
2.3 KiB
Markdown

# Wipforth
Wipforth is a simple Forth implementation that runs in the WebAssembly
virtual machine. It does I/O via memory-mapped peripherals, which are
emulated in JavaScript.
- For the Forth kernel, see [wipforth.wat](./wipforth.wat)
- For the JavaScript emulator, see [emu.js](./emu.js)
- For the Forth prelude, which is loaded at start-up, see
[prelude.f](./prelude.f)
- For a description of the peripherals, see the
[Peripherals](#peripherals) section below.
## Building and Running Locally
You'll need:
- [WABT](https://github.com/WebAssembly/wabt)
- [Guile](https://www.gnu.org/software/guile/) (or bring your own HTTP
server -- see note below)
To run, first compile the WebAssembly module:
```
wat2wasm --enable-threads wipforth.wat
```
Then run the development server:
```
guile server.scm
```
You should then be able to open <http://localhost:8080> in a browser
and use the system from there.
**NOTE**: The server is very simple and just serves the files with the
cross-origin isolation headers required for `SharedMemoryBuffer` use.
You could use any HTTP server that sets these headers.
## Peripherals
### Terminal
| Name | Address | Size / B | Access |
|--------|---------|----------|--------------|
| TXBUF | 00h | 32 | write |
| RXBUF | 20h | 32 | read |
| TXHEAD | 40h | 4 | atomic read |
| TXTAIL | 44h | 4 | atomic write |
| RXHEAD | 48h | 4 | atomic write |
| RXTAIL | 4Ch | 4 | atomic read |
For both sending (`TX`) and receiving (`RX`), there are three
registers: `xBUF`, `xHEAD` and `xTAIL`:
- `xBUF` registers are 32-byte FIFO ring buffers used for data
- The `xHEAD` and `xTAIL` registers specify the start and end of data
in the ring buffer, `xHEAD` being the offset of the first byte of
data, and `xTAIL` being the offset of the first byte *after* the data.
In order to be distinguishable from the empty state, the ring buffers
must never be completely full -- there must always be *at least one*
unoccupied byte between the tail and the head.
### System status
| Name | Address | Size / B | Access |
|----------|---------|----------|--------------|
| SYSREADY | 50h | 1 | atomic write |
The `SYSREADY` register is used to indicate when the system has booted
up and is ready for user input.