← back to the programs

The Roc machine

Each program on the page is a test from Cobblestone, an operating system written in Codex. In Cobblestone's own test runs these programs are compiled to x86 and run in QEMU or in codex-vm, Cobblestone's emulator. Here they run on a machine written in Roc instead, and this page describes that machine.

What runs, and what does not

rocemit turns each Codex program into Roc, one module for the test and one for each Codex chapter it uses; the page's Roc pane shows them. That Roc is built for WebAssembly together with the machine. Nothing here imitates x86 instructions. Cobblestone's lowest layer (booting, interrupts, the scheduler) is x86 code that Codex's compiler writes, not Codex, so the machine stands in for it.

One value holding every device

The machine is a single Roc record with a field for each device. Every Codex builtin that touches hardware, such as reading a disk sector, writing a byte to an I/O port or sending a network frame, becomes a function that takes the machine and hands back the machine as it is afterwards. The program passes the machine along from call to call, so a run is an ordinary Roc computation from the first machine to the last.

What "boot" means here

A run starts from the state that Cobblestone's x86 boot code leaves behind, and nothing more:

The machine puts no files, programs or data anywhere. Whatever a program finds, it brought with it.

Where a program's inputs come from

A Cobblestone test is a .codex file with an .expected file beside it holding the output it must print. It may also bring:

fat16-list's files are on its disk image. fat16-list.disk is a 16 MB image committed beside the test in Cobblestone's tree. It is partitioned like a boot disk, and its partition holds a FAT16 volume with an EFI directory, EFI/BOOT/BOOTX64.EFI and CODEX.CDX. The page fetches the image and loads it into drive 0 before the run; the program's FAT16 code, which is Codex turned into Roc, reads the partition table, the file allocation table and the directory sectors through the disk. fat16-write brings an image of its own, writes a file into the page's copy of it, and the Disk pane shows the sectors that changed. Reloading the page starts from the original image again.

The devices

devicewhat the machine does
memoryBytes addressed up to 236, stored sparsely, so a program can use the addresses Cobblestone's kernel uses. An address no device claims stops the run by name.
disk drivesThe IDE channel, the classic PC disk interface: two drive positions, each an image or empty, answering the commands to read a sector, write a sector and identify the drive. On this page a drive is the page's copy of the image, read and written a sector at a time.
PCI configuration spaceThe table a driver scans to discover what hardware is plugged in, with the devices codex-vm lists.
NE2000 network cardThe card's registers, its 32 KB of on-card memory and its receive ring, as codex-vm models them.
the network behind the cardA small stand-in for codex-vm's network address translation: it answers ARP (which hardware address has this IP address?) and DHCP (please give me an IP address) itself. Anything that would need the real internet, such as a DNS lookup or a TCP connection, stops the run with a message saying so.
Intel e1000 network cardThe other card codex-vm offers, with its fault-injection options, for the tests that choose it.
timersThe PIT, the HPET and the local APIC timer, the PC's three timer chips, counting the machine's own clock rather than wall time.
keyboardA queue of the keystrokes a test brings, delivered as the clock reaches them.
screencodex-vm's framebuffer: a block of ordinary memory at a fixed address that a program draws into, four bytes a pixel. A test's -gop flags choose its width, height and how many pixels each row takes in memory. When the run ends, the page draws what the program left there.
consoleThe lines a program prints, which is what its test checks.

A program that reaches a device codex-vm has and this machine does not, such as the real-time clock or the Bochs graphics adapter, stops with a message naming that device rather than getting a made-up answer.

The machine's clock

Time on the machine is a counter: every access to a device register moves it forward 10 microseconds, and reading or writing plain memory does not. A run therefore takes the same machine time on every computer, which is what lets tests that measure time pass here.

What is hand-written

The machine is hand-written Roc, in roc-apps/machine/roc, one module per device. The programs are not: their Roc is exactly what rocemit wrote from the Codex source, apart from three lines connecting the program to the page.