2026-01-19 07:28:14 +00:00

395 lines
8.2 KiB
Markdown

< [Back](chapter-1.md) | [Summary](table-of-contents.md) | [Next](chapter-3.md) >
# ⚙️ ** PVM (PROMETEU VM) — Instruction Set**
## 1. Overview
The **PROMETEU VM** is a mandatory virtual machine always present in the logical hardware:
* **stack-based**
* deterministic
* cycle-oriented
* designed for teaching and inspection
It exists to:
* map high-level language concepts
* make computational cost visible
* allow execution analysis
* serve as the foundation of the PROMETEU cartridge
> The PROMETEU VM is simple by choice.
> Simplicity is a pedagogical tool.
---
## 2. Execution Model
### 2.1 Main Components
The VM has:
* **PC (Program Counter)** — next instruction
* **Operand Stack** — value stack
* **Call Stack** — frame stack
* **Heap** — dynamic memory
* **Globals** — global variables
* **Constant Pool** — literals and references
* **ROM** — cartridge bytecode
* **RAM** — mutable data
---
### 2.2 Execution Cycle
Each instruction executes:
```
FETCH → DECODE → EXECUTE → ADVANCE PC
```
Properties:
* every instruction has a fixed cost in cycles
* there is no invisible implicit work
* execution is fully deterministic
---
## 3. Fundamental Types
| Type | Description |
| --------- | ------------------------- |
| `integer` | 64-bit signed integer |
| `float` | 64-bit floating point |
| `boolean` | true/false |
| `string` | immutable UTF-8 |
| `null` | absence of value |
| `ref` | heap reference |
Do not exist:
* magic coercions
* implicit casts
* silent overflows
---
## 4. Stack Conventions
* Operations use the top of the stack
* Results always return to the stack
* Last pushed = first consumed
Example:
```
PUSH_CONST 3
PUSH_CONST 4
ADD
```
State:
```
[3]
[3, 4]
[7]
```
---
## 5. Instruction Categories
1. Flow control
2. Stack
3. Arithmetic and logic
4. Variables
5. Functions
6. Heap and structures
7. Peripherals (syscalls)
8. System
---
## 6. Instructions — VM Set 1
### 6.1 Execution Control
| Instruction | Cycles | Description |
| ------------------- | ------ | ------------------------- |
| `NOP` | 1 | Does nothing |
| `HALT` | 1 | Terminates execution |
| `JMP addr` | 2 | Unconditional jump |
| `JMP_IF_FALSE addr` | 3 | Jumps if top is false |
---
### 6.2 Stack
| Instruction | Cycles | Description |
| -------------- | ------ | ------------------- |
| `PUSH_CONST k` | 2 | Pushes constant |
| `POP` | 1 | Removes top |
| `DUP` | 1 | Duplicates top |
| `SWAP` | 1 | Swaps two tops |
---
### 6.3 Arithmetic
| Instruction | Cycles |
| ----------- | ------ |
| `ADD` | 2 |
| `SUB` | 2 |
| `MUL` | 4 |
| `DIV` | 6 |
---
### 6.4 Comparison and Logic
| Instruction | Cycles |
| ----------- | ------ |
| `EQ` | 2 |
| `NEQ` | 2 |
| `LT` | 2 |
| `GT` | 2 |
| `AND` | 2 |
| `OR` | 2 |
| `NOT` | 1 |
---
### 6.5 Variables
| Instruction | Cycles | Description |
| -------------- | ------ | ---------------- |
| `GET_GLOBAL i` | 3 | Reads global |
| `SET_GLOBAL i` | 3 | Writes global |
| `GET_LOCAL i` | 2 | Reads local |
| `SET_LOCAL i` | 2 | Writes local |
---
### 6.6 Functions
| Instruction | Cycles | Description |
|----------------| ------ |---------------------------------|
| `CALL addr` | 5 | Call |
| `RET` | 4 | Return |
| `PUSH_SCOPE n` | 3 | Creates scope (execution frame) |
| `POP_SCOPE` | 3 | Removes scope |
---
### 6.7 Heap
| Instruction | Cycles | Description |
| --------------- | ------ | --------------- |
| `ALLOC size` | 10 | Allocates on heap |
| `LOAD_REF off` | 3 | Reads field |
| `STORE_REF off` | 3 | Writes field |
Heap is:
* finite
* monitored
* accounted for in the CAP
---
### 6.8 Peripherals (Syscalls)
| Instruction | Cycles | Description |
|--------------| -------- | --------------------- |
| `SYSCALL id` | variable | Call to hardware |
#### Implemented Syscalls (v0.1)
| ID | Name | Arguments (Stack) | Return |
| ---------- | ----------------- | ---------------------------- | ------- |
| `0x0001` | `system.has_cart` | - | `bool` |
| `0x0002` | `system.run_cart` | - | - |
| `0x1001` | `gfx.clear` | `color_idx` | - |
| `0x1002` | `gfx.draw_rect` | `x, y, w, h, color_idx` | - |
| `0x2001` | `input.get_pad` | `button_id` | `bool` |
| `0x3001` | `audio.play` | `s_id, v_id, vol, pan, pitch`| - |
**Button IDs:**
- `0`: Up, `1`: Down, `2`: Left, `3`: Right
- `4`: A, `5`: B, `6`: X, `7`: Y
- `8`: L, `9`: R
- `10`: Start, `11`: Select
---
## 7. Execution Errors
Errors are:
* explicit
* fatal
* never silent
Types:
* stack underflow
* invalid type
* invalid heap
* invalid frame
Generate:
* clear message
* state dump
* stack trace
---
## 8. Determinism
Guarantees:
* same input → same result
* same sequence → same cycles
* no speculative execution
* no invisible optimizations
> If you see the instruction, you pay for it.
---
## 9. Relationship with Languages
Java, TypeScript, Lua etc:
* are source languages
* compiled to this bytecode
* never executed directly
All run on the **same VM**.
---
## 10. Example
Source:
```java
x = 3 + 4;
```
Bytecode:
```
PUSH_CONST 3
PUSH_CONST 4
ADD
SET_GLOBAL 0
```
Cost:
```
2 + 2 + 2 + 3 = 9 cycles
```
---
## 11. Execution per Tick
The VM does not run infinitely.
It executes:
* until consuming the **logical frame** budget
* or until `HALT`
The budget is defined by the PROMETEU logical hardware (e.g., `CYCLES_PER_FRAME`).
Example:
```
vm.step_budget(10_000)
```
This feeds:
* CAP
* profiling
* certification
---
## 12. Logical Frame and `FRAME_SYNC`
PROMETEU defines **logical frame** as the minimum unit of consistent game update.
* **Input is latched per logical frame** (does not change until the logical frame is completed).
* The **cycle budget** is applied to the logical frame.
* A new logical frame only starts when the current frame ends.
### 12.1 System Instruction: `FRAME_SYNC`
The `FRAME_SYNC` instruction marks the **end of the logical frame**.
| Instruction | Cycles | Description |
| ------------ | ------ | ---------------------------------- |
| `FRAME_SYNC` | 1 | Finalizes the current logical frame |
Properties:
* `FRAME_SYNC` is a **system instruction**.
* It should not be exposed as a "manual" API to the user.
* Tooling/compiler can **inject** `FRAME_SYNC` automatically at the end of the main loop.
### 12.2 Semantics (what happens when it executes)
When executing `FRAME_SYNC`, the core:
1. **Finalizes** the current logical frame.
2. **Presents** the frame (`gfx.present()` or `gfx.compose_and_present()` depending on the GFX model).
3. **Releases** the input latch.
4. **Resets** the budget for the next logical frame.
### 12.3 Overbudget (when the frame doesn't finish on time)
If the logical frame budget runs out **before** the VM reaches `FRAME_SYNC`:
* the VM **pauses** (PC and stacks remain at the exact point)
* there is **no present**
* the input latch is **maintained**
* on the next host tick, the VM **continues** from where it left off, still in the same logical frame
Practical effect:
* if the code needs 2 budgets to reach `FRAME_SYNC`, the game updates at ~30 FPS (logical frame takes 2 ticks)
* this is deterministic and reportable in the CAP
---
## 15. Extensibility
The Instruction Set is versioned.
Future:
* DMA
* streaming
* vectors
* fictitious coprocessors
No existing instruction changes its meaning.
---
## 16. Summary
* stack-based VM
* explicit cost
* deterministic execution
* integrated with CAP
* foundation of every PROMETEU cartridge
< [Back](chapter-1.md) | [Summary](table-of-contents.md) | [Next](chapter-3.md) >