29 KiB
指令集优化(V2 规格,型号 STATOR2)
状态:规格冻结中。核心决策已全部定案(§2),本文为 V2 规格草案; §4 列出尚未确定的细节项,全部闭合后进入实现阶段。 与现状(V1)的关系:V1 编码冻结不可改(opcode 0..33、32bit 指令、8 字节定宽槽), 本优化为全新 V2 架构,.stb 格式 / 指令字 / 数据模型全部重设计,型号 bump 为 STATOR2。
1. 背景与动机
| # | 现状问题 | 优化方向 |
|---|---|---|
| 1 | opcode 定义草率:34 条按语义乱序编号,无位域结构 | format/宽度编码进 opcode,位掩码机械推导 |
| 2 | 8 字节定宽槽浪费:BOOL 只用 1/8 空间 | 变宽紧凑值区(1/2/4/8 字节按类型) |
| 3 | 变量区利用率低 | 值区按类型紧凑布局 + 地址 u32(4GB) |
| 4 | 类型只有 BOOL/INT/TIME | 扩展 IEC 全基础类型(19 种) |
| 5 | 结构体无法支持 | 槽表引用 + LOAD 16B 变体(基槽+偏移,预留) |
| 6 | 指令 32bit 固定 | 变长指令(长度编码在 opcode);寄存器编号维持 8 位 |
| 7 | 槽(变量)与初值(数据)耦合在同一格 | 槽表(引用)与值区(数据)解耦 |
2. 已定案设计
2.1 变长指令,前缀编码 + 形态分区
- 指令长度不固定:4 / 8 / 16 字节(32 字节预留);长度与形态由前缀分区一体表达(见
指令编码.md) - 前缀分区:
11=RR、10=NONE(4B);011=RRR、010 000/001/010/011/100/101=IMM/SLOT/JMP/JC/CALL/CAL(8B);0010=SLOT+off、0011=IMM64(16B);0001=预留(32B) - fmt 位段已取消(用户定案):形态全部由前缀分区表达(含 010 区内部分区,零查表)
字节 0 字节 1 字节 2..n(按长度组)
[前缀+形态分区 | op] [func:4 | 空:4] 操作数区
| 位段 | 位号 | 内容 |
|---|---|---|
| 前缀+分区 | 4B: bit7..6 / 8B: bit7..5 / 16B: bit7..4 / 32B: bit7..4 | 长度与形态分区 |
| op | 4B: bit5..0 / 8B: bit4..0 / 16B: bit3..0 / 32B: bit3..0 | 分区内独立编号 |
| func | bit15..12 | 数据语义(宽度×符号/浮点),语义随 op |
| 空 | bit11..8 | 待全部编码完后定用途 |
| 长度组 | 指令长度 | 形态分区 | 操作数区 |
|---|---|---|---|
11/10 |
4 字节 | RR / NONE | rd + rs1(各 1B)/ 无 |
011/010 |
8 字节 | RRR / 010 区六形态(分区直推) | rd+rs1+rs2 / 见指令编码.md §5 |
0010/0011 |
16 字节 | SLOT+off / IMM64 | rd + slot32 + off32 / rd + imm64 |
0001 |
32 字节 | 预留 | 超大立即数/未来扩展 |
- 取指:读字节 0 → 前缀定总长 → 搬 4/8/16 字节
- 推导(编码在头两字节):
- 指令长度 + 形态 ← 前缀分区(010 区查表)
- uses_rd/uses_ra/uses_rb ← 形态:全部前缀直推(指令编码.md §6)
- 数据宽度/符号 ←
func位段(查 constexpr 宽度/符号表)
- 字段访问统一为 LOAD/STORE 16B 变体:
LOAD rd, slot, off32(基槽 + 偏移,编译期算死)——结构体字段与 FB 共享体字段同一指令,无单独 LOADF - 跳转偏移字节化:off32(字节,相对下一条);pc/code_offset/code_len 全字节单位;code 段 16 字节对齐
2.2 寄存器模型与调用栈(U10 定案)
- 寄存器编号 = 1 字节(8 位)→ 256 个为寻址上限(8 位字段能编的最大寄存器号),不是每帧分配数
- 每帧按函数头 nregs 动态分配(编译器按该函数变量+临时峰值算):帧大小 = nregs × 8B(百字节级),栈深 64 上限
- 编号容量恒定关系:
8bit×256 == 16bit×128 == 32bit×64 == 64bit×32(指编号位宽 × 数量反比,编号空间,非帧大小) - 寄存器值仍 8 字节(int64);codegen
register overflow (>256)检查保留 - 调用约定不变:r0 结果、r1..r7 参数(≤7)、r8+ 变量/临时;CALL/RET 帧复制 = r0..r7 全宽(64B),类型解释是下游指令按 func 的事
调用栈(方案 C:预分配栈区,U10 定案)
- 无递归:链接层检测调用图环(FUNCTION 自调用/循环调用)→ 编译期报错(
link error: recursive call);无环 → 最坏调用路径编译期可算 - 帧结构(每帧 12B 帧头 + nregs×8B 寄存器区):帧头 = { fn_id:u32, ret_pc:u32, ret_fn_id:u32 };寄存器区 = 本函数 nregs 个 int64
- max_stack 编译期计算(写入映像头 @116):
max_stack = MAIN 帧需求 + 最坏 FUNCTION 调用路径 Σ(帧需求),帧需求 = 12 + nregs×8;调用图为 DAG(无递归),最坏路径 = 按字节权重的最长路径;MAIN 帧计入(常驻栈底) - 预分配栈区:Machine 构造时一次性分配 max_stack 字节连续内存,运行期零分配
- 压帧:从栈顶取 帧需求(12 + nregs×8),sp += 帧需求;弹帧:sp -= 帧需求
- 溢出检查双口径:剩余栈 < 帧需求 →
StackOverflow(字节主检查)+ 深度 ≤64(双保险) - MAIN 帧常驻栈底(跨周期保留),周期结束回退 sp 到 MAIN 帧顶
2.3 数据模型:槽表(引用)→ 值区(数据)
槽表段(静态引用表,8B/条) 值段(初值,紧凑变宽)
┌─────────────────────────┐ ┌──────────────────────────┐
│ { addr:u32, 预留:u32 } │ ──地址──▶ │ BOOL 1B / INT 2B(对齐) │
│ 槽 0..n_slots-1 │ │ DINT·REAL 4B / TIME 8B │
└─────────────────────────┘ │ 结构体 = 连续字段块(预留) │
└──────────────────────────┘
- 访问:
LOAD rd, slot→addr = 槽表[slot].addr→ 值区按type位段读 1/2/4/8 字节;字段访问LOAD rd, slot, off32→addr + off - 两级间接:每次访问多一次内存读(PLC 规模无感)
- 宽度编码进 opcode:
type位段携带宽度 + 符号,VM 无歧义读写(V1 因"变宽布局无法从槽号推断宽度"而改定宽,V2 用 type 位段化解) - 对齐规则:1/2/4/8 字节,编译器布局保证
- 初值整合在 .stb 内分段(ELF 式):槽表段 / 值段 / 元数据段并列,单文件 SHA-256 校验
- 寻址规模:全 32 位——槽号 u32(2^32 引用)、值区地址 u32(4GB)
2.4 类型系统:IEC 全基础类型(19 种,type:5)
type 位段 type:5(32 种):19 个 IEC 基础类型 + 13 预留;结构体/字符串/数组不占位段(组合类型走元数据段)。
| type | 类型 | 宽度 | 符号 | C 对应 | type | 类型 | 宽度 | 符号 | C 对应 |
|---|---|---|---|---|---|---|---|---|---|
| 0 | BOOL | 1B | — | bool | 10 | UINT | 2B | 无 | uint16_t |
| 1 | BYTE | 1B | 无 | uint8_t | 11 | UDINT | 4B | 无 | uint32_t |
| 2 | WORD | 2B | 无 | uint16_t | 12 | ULINT | 8B | 无 | uint64_t |
| 3 | DWORD | 4B | 无 | uint32_t | 13 | TIME | 8B | 有(ms) | int64_t |
| 4 | LWORD | 8B | 无 | uint64_t | 14 | REAL | 4B | IEEE754 | float |
| 5 | SINT | 1B | 有 | int8_t | 15 | LREAL | 8B | IEEE754 | double |
| 6 | INT | 2B | 有 | int16_t | 16 | DATE | 4B | 无 | uint32_t(天) |
| 7 | DINT | 4B | 有 | int32_t | 17 | TOD | 4B | 无 | uint32_t(当日 ms) |
| 8 | LINT | 8B | 有 | int64_t | 18 | DT | 8B | 无 | uint64_t |
| 9 | USINT | 1B | 无 | uint8_t | 19..31 | 预留 |
- type 位段红利:CMP/算术按类型自动语义——无符号类型无符号比较、整数饱和到类型宽度(模板化)、浮点走 IEEE 754(无饱和,溢出→±inf)、读取按宽度+符号/零扩展
- 整数除法语义(A 定案):除零 → 返回被除数(结果保持,Fail-safe);MIN/-1 溢出 → 饱和夹界(各宽度模板化);截断除法(向零,C 风格);MOD 符号随被除数(-7 MOD 3 = -1,与除法一致),除零同 DIV
- DATE/TOD/DT(U13 定案):DATE=uint32(天数)、TOD=uint32(当日 ms)、DT=uint64 {date:32 | tod:32} 拼接(高 32 位日期);DT→DATE 取高 32 位、DT→TOD 取低 32 位(CONV/移位展开);v1 无日期运算仅存取/比较
- 浮点表示:REAL 4B / LREAL 8B,值区 4/8 字节对齐;寄存器 int64 位模式搬运(REAL 低 4 字节),运算时按 type 重解释
- 常量表契约(A2 定案):条目 = 8 字节原始值(无 tag),按位模式去重;
LOADK rd, const_id(8B IMM 形态)用指令 type 位段解释(读 width 字节、按符号扩展), 与 LOAD 语义统一;同一常量可被不同 type 的 LOADK 复用(字面量按上下文适配的落地)。 V1 的 {tag, value} 契约废弃。IMM64 形态(16B 内嵌 64 位值)保留编码、v1 不发射。 - ST 层:19 类型名全量进关键字;进制前缀
2#/8#/16#支持(浮点无前缀);浮点十进制字面量(1.5、-2.5e3) - 类型转换:禁止隐式变量转换(赋值/比较/算术要求类型严格一致,Typecheck 阶段报错);字面量按上下文适配(
5可赋 INT/REAL/DINT 等,编译期解释,非运行时转换);显式转换函数(INT_TO_REAL())v1 不做
2.5 映像格式(头 128 字节,16 对齐)——U7 已定案
0..3 magic(STSC,不变)
4..7 version = 2(V2 格式;V1 = 1)
8..71 原 15 字段(cycle_limit/dt_ms/project_hash/entry_fn_id/
n_globals/n_i/n_q/n_m/n_consts/n_funcs + offset_const/funcs/code/fb/data)
64 offset_slots ← 槽表段(原 offset_fb 改义,FB 并入值区)
68 offset_values ← 值段(原 offset_data 改义,起点 16 对齐)
72..103 型号标识(STATOR2)
104 n_slots ← 槽表条目数(= n_globals + FB 实例/结构体字段槽数)
108 values_size ← 值段字节数(原 n_values,命名修正)
112 offset_meta ← 元数据段偏移(v1 恒 0 = 空段;结构体/字符串类型表预留)
116 max_stack ← 栈区字节数(编译期按调用图算,U10 方案 C)
120..127 预留 8 字节
段序:头 → 常量表 → 函数表 → 字节码 → 槽表段 → 值段 → 元数据段(v1 空) → SHA-256 尾
U7 修正注记(2026-08-24):
- 「原 15 字段」修正为原 17 字段(72 字节)
n_values改名values_size(值段字节数,避免与"数量"混淆)- 预留区固定
offset_meta@112(v1 填 0 = 元数据段不存在,将来启用不改头) - n_i/n_q/n_m 保留恒 0(V1 遗产字段:兼容 + sidecar 校验/将来 I/Q/M 分区语义预留,不删)
- n_slots = n_globals + FB 实例/结构体字段槽数(明确关系)
- offset_values 16 对齐(TIME/LREAL 8B 对齐的上界;编译器保证)
2.6 其他定案
- 型号 bump:STATOR1 → STATOR2
- I/Q/M 六条 LOAD/STORE 合并为 LOAD/STORE 两条(单一值区,语义标签交给 sidecar)
- LOADF 取消:结构体/FB 字段访问统一用 LOAD/STORE 16B 变体(基槽 + 偏移)
- FB 共享体实施:16B 变体即基址寻址指令,FB 体编译一次消除内联膨胀
- 结构体语法 v1 不实现,只留编码路径(16B 变体 + 元数据段)
- FB 编码定案(B1/B2):1 条 CAL(SLOT 形态,8B:头 2 + fb_id:16 + slot32)+ fb_id 16 位(查 machine.toml
[[fb]]表);新增内建 FB 只改配置 + VM 实现,指令格式零变化。V1 的 CAL_TON..CAL_F_TRIG 8 个 opcode 作废 - 领域指令不进指令集(B4 定案):运动控制 / 通信等全部走 FB 库(ST 层 FB + CALL + 共享体),V2 不设 EXT 服务指令——op 位段只承载基础指令
2.7 调用与内联策略(V1 现状 + V2 方向)
V1 现状:
| 对象 | V1 处理 | 原因 |
|---|---|---|
| 用户 FB(FUNCTION_BLOCK) | 调用点内联展开(字节码随调用点数膨胀) | 12.8 定案:FB 体访问绝对字段地址,不同实例基址不同,共享体无法复用 |
| FUNCTION(FC) | 独立函数 + CALL fn_id 帧栈 |
FC 无状态,寄存器约定(r1..r7 / r0),无地址冲突;递归在前层被拒 |
| 内建 FB(TON/CTU/…) | CAL_* 指令(VM 运行时原语 do_cal) |
定时器/计数器是 VM 侧状态机,天然共享 |
V2 定案:16B 变体 LOAD/STORE rd, slot, off = 基址寻址——FB 体编译一次,运行时按实例槽定位字段,消除内联膨胀。FUNCTION 仍走 CALL 帧栈;内建 FB 仍走 CAL(SLOT 形态,实例号即槽号)。
3. 与 V1 的差异对照
| 项 | V1(现状) | V2(定案) |
|---|---|---|
| 指令长度 | 固定 32bit | 变长 4/8/16B,长度在 opcode |
| opcode | 0..33 乱序,无位域 | [前缀+形态分区|op] + [func:4|空:4] |
| 格式 | 9 种(RR/RRR/IMM/SLOT/JMP/JC/CALL/CAL/NONE) | 形态由前缀分区表达(11/10/011/010查表/0010/0011),fmt 位段取消 |
| 寄存器编号 | 8 位(256/帧) | 8 位(256/帧,不变) |
| 变量访问 | 立即数槽号直接寻址 | 槽表引用 → 值区(两级间接) |
| 槽 | 8B 定宽 | 8B 引用表({addr:u32}) |
| 值区 | 定宽 8B/变量 | 变宽紧凑(1/2/4/8B) |
| 宽度信息 | 无(定宽) | type 位段(RISC-V 式) |
| 类型 | BOOL/INT/TIME | 19 IEC 基础类型 + 13 预留 |
| 字段访问 | 无(FB 内联) | LOAD/STORE rd, slot, off(结构体/FB 共用) |
| FB 调用 | 用户 FB 内联展开 | 基址寻址共享体(消除膨胀) |
| 寻址空间 | 槽 65535(512KB) | 槽 2^32、值区 4GB |
| 初值 | 槽内 | 值段(逻辑分段,同文件) |
| 跳转/pc | 条数单位 | 字节单位 |
| 型号 | STATOR1 | STATOR2 |
4. 尚未确定项(细节,待逐项闭合)
核心决策已全部定案,以下为进入实现前需闭合的设计细节:
| # | 项 | 状态 |
|---|---|---|
| 已定案(U12):v1 0 长度占位(offset_meta=0),schema 延后 | ||
| 已定案:常量表(8B LOADK 查表);LOADK 用 type 位段解释;条目 8B 无 tag;IMM64 预留不发射 | ||
| A3 | 内建 FB 字段类型化 | 已定案:字段类型化(TON: in/pt/q/et = BOOL/TIME/BOOL/TIME;R_TRIG: clk/q = BOOL/BOOL);计数器单/双字(INT/DINT)编码形式 = fb 表拆条(CTU/DCTU/CTD/DCTD/CTUD/DCTUD 6 条,名字即宽度)——U5 已定案 |
| A4 | DATE/TOD/DT 字面量 | 已定案:v1 不支持(类型存在,仅声明/存取/比较,无 D#/TOD#/DT# 字面量语法) |
| A5 | 算术语义细化 | 已定案:饱和模板化到各宽度(SINT/DINT/LINT);TIME+TIME / TIME-TIME / TIME 比较;浮点 IEEE 常规(溢出→±inf、0 除→±inf、NaN 传播,无特判);DATE/TOD/DT 不做运算(仅存取/比较) |
| A6 | sidecar/I/O 绑定 | 已定案:与现状一致——绑定粒度仍 slot = 槽号(指向槽表条目),channel/bit 语义不变 |
| A7 | disasm 文本格式 | 已定案:类型后缀形式:LOAD.I16 r5, s3、STORE.U32 s1, r7、ADD.F64 r1, r2, r3 |
| A8 | machine.toml V2 schema | 已定案:type 表 = 编译器内建基元别名(bit/int8/int16/int32/int64/uint8/uint16/uint32/uint64/float32/float64):REAL→base float32(=C float)、LREAL→base float64(=C double),其余按位宽/符号映射;op 表 {name, op(0..63), fmt} + fmt/type 位段互锁校验 |
| 已定案:按上下文适配;默认 DINT 仅作兜底语义(上下文恒存在,正常程序不触发) | ||
| 已定案(B1/B2):1 CAL + fb_id 16 位(查 fb 表);新增 FB 只改配置 + VM 实现 |
另:CALL 的 V2 确认(随 A10)——ret_pc 字节化(随跳转已定);CALL(IMM 形态)rd 恒 0;帧/寄存器约定不变(r0..r7 复制)。
未定 / 待细化(C1..C6)
| # | 项 | 说明 |
|---|---|---|
| 已定案(U12):v1 0 长度占位(offset_meta=0),schema 延后 | ||
| 已定案(U7 修正版):见 §2.5(offset_meta/max_stack/values_size 等) | ||
| C3 | machine.toml [[fb]] 表 schema |
字段/布局已定案(指令集清单 §8.1);[[fb]] 配置格式并入 N5(machine.toml V2 schema,阶段 1) |
| 已定案(U14):已写入指令编码.md §5 | ||
| C5 | line1 推演重算 | 实施阶段(阶段 5)才需要 |
| 已定案:指令集清单 §8.1(CTU 8B / DCTU 16B / CTUD 10B / DCTUD 16B) |
8. 待讨论(用户反问)
A9:什么情况下会没有上下文?(已定案)
ST 中字面量只能出现在表达式/赋值里(x := 5、y + 5、IF 16#FF > t THEN),
目标类型或运算操作数类型恒在,v1 无"裸字面量"位置——上下文恒存在。
因此"默认 DINT"只是防御性兜底(编译器内部缺类型时的报错路径),
正常程序不触发。结论:按上下文适配即可,默认 DINT 保留为兜底语义。已确认(2026-08-24)。
A10:FB 为什么会有 8 种?(已定案)
V1 的 CAL_TON..CAL_F_TRIG 是 8 个 opcode(24..31),因为 V1 opcode 充足、无位段压力。
V2 的 op 位段仅 6 位(64 个),FB 占 8 个不划算,且 machine.toml 已有 [[fb]] 表
(8 条,含 opcode 字段)——可收敛为 1 个 CAL(SLOT 形态)+ FB 类型 id(立即数/查 fb 表):
- 收益:op 位段省 7 个;新增 FB(如自定义内建)不加 opcode、只加配置
- 代价:VM 按 id 分派(一次查表,可接受);disasm 需查 fb 表打印名称
- 关联:A3 的单字/双字计数变体编码也随此定(fb 表加 width/type 列即可) 已定案(B1/B2):1 CAL + fb_id 16 位。
后续扩展讨论(B4/B5):领域指令(运动控制/通信)不进指令集——PLCopen 运动控制本 是 FB 库;V2 不设 EXT 服务指令,一切领域功能走 FB 库(CALL + 共享体)。op 位段预算见 B5。
5. 影响面清单
| 模块 | 改动 |
|---|---|
| isa | Op.h 重排(位域)、Instr.h 变长 pack/拆、Encode disasm 表驱动、Types 宽度/符号表 + 饱和模板化 |
| compiler | machine.toml V2(type 表 19 条 + fmt/type 位段互锁)、MachineConfig 校验、Codec 变长、Codegen(槽表+值区布局、初值写值段、E_* 变长发射、字节化回填)、Stb 新头/段 |
| vm | Image 新头/段校验、Machine 取指变长 + 两级访问(槽表→值区)+ 按 func 读写 + 预分配栈区(max_stack,替代动态 vector frames) |
| executor | slot_bool 按 BOOL 读 1 字节(小改) |
| tests | isa/vm/machine/codegen/compiler 全部重写;cases 20 个重新生成产物 |
| docs | 指令与映像、指令配置、stb文件格式、寄存器码、指令执行(line1 推演重算)、扫描周期、初步计划、README |
6. 实施阶段(每阶段独立可验证 + 提交)
- 规格冻结:本文 §4 全部闭合后,重写指令与映像.md / 指令配置.md / stb文件格式.md
- isa 重构:变长 Instr + 位域 Op + Encode + isa_test
- compiler 侧:machine.toml V2 + MachineConfig + Codec + Codegen + Stb + 对应测试
- vm 侧:Image + Machine(两级访问)+ vm_test
- executor + 全链路:cases 20 个 + cli 测试 + line1 产物重生成
- 文档收尾:指令执行推演、扫描周期、初步计划、README
7. 决策历史(讨论纪要)
- 动机源起:用户质疑 opcode 定义草率;探索 format 位前缀编码(方案 A)与 uses_rd 位掩码推导
- 数据模型演进:8B 定宽槽 →(用户提出槽表引用 + 初值分离)→ 槽表/值区两级模型
- 宽度信息:用户选「宽度编码进 opcode」(RISC-V 式,对应「槽表条目带类型」被否)
- 初值组织:用户选「整合 .stb 内分段」(ELF 式)
- 寻址规模:用户选「全 32 位」(槽号 u32 + 地址 u32)
- 指令长度:用户定「变长指令,长度编码在 opcode」;此前 128bit 固定长度方案被否
- 寄存器:用户定「编号 8 位(256/帧)维持现状」,容量恒定式 8bit×256=16bit×128=32bit×64=64bit×32
- 类型扩展:IEC 整数族 12 种 + REAL/LREAL(= C float/double)+ DATE/TOD/DT → 19 种,type:5(32 种)
- 格式合并:用户确认原子类型固定后选位段方案;数位得出 type:5;CALL→IMM、CAL→SLOT 形态合并,fmt 3 位
- 调用策略:V1 用户 FB 内联 / FC CALL / 内建 CAL_*;V2 用 16B 变体(基槽+偏移)实现 FB 共享体
- LOADF 取消:用户指出 LOADF 与 LOAD 无本质区别(仅数据搬运)→ 字段访问统一 LOAD/STORE 16B 变体
- 类型转换:用户定「禁止隐式变换,编译阶段检查」+ 字面量按上下文适配
- 字面量:用户定支持 IEC 进制前缀(2#/8#/16#)
- A2 定案:LOADK 用 type 位段解释常量值(与 LOAD 语义统一);常量表条目 8B 无 tag;IMM64 预留不发射
- A3..A8 定案(2026-08-24):计数器单/双字两种;DATE 字面量不支持;TIME/浮点运算按推荐;sidecar 一致;disasm 类型后缀;type 表=基元别名(REAL→float32、LREAL→float64)
- A9 定案:按上下文适配、默认 DINT 兜底(用户确认)
- U5 定案:内建 FB 15 条全部 v1 实现(6 计数拆条 + TON/TOF/TP/R/F_TRIG + SR/RS、PWM、RTC)
- U6 定案:op 预算按指令集清单/指令编码文档方案(前缀分区)
- U7 定案:头 128B 修正版(offset_meta 占位、values_size 命名、n_i/n_q/n_m 保留恒 0、n_slots 关系、16 对齐)
- U8 定案:槽表条目 {addr:u32, 预留:u32} 8B
- U9 定案:值段 1/2/4/8B 对齐编译器保证
- U10 定案:寄存器/调用约定维持现状、帧按 nregs 动态分配;栈方案 C(预分配栈区 + max_stack@116 编译期算 + 字节/深度双检查);递归 = 链接层环检测编译期报错
- U12 定案:元数据段 v1 0 长度占位(offset_meta=0),schema 延后
- U13 定案:DATE/TOD/DT 表示(DT={date:32|tod:32} 拼接,转换取高/低 32 位)
- U14 定案:CALL/CAL rd 字段恒 0(按指令编码/指令集清单文档)——全部 U 项闭合,V2 规格冻结
- 版本线确认:当前设计 = V2(V1 为已实现简化版);头 version = 2,型号 STATOR2
- 帧头 12B 成文(fn_id/ret_pc/ret_fn_id)+ max_stack 计算细则(MAIN 计入、DAG 最长路径)
- 整数除法语义 A 定案:除零返回被除数、MIN/-1 饱和、截断除法、MOD 符号随被除数(延续 V1 饱和算术家族)
- A10 定案(B1/B2):1 CAL + fb_id 16 位(查 fb 表);V1 的 8 个 CAL_* opcode 作废
- B4 定案:领域指令(运动控制/通信)不进指令集,一律 FB 库;无 EXT 服务指令
- B3/B5 说明中待确认:单/双字计数编码、op 位段预算(均已随 U5/U6 定案)
- 未定项记录:C1..C6(均已闭合:C1=U12、C2=U7、C3=字段表已定+配置格式入 N5、C4=U14、C5=实施阶段、C6=§8.1 字段表终稿)
9. 确认核验清单(2026-08-24 核对)
原则:未明确回答 ≠ 同意。本清单逐项记录「用户明确回答」与「待确认」, 待确认项由用户逐项表态后闭合。
9.1 已确认(用户明确回答)
| # | 项 | 用户回答 |
|---|---|---|
| K1 | 变长指令(长度编码在 opcode) | 「变长指令,指令长度编码再opcode里面」 |
| K2 | 寄存器 8 位编号 256/帧(容量恒定式) | 「寄存器大小不变,8bit256 == 16bit128 == ...」 |
| K3 | 宽度编码进 opcode(非槽表带类型) | question 选「宽度编码进 opcode」 |
| K4 | 初值整合 .stb 内分段(ELF 式) | question 选「整合在 .stb 内分段」 |
| K5 | 全 32 位寻址(槽号 u32 + 地址 u32) | question 选「全 32 位寻址」 |
| K6 | type:5(32 种,含 DATE/TOD/DT 19 基础类型) | 「B」 |
| K7 | 跳转偏移字节化 | 「接受」 |
| K8 | I/Q/M 六条合并为 LOAD/STORE 两条 | 「合并」 |
| K9 | LOADF 取消(LOAD/STORE 16B 变体=字段访问) | 「LOADF和普通的LOAD应该没有区别吧」 |
| K10 | ST 层类型全量(19 类型名进关键字) | 「全量」 |
| K11 | 禁止隐式变量转换(编译期检查) | 「禁止隐式变换,只需要编译阶段检查」 |
| K12 | 进制前缀(2#/8#/16#) | 「进制前缀」 |
| K13 | A2 常量表(LOADK type 解释、条目 8B 无 tag、IMM64 预留) | 「使用常量表吧」+ 讨论 |
| K14 | A3 计数单字/双字两种都要 | 「需要两种,单字的和双字的计数指令都要有」 |
| K15 | A4 DATE/TOD/DT 字面量 v1 不支持 | 「先不支持」 |
| K16 | A5 算术语义(饱和模板/TIME±/浮点 IEEE/DATE 不运算) | 「先做吧」 |
| K17 | A6 sidecar 绑定粒度一致(slot=槽号) | 「应该可以保持一致」 |
| K18 | A7 disasm 类型后缀(LOAD.I16 r5, s3) | 「类型后缀」 |
| K19 | A8 type 表=基元别名(REAL→float32、LREAL→float64) | 「类型:编译器内建基元...float32-float,float64-double」 |
| K20 | A9 字面量按上下文适配、默认 DINT 兜底 | 「就这么做」 |
| K21 | B1 fb_id 16 位 | 「16位」 |
| K22 | B2 1 CAL + fb_id(查 fb 表) | 「cal + fb_id」 |
| K23 | B4 领域指令不进指令集(运动/通信走 FB 库) | 「不进指令集」 |
| K24 | 前缀分区形态:011=RRR、010=其他 |
「那就011前缀的是RRR类型指令,010前缀的是其他指令」 |
| K25 | fmt 位段取消,形态全前缀分区(零查表) | 「010区也换成前缀编码,这样所有指令都统一了」 |
| K26 | MOVE 只搬宽度,不管符号/浮点;类型不匹配编译期报错 | 「move指令只管宽度和搬运...类型不匹配,编译时就报错」 |
9.2 待确认(用户未明确回答)——已全部闭合(2026-08-24)
| # | 事项 | 当前文档写法 | 待表态 |
|---|---|---|---|
| 作废:fmt 位段已取消,形态由前缀分区表达,无合并问题 | |||
| 已被前缀编码取代(11/10/011/010xxx/0010/0011/0001,见指令编码.md §3) | |||
已被取代:[前缀+形态分区|op] + [func:4|空:4](指令编码.md §2) |
|||
| 已定案(预留):只留编码路径(LOAD/STORE 16B 变体 + 元数据段),语法 v1 不实现 | |||
| 已定案:fb 表拆条 11 条(CTU/DCTU/CTD/DCTD/CTUD/DCTUD 6 计数 + TON/TOF/TP/R_TRIG/F_TRIG),名字即宽度;清单内建 FB 全部 15 条(含 SR/RS、PWM、RTC)v1 实现 | |||
| 已定案:按指令集清单.md §12 / 指令编码.md §3 方案(前缀分区预算:RR 21/64、NONE 2/64、RRR 26/32、010 区 8/24、SLOT+off 8/16、IMM64 1/16、0001 预留 6/16) | |||
| 已定案(修正版):17 字段表述、values_size 命名、offset_meta @112(v1=0)、n_i/n_q/n_m 保留恒 0、n_slots 关系定义、16 对齐(见 §2.5 注记) | |||
| 已定案:{addr:u32, 预留:u32} 8B/条(引用表,地址指向值段) | |||
| 已定案:1/2/4/8B 对齐由编译器布局保证(值段起点 16 对齐,见 U7) | |||
| 已定案:寄存器 int64 不变;调用约定不变;CALL/RET 全宽复制;帧按 nregs 动态分配(§2.2 表述修正);栈方案 C(预分配 + max_stack@116 + 字节/深度双检查 + 递归编译器报错) | |||
| 已定案:010 101 分区,操作数区 fb_id16=31..16 + slot32=63..32 | |||
| 已定案:v1 定 0 长度占位(offset_meta=0 = 空段,接口预留),字段表 schema 延后(有使用方时再定) | |||
| 已定案:DATE=uint32(天数)、TOD=uint32(当日 ms)、DT=uint64 {date:32 | tod:32} 拼接(高 32 位日期,取高/低即转换,比较天然有序);v1 无日期运算(A5);将来转换编译展开 | |||
| 已定案:CALL(010 100 区)/ CAL(010 101 区)的 rd 字节恒 0(未使用),按指令编码/指令集清单文档编码 | |||
| 已被 func=0 取代(func 位段,无类型指令编码 0 不使用) | |||
| 已确认(随 K7 跳转字节化接受) |
10. 全功能指令集清单
全功能目标下的完整指令清单(10 类 ~55 条,含 op 预算核对)已拆分为独立文档:
指令集清单.md。状态列:核心 = v1 实现;扩展 = v1 后实现;预留 = 仅留编码/未来。