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:
@@ -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/CTU(12.9 步骤 4)
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user