From 728ed9e71f7217c49fd78081075cb4e74b9aaa66 Mon Sep 17 00:00:00 2001 From: chentianya Date: Fri, 21 Aug 2026 22:00:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=87=E4=BB=A4=E9=85=8D=E7=BD=AE=E5=AE=9A?= =?UTF-8?q?=E6=A1=88=E6=9B=B4=E6=96=B0=EF=BC=9A=E6=9C=80=E7=BB=88=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=20+=20.stb=20=E6=A0=BC=E5=BC=8F=E5=86=BB=E7=BB=93?= =?UTF-8?q?=E4=BF=AE=E8=AE=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 指令配置.md 重写:架构图(machine.toml 只给编译器、vm 不读配置、isa 归执行器只管指令)、 决策清单 9 项、TOML 草案(meta/type 别名+range+tag/op/fb)、类型系统(基元内置+值域+tag)、 .stb 加固(型号标识[32]+SHA-256 文件尾各实现一份)、强校验清单、加东西流程、8 步执行计划、 4 项实现前确认 - 指令与映像.md:头 72→104 字节(型号标识[32] 偏移 72)、文件尾 SHA-256[32],12.13 修订注记 - stb文件格式.md:12.13 修订注记(落地后字节数字重新生成) --- Doc/isa/stb文件格式.md | 2 + Doc/isa/指令与映像.md | 13 +- Doc/isa/指令配置.md | 263 +++++++++++++++++++++++------------------ 3 files changed, 160 insertions(+), 118 deletions(-) diff --git a/Doc/isa/stb文件格式.md b/Doc/isa/stb文件格式.md index f7ccf98..ee4f3ec 100644 --- a/Doc/isa/stb文件格式.md +++ b/Doc/isa/stb文件格式.md @@ -2,6 +2,8 @@ 编译产物 `.stb` 的**面向使用者**的结构说明。规范以 [`指令与映像.md`](指令与映像.md) 为准,本文用 `line1.stb`(224 字节)做真实拆解。 +> **12.13 修订**(尚未落地到代码,本文拆解仍为旧格式):头新增型号标识[32](头 72 → 104 字节,段偏移基准同步后移),文件尾新增 SHA-256[32]。落地后本文全部字节数字需重新生成。 + ## 概览 - 魔数 `STSC`,版本 `1`,**全部整数小端** diff --git a/Doc/isa/指令与映像.md b/Doc/isa/指令与映像.md index 3cb6867..1805a6a 100644 --- a/Doc/isa/指令与映像.md +++ b/Doc/isa/指令与映像.md @@ -142,9 +142,13 @@ FB 实例固定布局,字段偏移编译期算死。 ## 映像 -魔数 `STSC`,版本 `1`。全部整数小端。文件 = 头 + 五个段,段序:常量表 → 函数表 → 字节码 → FB 布局 → 数据。偏移记在头里,段必须连续、偏移单调不减,末段终点不超过文件长度。 +魔数 `STSC`,版本 `1`。全部整数小端。文件 = 头 + 五个段 + **文件尾校验**,段序:常量表 → 函数表 → 字节码 → FB 布局 → 数据。偏移记在头里,段必须连续、偏移单调不减,末段终点不超过文件长度(文件尾在数据段之后)。 -### 头(72 字节) +> 12.13 修订:头新增 **型号标识[32]**(原头 72 字节 → 104 字节,段偏移基准同步后移); +> 文件尾新增 **SHA-256[32]**(对文件尾之前全部内容计算,compiler 写侧 / vm 读侧各自实现)。 +> 执行器读取时:型号标识与自身支持型号不匹配 → 报错;SHA-256 不匹配 → 报错(损坏/篡改)。 + +### 头(104 字节) | 偏移 | 宽 | 字段 | |---|---|---| @@ -165,6 +169,11 @@ FB 实例固定布局,字段偏移编译期算死。 | 60 | 4 | `offset_code` | | 64 | 4 | `offset_fb` | | 68 | 4 | `offset_data` | +| 72 | 32 | **型号标识**(定长 ASCII,含版本,如 `"STATOR" + "1"` 拼 32 字节补 `'\0'`) | + +### 文件尾(SHA-256) + +数据段之后追加 **32 字节 SHA-256**:对文件尾之前全部内容计算。执行器必须校验通过才运行;compiler 写入。 ### 常量表一行(12 字节) diff --git a/Doc/isa/指令配置.md b/Doc/isa/指令配置.md index 66d21e0..88baef7 100644 --- a/Doc/isa/指令配置.md +++ b/Doc/isa/指令配置.md @@ -1,15 +1,42 @@ -# 指令配置文件(ops.txt) +# 机器定义文件(machine.toml) -指令集的**唯一事实来源**:name / opcode / class / format / 参数名 / enabled。代码实现与配置文件在启动时**强校验**一致,防止两处漂移。 +指令集与类型的**唯一事实来源**,**只给编译器**(STCompiler/compiler)使用。执行器(vm)不读本文件——它是下位机程序,内建全部指令。 -## 目标 +## 架构(最终定案) -- 加指令/屏蔽指令的登记集中在一处(配置文件),不再散落在代码各处手改 -- 执行器(VM):**语义实现必须在代码里**,不能纯从文件加载;配置文件用于**屏蔽**(`enabled=false` 的指令执行到 → 故障) -- 编译器(STCompiler):**启动时从文件加载**(校验 + 屏蔽传导) -- `.stb` ABI 不变:opcode 数值仍是冻结契约;屏蔽是编译期/运行期策略,不改数值 +```text +machine.toml(只给编译器:meta + type 别名表 + op 表 + fb 表) + │ 运行时加载(toml++)+ 强校验 + ▼ +STCompiler → compiler(编码 opcode / 类型元数据 / FB 布局 全部来自配置) + │ 写 .stb(compiler 自带写实现:型号标识[32] + SHA-256 文件尾) + ▼ +.stb ──→ BytecodeExecutor → vm(执行 switch 在 vm;读 .stb 自实现) + │ + 型号匹配校验 + SHA-256 校验 + ▼ + isa(归执行器侧,只管指令定义) +``` -## 指令的三层分类(定案) +| 模块 | 职责 | +|---|---| +| `compiler` | 配置驱动编译;自带 `.stb` 写实现;`--disasm` 用配置参数名/format 自格式化 | +| `vm` | 内建全指令集(执行 switch 在 vm);自带 `.stb` 读实现 + 型号/SHA-256 校验;无屏蔽、不读配置 | +| `isa` | **归执行器侧**(vm 依赖),**只管指令定义**:Op 枚举/Instr/Encode/OpFormat/OpClass/类型/饱和/disasm。指令的具体执行实现在 vm | +| `machine.toml` | 编译器唯一知识来源 | + +## 决策清单(定案) + +1. 指令两大分类:**PLAIN**(无实例,26 条)/ **INSTANCE**(有实例,8 条 `CAL_*`) +2. 三层分类:`class`(操作对象)→ `format`(操作数形态)→ `参数名`(语义) +3. isa 归执行器侧、只管指令定义;执行 switch 留在 vm +4. 配置改 TOML、改名 machine.toml,只给编译器;vm 不需要配置 +5. 一致性靠 `.stb`:**型号标识[32]**(定长字符串含版本)+ **SHA-256 文件尾**(compiler/vm 各实现一份)+ 强校验 +6. 类型:**基元内置**(编译器内建 bit/int8..uint64/float32/float64,元数据在代码);配置类型行 = `name + base + range? + tag`(别名);**值域约束进配置**(如 BOOL range=[0,1]) +7. 字符串:**方案 A**(v1 不做;"组合类型"(含定长字符串 STRING(n))为未来扩展,需时再扩 .stb 格式) +8. `.stb` 读写:compiler 写、vm 读,**各自实现**(无共享 image 模块) +9. 冻结哈希测试更新(接受) + +## 指令三层分类 ```text class(操作对象) → format(操作数形态) → 参数名(操作数语义) @@ -17,129 +44,133 @@ class(操作对象) → format(操作数形态) → 参数名(操作 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/RET(26 条) | +| **INSTANCE**(有实例) | 数据区实例块(内建 FB) | CAL_TON/TOF/TP/CTU/CTD/CTUD/R_TRIG/F_TRIG(8 条) | -### 两个大类 +format 不可省:同是"第二个操作数是数字",`LOADK`/`LOAD_I`/`CALL` 渲染相同但语义不同(常量 id / 槽号 / fn_id,由参数名表达);"数字 vs 寄存器 vs 偏移"的渲染差异(`r%d` / `%u` / `%+d`)只有 format 能表达。 -| 大类 | 操作对象 | 现有指令 | 操作数形态 | -|---|---|---|---| -| **无实例**(PLAIN) | 寄存器 / 立即数 / 槽号 / 分支 / 调用 | MOVE/LOADK/NOT/AND/OR/算术/CMP_* / JMP/JT/JF / LOAD_*/STORE_* / CALL/RET(26 条) | RR/RRR/IMM/SLOT/JMP/JC/CALL/NONE | -| **有实例**(INSTANCE) | **数据区实例块**(内建 FB) | CAL_TON/TOF/TP/CTU/CTD/CTUD/R_TRIG/F_TRIG(8 条) | CAL(一个实例基槽号) | +## 配置文件格式(TOML) -区别的本质: +**全属性必填,不可省略**: + +```toml +[meta] +name = "STATOR" # 型号名(参与 .stb 型号标识) +version = 1 # 指令集版本(参与 .stb 型号标识) + +# ---- 类型:编译器内建基元(bit/int8/int16/int32/int64/uint8/uint16/uint32/uint64/float32/float64) +# 配置类型 = 基元别名(+ 值域约束 + .stb 契约 tag) +[[type]] +name = "BOOL" +base = "uint8" +range = [0, 1] # 值域约束(语言语义数据化;缺省 = 基元全范围) +tag = 0 # 常量表契约(强校验) + +[[type]] +name = "INT" +base = "int16" +tag = 1 + +[[type]] +name = "TIME" +base = "int64" +tag = 2 + +# ---- 指令(全属性必填) +[[op]] +name = "MOVE" +opcode = 0 +class = "plain" # plain / instance +format = "RR" +params = ["rd", "rs"] +enabled = true + +[[op]] +name = "CAL_TON" +opcode = 24 +class = "instance" +format = "CAL" +params = ["instance"] +enabled = true + +[[op]] +name = "RET" +opcode = 33 +class = "plain" +format = "NONE" +params = [] +enabled = true + +# ---- 内建 FB(布局登记;cal_opcode 与 op 行强校验一致) +[[fb]] +name = "ton" +opcode = 24 +fields = [["in", "BOOL"], ["pt", "TIME"], ["q", "BOOL"], ["et", "TIME"]] + +[[fb]] +name = "ctud" +opcode = 29 +fields = [["cu", "BOOL"], ["cd", "BOOL"], ["r", "BOOL"], ["lu", "BOOL"], + ["pv", "INT"], ["qu", "BOOL"], ["qd", "BOOL"], ["cv", "INT"]] +``` + +## 类型系统 + +- **基元内置**:编译器内建 `bit/int8/int16/int32/int64/uint8/uint16/uint32/uint64/float32/float64`(宽度/有无符号/是否浮点元数据在代码,C 语义) +- **别名**:配置类型行只写 `name + base + range? + tag`——宽度/符号/浮点从 base 继承 +- **值域约束**:`range`(如 BOOL [0,1])供编译器做常量/赋值检查;缺省 = 基元全范围 +- **tag 契约**:`tag`(0/1/2)与 `.stb` 常量表格式强校验(防 type 表改序破坏旧 .stb) +- **字符串**:v1 不做(方案 A);组合类型(含 `STRING(n)`)为未来扩展,文档预留,需时再扩 `.stb` 格式 +- 半数据化边界:**类型定义数据化**(配置),**运算/类型检查语义代码化**(如 AND 只吃 BOOL 是语言规则,在 compiler 代码;饱和算术在 vm/isa) + +## .stb 加固(格式冻结更新) + +见 [`指令与映像.md`](指令与映像.md):头新增 **型号标识[32]**(定长 ASCII 字符串,含版本,不足补 `'\0'`);文件尾新增 **SHA-256[32]**(对前面全部内容计算,compiler 写侧 / vm 读侧各自实现)。执行器读取时: ```text -LOAD_GLOBAL(无实例):从槽读一个"值" → 地址是编译期槽号,纯搬运 -CAL_TON(有实例) :对实例块执行"算法" → 基槽号 + 完整定时器语义(读字段/推进/写字段) +型号标识与自身支持型号不匹配 → 直接报错 +SHA-256 不匹配 → 报错(文件损坏/篡改) ``` -format 不可省:同是"第二个操作数是数字",`LOADK`/`LOAD_I`/`CALL` 渲染相同但语义不同(常量 id / 槽号 / fn_id,由参数名表达);"数字 vs 寄存器 vs 偏移"的**渲染差异**只有 format 能表达(`r%d` / `%u` / `%+d`)。 +## 强校验清单(加载/读取时,任一不符 → 报错退出) -## 配置文件格式(`isa/ops.txt`) +1. TOML 语法与字段完整性(全属性必填) +2. `type.base` 命中内建基元;`range` 合法(min ≤ max、类型相符) +3. `tag` 与 `.stb` 常量表契约一致(0/1/2) +4. `op.opcode` 唯一、0..255;`class` 合法;`format` 合法;**类别-格式互锁**(INSTANCE ↔ CAL) +5. `fb.opcode` 与 op 行的 CAL_* 一致;fb 字段类型命中配置类型表 +6. 型号标识(.stb 侧) -**全属性必填,不可省略**;`#` 注释、空行忽略: +## 加东西的流程 ```text -# op <参数名...> -# 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 +加普通指令:machine.toml 加 [[op]] 一行 + vm 一个语义 case → 重建 vm +加内建 FB :machine.toml 加 [[fb]] 一行 + vm 一个语义 case → 重建 vm(compiler 免重建) +加语言类型:machine.toml 加 [[type]] 一行(别名+tag)+ 类型检查/VM 语义代码 → 重建 +改型号版本:machine.toml [meta] version +1 → 旧 .stb 被旧/新执行器按型号校验决定是否接受 ``` -- 参数个数由 format 决定,解析时校验字段数: +## 执行计划(分支 dev_ops_config) -| format | 参数 | 现有指令 | -|---|---|---| -| `RR` | 2(rd rs) | MOVE / NOT | -| `RRR` | 3(rd ra rb) | AND/OR/ADD/SUB/MUL/DIV/CMP_xx | -| `IMM` | 2(rd const_id) | LOADK | -| `SLOT` | 2(rd slot) | LOAD_I/STORE_Q/LOAD_M/STORE_M/LOAD_GLOBAL/STORE_GLOBAL | -| `JMP` | 1(off) | JMP | -| `JC` | 2(r off) | JT / JF | -| `CALL` | 1(fn_id) | CALL | -| `CAL` | 1(instance) | CAL_*(8 个) | -| `NONE` | 0 | RET | - -- **类别与格式互锁**:`INSTANCE` 类的 format 必须是 `CAL`,反之亦然——配置错误启动期暴露 - -### 内建 FB 注册(定案:并入 ops.txt) - -`CAL_*` 已是 op 行(与 ADD 同机制:编码/译码/disasm/屏蔽);fb 行登记其**数据结构(布局)**——ST 语言层的登记处(Lexer/Parser/Linker/Codegen 查表): - -```text -# fb <字段:类型 ...> -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 +``` +0. 文档定案(本文 + 指令与映像.md 格式冻结更新 + stb文件格式.md 修订注记) ← 当前 +1. ✅ OpFormat/OpClass 显式化 + disasm 表驱动(已完成,35dabf4) +2. machine.toml 落地:meta + type 表 + op 34 条 + fb 8 条 +3. compiler 配置驱动改造:toml++ 加载 + 强校验;编码 opcode / 类型元数据 / + FB 布局来自配置(compiler 不再依赖 isa) +4. .stb 写侧:compiler 实现 型号标识[32] + SHA-256 文件尾 +5. .stb 读侧:vm 自实现读 + 型号匹配 + SHA-256 校验(isa 的 Image 拆出) +6. CLI:STCompiler --machine (编译路径必填) +7. 测试:machine 解析/校验负例、型号不匹配报错、SHA-256 篡改检测、 + 冻结哈希更新、全量回归 +8. 文档 + 提交 ``` -- fb 行的 `cal_opcode` 与 op 行的 CAL_* 操作码**强校验一致**(防两处漂移) -- 字段类型名小写(`bool/int/time`),与语言关键字对齐 -- **加 FB = fb 行 + VM 一个语义 case,编译器免重建**(关键字/布局/操作码映射全部从表读) +## 实现前确认项(4 项,未定案) -## isa 层:`OpTable` - -```cpp -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/NONE`;`disasm` 改表驱动(输出文本不变,现有断言兼容)。 - -## 各端接线 - -| 端 | 参数 | 行为 | -|---|---|---| -| STCompiler | `STCompiler [-o out.stb] --ops ` | **仅 `-o` 编译路径要求**;加载/校验失败 → 报错退出;codegen 生成被屏蔽指令 → 编译错误(屏蔽传导) | -| BytecodeExecutor | `--ops `(**可选**) | 不传 = 全部启用(兼容现有用法);传入 → 加载 + 校验,执行到 disabled 指令 → `Fault::Disabled`,周期中止退出码 1 | -| 语义实现 | — | 仍在 VM 代码里(每指令一个 case,不可省) | - -## 加东西的流程(改造后) - -```text -加普通指令:ops.txt 加一行 op(name opcode class format 参数 enabled) - + Op.h 枚举加一项 + VM 一个语义 case → 重建 isa/VM -加内建 FB:ops.txt 加一行 fb(name cal_opcode 字段:类型) - + VM 一个语义 case → 重建 VM(编译器免重建) -屏蔽指令:ops.txt 把 enabled 改 disabled - → 编译器拒绝生成、执行器运行时报 Disabled 故障(零代码改动) -``` - -## 执行计划(单步确认) - -1. **OpFormat / OpClass 显式化**:新增 `OpFormat`(RR/RRR/IMM/SLOT/JMP/JC/CALL/CAL/NONE)与 `OpClass`(PLAIN/INSTANCE);`disasm` 改表驱动(输出不变,11 个 ctest 全绿) -2. **`ops.txt` 落地**:34 条 op 行 + 8 条 fb 行,全属性必填 -3. **`OpTable`**:`isa/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. **文档 + 提交** +1. 配置文件名与位置:建议 `compiler/machine.toml`(只归编译器用) +2. 型号标识生成规则:建议 `[meta] name + version` 拼成 32 字节(如 `"STATOR" + "1"` → 补 `'\0'`);vm 内建"支持型号列表"比对 +3. compiler 内部 `TypeKind`(Bool/Int/Time):保留为语言语义枚举(类型检查规则),元数据从配置 base 查 +4. 依赖方向确认:`compiler` 不再依赖 `isa`(`compiler → toml++` 自有;`STCompiler → compiler`;`vm → isa`)