12.9 步骤 1:VM 头文件(API、Fault 枚举、帧结构)。

- Machine.h:create/run_cycle + 可观察性(step/pc/fn_id/cycle_count/call_depth/data/reg)
- Fault:None/CycleLimit/StackOverflow/BadOp/BadSlot/BadConst
- 帧 { fn_id, regs[nregs], ret_pc, ret_fn_id },调用栈深度 64,MAIN 帧跨周期保留
- ctu_prev_ 预留(步骤 4);exec_one/do_call/do_ret/do_cal 桩
This commit is contained in:
2026-08-21 20:12:43 +08:00
parent ce948451e0
commit 815eb87a46
+111
View File
@@ -0,0 +1,111 @@
/**
* @file Machine.h
* @brief 寄存器虚拟机(12.9
* @author
* @date 2026-08-21
*
* @details 设计说明(详见 Doc/vm/扫描周期.md 与 Doc/vm/指令执行.md):
* - 只认 isa 映像(ImageView);无 GC、无堆、无线程
* - 扫描周期:MAIN pc=0 → RET;MAIN 帧跨周期保留,调用栈深度上限 64
* - 帧:{ fn_id, regs[nregs], ret_pc, ret_fn_id }CALL 压帧复制 r0..r7
* RET 复制回调用方(r0=结果)
* - 数据区:8 字节定宽槽(方案 a),指令 slot = 槽号,偏移 = slot × 8
* - 可观察性(v1 预留):step / pc / fn_id / cycle_count / call_depth / reg
*/
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "isa/Image.h"
namespace vm {
// 周期/指令故障
enum class Fault {
None, // 正常
CycleLimit, // 本周期指令数超过映像头 cycle_limit(用例 6
StackOverflow, // 调用栈深度超过 64
BadOp, // 非法操作码(op ≥ 29
BadSlot, // slot × 8 + 8 越出数据区
BadConst, // const_id 越出常量表
};
class Machine {
public:
/**
* @brief 从映像字节构建机器(校验 + 拷贝数据段 + 建 MAIN 帧)
* @param image .stb 映像字节
* @param out 输出 Machine(未初始化)
* @param err 错误输出;可为 nullptr(静默)
* @return true 成功;false(映像非法,err 已写)
*/
static bool create(const std::vector<uint8_t>& image, Machine* out,
std::string* err);
/**
* @brief 跑一个扫描周期:MAIN pc=0 执行到 RET
* @return 故障(None = 正常完成);调用栈清空但 MAIN 帧保留
*/
Fault run_cycle();
// ---- 可观察性(v1 预留,12.11 供单步/回放/TUI----
/**
* @brief 执行一条指令,停在指令边界
* @return true 继续;false 周期结束(MAIN 的 RET)或发生故障
*/
bool step();
/** @brief 最近一次故障(step 返回 false 后查询) */
Fault fault() const;
/** @brief 当前指令下标(相对当前函数字节码段) */
uint32_t pc() const;
/** @brief 当前函数 fn_id */
uint32_t fn_id() const;
/** @brief 本周期已执行指令数 */
uint32_t cycle_count() const;
/** @brief 调用栈深度(MAIN 帧 = 1 */
uint32_t call_depth() const;
/** @brief 数据区(I 采样写入 / Q 读回由外部做;8 字节定宽槽) */
uint8_t* data();
const uint8_t* data() const;
/** @brief 数据区字节数 */
size_t data_len() const;
/** @brief 当前帧寄存器值(i < nregs */
int64_t reg(uint8_t i) const;
private:
struct Frame {
uint32_t fn_id = 0; // 本帧函数
std::vector<int64_t> regs; // 寄存器文件(大小 = 函数头 nregs)
uint32_t ret_pc = 0; // CALL 的下一条(非 MAIN 帧有意义)
uint32_t ret_fn_id = 0; // 返回目标函数
};
isa::ImageView image_; // 映像只读视图
std::vector<uint8_t> data_; // 数据区工作副本(8 字节定宽槽)
std::vector<Frame> frames_; // 调用栈([0] = MAIN,跨周期保留)
std::vector<uint8_t> ctu_prev_; // CTU 上次 cu(按实例基槽索引,12.9 步骤 4)
uint32_t pc_ = 0; // 当前 pc(相对本帧函数字节码段)
uint32_t cycle_count_ = 0; // 本周期指令数
Fault fault_ = Fault::None; // 最近一次故障
bool ended_ = false; // step 后周期是否已结束
Frame& cur_frame();
const Frame& cur_frame() const;
bool exec_one(); // 译码执行一条(12.9 步骤 2/3/4 填充)
Fault do_call(uint32_t fn_id); // 压帧;BadFn 用 BadOp 表示
Fault do_ret(); // 弹帧 / 周期结束
Fault do_cal(uint8_t op, uint16_t slot); // TON/TOF/CTU12.9 步骤 4
};
}