Files
Interpreter/Doc/isa/指令配置.md
T
Admin 5bcab6791f 指令配置定案:两大分类(PLAIN/INSTANCE)+ FB 注册并入 ops.txt。
- 三层分类:class(操作对象)→ format(操作数形态)→ 参数名(语义)
- op 行加 class 字段(PLAIN 26 条 / INSTANCE 8 条 CAL_*),类别-格式互锁校验
- fb 行登记内建 FB 布局(8 个),cal_opcode 与 op 行强校验一致
- 加 FB = 配置文件一行 + VM 语义 case,编译器免重建;执行计划更新为 7 步
2026-08-21 21:09:23 +08:00

7.3 KiB
Raw Blame History

指令配置文件(ops.txt

指令集的唯一事实来源name / opcode / class / format / 参数名 / enabled。代码实现与配置文件在启动时强校验一致,防止两处漂移。

目标

  • 加指令/屏蔽指令的登记集中在一处(配置文件),不再散落在代码各处手改
  • 执行器(VM):语义实现必须在代码里,不能纯从文件加载;配置文件用于屏蔽enabled=false 的指令执行到 → 故障)
  • 编译器(STCompiler):启动时从文件加载(校验 + 屏蔽传导)
  • .stb ABI 不变:opcode 数值仍是冻结契约;屏蔽是编译期/运行期策略,不改数值

指令的三层分类(定案)

class(操作对象) → format(操作数形态) → 参数名(操作数语义)
  PLAIN/INSTANCE     RR/RRR/IMM/SLOT/       rd/rs/const_id/
                     JMP/JC/CALL/CAL/NONE    slot/off/fn_id/instance
回答的问题 谁需要它
class 操作对象:值/搬运 还是 实例算法 语义归属、校验互锁(INSTANCE ↔ CAL
format 操作数的形态:寄存器 / 常量 id / 槽号 / 带符号偏移 disasm 渲染、编码助手
参数名 每个操作数的语义命名 元数据、文档、校验

两个大类

大类 操作对象 现有指令 操作数形态
无实例PLAIN 寄存器 / 立即数 / 槽号 / 分支 / 调用 MOVE/LOADK/NOT/AND/OR/算术/CMP_* / JMP/JT/JF / LOAD_/STORE_ / CALL/RET26 条) RR/RRR/IMM/SLOT/JMP/JC/CALL/NONE
有实例INSTANCE 数据区实例块(内建 FB CAL_TON/TOF/TP/CTU/CTD/CTUD/R_TRIG/F_TRIG8 条) CAL(一个实例基槽号)

区别的本质:

LOAD_GLOBAL(无实例):从槽读一个"值"        → 地址是编译期槽号,纯搬运
CAL_TON(有实例)     :对实例块执行"算法"     → 基槽号 + 完整定时器语义(读字段/推进/写字段)

format 不可省:同是"第二个操作数是数字",LOADK/LOAD_I/CALL 渲染相同但语义不同(常量 id / 槽号 / fn_id,由参数名表达);"数字 vs 寄存器 vs 偏移"的渲染差异只有 format 能表达(r%d / %u / %+d)。

配置文件格式(isa/ops.txt

全属性必填,不可省略# 注释、空行忽略:

# op <name> <opcode> <class> <format> <参数名...> <enabled>
# class: PLAIN(无实例)/ INSTANCE(有实例)
op MOVE     0   PLAIN    RR   rd rs      enabled
op LOADK    1   PLAIN    IMM  rd const_id enabled
op NOT      2   PLAIN    RR   rd rs      enabled
op AND      3   PLAIN    RRR  rd ra rb   enabled
op ADD      5   PLAIN    RRR  rd ra rb   enabled
op CMP_EQ   9   PLAIN    RRR  rd ra rb   enabled
op JMP      15  PLAIN    JMP  off        enabled
op JT       16  PLAIN    JC   r off      enabled
op LOAD_I   18  PLAIN    SLOT rd slot    enabled
op CAL_TON  24  INSTANCE CAL  instance   enabled
op CALL     32  PLAIN    CALL fn_id      enabled
op RET      33  PLAIN    NONE            enabled
  • 参数个数由 format 决定,解析时校验字段数:
format 参数 现有指令
RR 2rd rs MOVE / NOT
RRR 3rd ra rb AND/OR/ADD/SUB/MUL/DIV/CMP_xx
IMM 2rd const_id LOADK
SLOT 2rd slot LOAD_I/STORE_Q/LOAD_M/STORE_M/LOAD_GLOBAL/STORE_GLOBAL
JMP 1off JMP
JC 2r off JT / JF
CALL 1fn_id CALL
CAL 1instance CAL_*8 个)
NONE 0 RET
  • 类别与格式互锁INSTANCE 类的 format 必须是 CAL,反之亦然——配置错误启动期暴露

内建 FB 注册(定案:并入 ops.txt)

CAL_* 已是 op 行(与 ADD 同机制:编码/译码/disasm/屏蔽);fb 行登记其数据结构(布局)——ST 语言层的登记处(Lexer/Parser/Linker/Codegen 查表):

# fb <name> <cal_opcode> <字段:类型 ...>
fb ton    24  in:BOOL pt:TIME q:BOOL et:TIME
fb tof    25  in:BOOL pt:TIME q:BOOL et:TIME
fb tp     26  in:BOOL pt:TIME q:BOOL et:TIME
fb ctu    27  cu:BOOL r:BOOL pv:INT q:BOOL cv:INT
fb ctd    28  cd:BOOL ld:BOOL pv:INT q:BOOL cv:INT
fb ctud   29  cu:BOOL cd:BOOL r:BOOL lu:BOOL pv:INT qu:BOOL qd:BOOL cv:INT
fb r_trig 30  clk:BOOL q:BOOL
fb f_trig 31  clk:BOOL q:BOOL
  • fb 行的 cal_opcode 与 op 行的 CAL_* 操作码强校验一致(防两处漂移)
  • 字段类型名小写(bool/int/time),与语言关键字对齐
  • 加 FB = fb 行 + VM 一个语义 case,编译器免重建(关键字/布局/操作码映射全部从表读)

isa 层:OpTable

class OpTable {
    bool load(const char* path, std::string* err);  // 解析 + 强校验
    bool enabled(uint8_t op) const;
    // name / format / 参数名查询(后续 FB 注册也走这里)
};

强校验(load 时)

  • 语法:字段数符合 format、enabled 必须出现
  • 操作码唯一、0..255
  • 与编译期枚举一致:文件里每条指令的 name/opcode/format 必须与代码(Op 枚举 + 助记符 + OpFormat)逐条一致,任一不符 → 报错列出差异
  • 任一失败 → load 返回 false,调用方报错退出

前置改造:OpFormat 显式化——现有隐式"形态"disasm 的 case)变成枚举 RR/RRR/IMM/SLOT/JMP/JC/CALL/CAL/NONEdisasm 改表驱动(输出文本不变,现有断言兼容)。

各端接线

参数 行为
STCompiler STCompiler <project.toml> [-o out.stb] --ops <ops.txt> -o 编译路径要求;加载/校验失败 → 报错退出;codegen 生成被屏蔽指令 → 编译错误(屏蔽传导)
BytecodeExecutor --ops <ops.txt>可选 不传 = 全部启用(兼容现有用法);传入 → 加载 + 校验,执行到 disabled 指令 → Fault::Disabled,周期中止退出码 1
语义实现 仍在 VM 代码里(每指令一个 case,不可省)

加东西的流程(改造后)

加普通指令:ops.txt 加一行 opname opcode class format 参数 enabled
          + Op.h 枚举加一项 + VM 一个语义 case → 重建 isa/VM
加内建 FBops.txt 加一行 fbname cal_opcode 字段:类型)
          + VM 一个语义 case → 重建 VM(编译器免重建)
屏蔽指令:ops.txt 把 enabled 改 disabled
          → 编译器拒绝生成、执行器运行时报 Disabled 故障(零代码改动)

执行计划(单步确认)

  1. OpFormat / OpClass 显式化:新增 OpFormatRR/RRR/IMM/SLOT/JMP/JC/CALL/CAL/NONE)与 OpClassPLAIN/INSTANCE);disasm 改表驱动(输出不变,11 个 ctest 全绿)
  2. ops.txt 落地34 条 op 行 + 8 条 fb 行,全属性必填
  3. OpTableisa/include/isa/OpTable.h + isa/src/OpTable.cpp(解析 + 强校验:语法/重号/越界/类别-格式互锁/fb-opcode 一致/与编译期枚举一致)
  4. STCompiler --ops:加载/校验/屏蔽传导(codegen 生成被屏蔽指令 → 编译错误)
  5. BytecodeExecutor --ops:可选加载 / Fault::Disabled
  6. 测试ops_test(正例 + 缺属性/字段数错/重号/互锁破坏/与枚举不一致负例)、屏蔽传导用例、11 个 ctest 回归
  7. 文档 + 提交