Files
Interpreter/Doc/vm/扫描周期.md
T
Admin 6873b5ee0b 文档同步:machine.toml 配置驱动架构收尾。
- README.md:依赖方向(STCompiler→compiler 不链 isa)、模块表、isa 归执行器侧、
  数据流图(machine.toml + 型号/SHA)
- isa/README.md:重写——只管指令定义(Types/Op/Instr/Encode),删 Image 部分
- 指令与映像.md:依赖图与 CMake(compiler 不链 isa)
- 编译管线.md:管线首步加载 machine.toml、产物含型号/SHA
- 初步计划.md:12.10/12.13 修订(--machine、依赖方向)
- 扫描周期.md / 指令执行.md:12.9 步骤标注已落地、vm 读校验说明
- compiler/vm/executor README:依赖与边界同步
2026-08-21 22:39:27 +08:00

123 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 扫描周期
vm 模块:寄存器虚拟机。CMake 目标:`vm``STATIC`),只依赖 [`指令与映像.md`](../isa/指令与映像.md)。
运行时是 **一台 VM、一个入口、一份映像**。不链接 `compiler`。扫描周期与确定性见 [`初步计划.md`](../初步计划.md) 第 2、8 节。
## 扫描周期
```text
1. 按 sidecar 的 io 绑定,采样 → I / 输入全局
2. 从 PROGRAM MAIN 的 pc=0 执行到 RET
3. 写回 Q / 输出全局
4. 用本周期 Δt 推进内置 FB(不用 wall clock
```
## 边界
- 只认 `.stb` 映像(`vm` 自带读实现);读取时**型号标识匹配 + SHA-256 校验**,不符/篡改 → 拒绝
- 类型与溢出按 [`指令与映像.md`](../isa/指令与映像.md)`INT` 饱和);指令定义归 `isa`
- 局部 / `VAR` = 固定寄存器;`nregs` 在函数头
- `CALL` 目标是立即数 `fn_id`,有界调用栈
- 无 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 可序列化)。
建议的 API 形态(12.9 实现时冻结签名,本节只定方向):
```cpp
struct Snapshot {
uint32_t pc; // 当前指令下标(相对函数字节码段)
uint32_t fn_id; // 当前函数
uint32_t cycle_count; // 本周期已执行指令数
uint32_t call_depth; // 调用栈深度
// 寄存器 / I / Q / M / 全局 / FB 字段 的只读视图
};
bool step(); // 精确执行一条指令,停在指令边界
const Snapshot& snapshot() const;
```
- 寄存器 ≤256、映像很小,快照拷贝成本可忽略。
- 单步、回放、dump 都建立在同一套观察 API 上。
---
## 12.9 执行计划
指令执行语义(帧/调用栈、指令表、定时器、故障、line1 推演)见 [`指令执行.md`](指令执行.md)。
### 步骤 0:数据段改 8 字节定宽槽(方案 a,前置)
VM 需要无歧义地访问数据区,当前变宽布局(BOOL 1B / INT 2B / TIME 8B 对齐)无法从槽号推断宽度。定案:**每槽 8 字节定宽**,指令 slot 语义 = **槽号**(数据偏移 = slot × 8)。
- 文档修订:`Doc/isa/指令与映像.md`(数据段规则 + slot 语义)、`Doc/compiler/寄存器码.md`(存储布局,`global_offset` 映射取消)、`Doc/isa/stb文件格式.md`line1 数据段 16B → 56B
- `Codegen.cpp` 简化:`width_of`/`align_up` 删除、`layout_data`/`layout_fb_instances` 按槽号布局、指令 slot = 符号表槽号
- `codegen_test` 断言更新(slot 从字节偏移变槽号、数据区字节数变化)
### 步骤 1`Machine.h`(已落地 `vm/include/vm/Machine.h`
```cpp
namespace vm {
enum class Fault { None, CycleLimit, StackOverflow, BadOp, BadSlot, BadConst };
class Machine {
public:
static bool create(const std::vector<uint8_t>& image, Machine* out, std::string* err);
Fault run_cycle(); // MAIN pc=0 → RETMAIN 帧跨周期保留)
// 可观察性(v1 预留,见上节):
bool step(); // 执行一条指令,停在指令边界
uint32_t pc() / fn_id() / cycle_count() / call_depth();
uint8_t* data(); // 数据区(I 采样 / Q 读回由外部做)
int64_t reg(uint8_t i); // 当前帧寄存器
};
}
```
- `Fault` 枚举 + 帧结构 `{ fn_id, regs[nregs], ret_pc, ret_fn_id }`;调用栈深度上限 64
- 只依赖 `isa`(指令定义)+ 自带 `vm::Image`.stb 读)
### 步骤 2`Machine.cpp` 译码 switch(已落地)
- 取指:函数表 → `code_offset`(字节)→ 读 u32 → 拆 `op/rd/a/b`
- 标量:`MOVE` / `LOADK`(常量表 tag 定值表示)/ `NOT` / `AND` / `OR`(布尔)/ `ADD/SUB/MUL/DIV``sat_*`/ `CMP_xx`(全宽比较)
- 跳转:`JMP` / `JT` / `JF``pc += off`,相对下一条语义)
- 数据区:`LOAD_I/LOAD_M/LOAD_GLOBAL``STORE_Q/STORE_M/STORE_GLOBAL`(同一实现,slot × 8
### 步骤 3CALL / RET 帧栈 + 故障(已落地)
- `CALL fn_id`:压新帧(复制 r0..r7)→ pc=0`RET`:复制 r0..r7 回调用方 → 弹栈(MAIN 的 RET = 周期结束)
- `cycle_limit` 超限(用例 6)、栈深 > 64、`BadOp` / `BadSlot` / `BadConst` → 周期中止返回故障
### 步骤 4:定时器与边沿(已落地)
- 执行时用映像 `dt_ms` 推进(每周期一次调用 = 推进一次),不读系统时钟
- TONin 真 → et += dt(到 pt 停)、q = et ≥ ptin 假 → et = 0
- TOFin 真 → q=1、et=0;掉电 → et += dt、et ≥ pt → q=0
- CTUcu 上升沿(**上次 cu 存 VM 侧 vector**,按实例基槽索引)→ cv+1r → 复位;q = cv ≥ pv
### 步骤 5:可观察性基础(已落地)
- `step()` / `pc` / `fn_id` / `cycle_count` / `call_depth` / `reg` 落基础实现;`snapshot()` 留 12.11 补全
### 步骤 6`vm_test`(已落地)
- 手工拼小映像(`isa` 编码函数):赋值、跳转、CALL/RET 帧复制、cycle_limit
- 编译器产物全链路:用例 01/02/04/05/07/09/13/15/17/18/20 跑周期断言寄存器与数据区
- 用例 06`cycle_limit` 打满 → `CycleLimit` 故障
- TONdt=10、pt=30 → 第 3 周期 q=1CTU:上升沿计数
- **确定性**:同一 I 序列跑两遍,数据区完全一致
### 步骤 7:验证 + 提交(已落地,ctest 14/14
- `cmake --build` + `ctest`(新增 `vm_cycles` 后 10/10 全绿);20 用例扫描:14 正例执行通过