71 lines
3.8 KiB
Markdown
71 lines
3.8 KiB
Markdown
# 扫描周期
|
||
|
||
vm 模块:寄存器虚拟机(V2:变长指令 / 槽表两级 / 栈方案 C)。CMake 目标:`vm`(`STATIC`),只依赖 [`指令与映像.md`](../isa/指令与映像.md)。
|
||
|
||
运行时是 **一台 VM、一个入口、一份映像**。不链接 `compiler`。扫描周期与确定性见 [`初步计划.md`](../初步计划.md) 第 2、8 节。
|
||
|
||
## 扫描周期
|
||
|
||
```text
|
||
1. 按 sidecar 的 io 绑定,采样 → I / 输入全局(executor 写值区槽)
|
||
2. 从 PROGRAM MAIN 的 pc=0 执行到 RET
|
||
3. 写回 Q / 输出全局(executor 读值区槽)
|
||
4. 用本周期 Δt(映像头 dt_ms)推进内置 FB(不用 wall clock);RTC 用累计周期数
|
||
```
|
||
|
||
## 边界
|
||
|
||
- 只认 `.stb` 映像(`vm` 自带读实现);读取时**型号标识匹配(STATOR2)+ SHA-256 校验**,不符/篡改 → 拒绝
|
||
- 类型与溢出按 [`指令与映像.md`](../isa/指令与映像.md)(整数饱和 / 除法 A / 浮点 IEEE);指令定义归 `isa`
|
||
- 局部 / `VAR` = 固定寄存器;`nregs` 在函数头;栈区预分配(`max_stack`,编译期 DAG 最坏路径)
|
||
- `CALL` 目标是立即数 `fn_id`,有界调用栈(深度 64 双检查)
|
||
- 无 GC、无堆、无线程;每周期受 `cycle_limit` 限制
|
||
- I/O 从哪来、Δt 谁给、回放怎么喂,属于 `BytecodeExecutor`(读 `.stb` + sidecar)
|
||
|
||
---
|
||
|
||
## 可观察性接口(v1 预留)
|
||
|
||
TUI 是执行器(`BytecodeExecutor`)的界面,用途是方便观察 VM 运行状态。**v1 不做 TUI**,只预留接口,避免后续改 VM 的观察面。原则:
|
||
|
||
- **数据与展示分离**:`vm` 只提供只读观察 API(数据);TUI 渲染与文本输出属于 `executor`(展示)。vm 不画任何界面。
|
||
- **只读轮询**:TUI 通过快照轮询,绝不写 VM 状态;"继续 / 单步"是 executor 侧命令,不改变确定性。
|
||
- **快照 POD 化**:快照保持简单数据(将来跨进程 TUI 可序列化)。
|
||
|
||
已落地的观察面(`Machine` 公共接口):
|
||
|
||
```cpp
|
||
bool step(); // 精确执行一条指令,停在指令边界
|
||
Fault fault() const; // 最近一次故障
|
||
bool ended() const; // 周期是否已结束
|
||
uint32_t pc() const; // 当前 pc(字节,相对本帧函数)
|
||
uint32_t fn_id() const; // 当前函数
|
||
uint32_t cycle_count() const; // 本周期已执行指令数
|
||
uint32_t call_depth() const; // 调用栈深度
|
||
uint8_t* data(); // 值区(I 采样 / Q 读回由外部做)
|
||
uint32_t slot_addr(uint32_t slot) const; // 槽 → 值区偏移(槽表两级)
|
||
int64_t reg(uint8_t i) const; // 当前帧寄存器
|
||
const uint8_t* cur_instr_bytes() const; // 当前指令首字节(单步反汇编用)
|
||
uint32_t cur_instr_len() const; // 当前指令长度(变长)
|
||
```
|
||
|
||
- 寄存器 ≤256、映像很小,快照拷贝成本可忽略。
|
||
- 单步、回放、dump 都建立在同一套观察 API 上。
|
||
|
||
---
|
||
|
||
## V2 落地状态
|
||
|
||
| 项 | 状态 |
|
||
|---|---|
|
||
| 变长取指(4/8/16/32B,前缀分区)+ 字节 pc | ✅ `Machine.cpp` exec_one |
|
||
| 槽表两级(slot → addr → 值区变宽紧凑)+ LOAD_OFF/STORE_OFF | ✅ |
|
||
| 栈方案 C(预分配 max_stack、帧头 12B、r0..r7 复制、深度 64 双检查) | ✅ do_call/do_ret |
|
||
| 19 类型 func 驱动(整数饱和 / 无符号 / F32 / F64 IEEE) | ✅ exec_arith/exec_cmp |
|
||
| CAL 15 条(TON/TOF/TP/CTU/DCTU/CTD/DCTD/CTUD/DCTUD/R_TRIG/F_TRIG/SR/RS/PWM/RTC) | ✅ do_cal |
|
||
| 故障(None/CycleLimit/StackOverflow/BadOp/BadSlot/BadConst) | ✅ |
|
||
| 边沿缓冲 edge_prev_(每槽 2 字节,跨周期) | ✅ |
|
||
| 确定性:同一 I 序列跑两遍,数据区完全一致 | ✅ vm_test |
|
||
|
||
指令执行语义(帧/调用栈、指令表、定时器、故障、line1 推演)见 [`指令执行.md`](指令执行.md)。
|