指令集优化(V2 草案,型号 STATOR2)
状态:设计中。本文汇总「指令集优化」的全部信息:动机、已确认设计决策、
待确认问题、影响面与实施阶段。全部内容为草案,未进入实现。
与现状(V1)的关系:V1 编码冻结不可改(opcode 0..33、32bit 指令、8 字节定宽槽),
本优化为全新 V2 架构,.stb 格式 / 指令字 / 数据模型全部重设计,型号 bump 为 STATOR2。
1. 背景与动机
| # |
现状问题 |
优化方向 |
| 1 |
opcode 定义草率:34 条按语义乱序编号,无位域结构 |
format/宽度编码进 opcode,位掩码机械推导 |
| 2 |
8 字节定宽槽浪费:BOOL 只用 1/8 空间 |
变宽紧凑值区(1/2/8 字节按类型) |
| 3 |
变量区利用率低 |
值区按类型紧凑布局 + 地址 u32(4GB) |
| 4 |
类型只有 BOOL/INT/TIME |
扩展 IEC 整数族(12 种)+ REAL 预留 |
| 5 |
结构体无法支持 |
槽表引用 + 元数据段字段表(预留) |
| 6 |
寄存器上限 256、指令 32bit 固定 |
变长指令(长度编码在 opcode);寄存器编号维持 8 位 |
| 7 |
槽(变量)与初值(数据)耦合在同一格 |
槽表(引用)与值区(数据)解耦 |
2. 已确认设计决策
2.1 变长指令,长度编码在 opcode
- 指令长度不固定:4 / 8 / 16 字节(32 字节预留)
- 长度组 = opcode 高 2 位:
[len:2 | op:6]
- 长度组 = 格式(fmt)的自然覆盖,由格式决定整条长度
| 长度组 |
指令长度 |
覆盖格式 |
字段 |
00 |
4 字节 |
NONE / RR |
头 + rd + rs1 |
01 |
8 字节 |
RRR / JMP / JC / CALL / CAL / IMM / SLOT |
头 + rd + rs1 + rs2 + slot32/fn_id32/off32/const_id32 |
10 |
16 字节 |
SLOT+off / IMM64 |
头 + rd + rs1 + slot32 + off32/imm64 |
11 |
32 字节 |
预留 |
超大立即数/未来扩展 |
- 取指:读字节 0 →
len 位段定总长 → 搬 4/8/16 字节
- 位掩码推导(三件事全编码在头两字节):
- 指令长度 ←
len 组
- 格式(uses_rd/uses_ra/uses_rb)←
fmt 位段:uses_rd = fmt∈{RR,RRR,IMM,SLOT,JC}、uses_ra = fmt∈{RR,RRR}、uses_rb = {RRR}
- 数据宽度/符号 ←
type 位段(查 constexpr 宽度/符号表)
2.2 寄存器模型(维持现状)
- 寄存器编号 = 1 字节(8 位)→ 256 个/帧(定长)
- 编号容量恒定关系:
8bit×256 == 16bit×128 == 32bit×64 == 64bit×32(编号位宽 × 数量反比,总容量恒定)
- 寄存器值仍 8 字节(int64);codegen
register overflow (>256) 检查保留
- 调用约定不变:r0 结果、r1..r7 参数、r8+ 变量/临时
2.3 数据模型:槽表(引用)→ 值区(数据)
- 访问:
LOAD rd, slot → addr = 槽表[slot].addr → 值区按 type 位段读 1/2/8 字节
- 两级间接:每次访问多一次内存读(PLC 规模无感)
- 宽度编码进 opcode(用户决策):
type 位段携带宽度 + 符号,VM 无歧义读写(解决 V1 定宽的原因——V1 因"变宽布局无法从槽号推断宽度"而改定宽,V2 用 type 位段化解)
- 对齐规则:1/2/8 字节,编译器布局保证
- 初值整合在 .stb 内分段(用户决策,ELF 式):槽表段 / 值段 / 元数据段并列,单文件 SHA-256 校验
- 寻址规模(用户决策):全 32 位——槽号 u32(2^32 引用)、值区地址 u32(4GB)
2.4 类型系统:IEC 整数族扩展
type 位段候选:type:4(16 种)——14 个 IEC 标量 + REAL + 预留 1;结构体/字符串/数组不占位段,走元数据段字段表(LOADF rd, slot, field_id,宽度从元数据查)
| type |
宽度 |
符号 |
type |
宽度 |
符号 |
| BOOL |
1B |
— |
SINT |
1B |
有 |
| BYTE |
1B |
无 |
INT |
2B |
有 |
| WORD |
2B |
无 |
DINT |
4B |
有 |
| DWORD |
4B |
无 |
LINT |
8B |
有 |
| LWORD |
8B |
无 |
USINT |
1B |
无 |
| TIME |
8B |
有(ms) |
UINT |
2B |
无 |
|
|
|
UDINT |
4B |
无 |
|
|
|
ULINT |
8B |
无 |
- type 位段红利:CMP/算术按类型自动语义——无符号类型无符号比较、饱和到类型宽度(模板化)、读取按宽度+符号/零扩展
- 常量表
tag 契约升级:tag = type 位段值(0..14)
2.5 映像格式(头 128 字节,16 对齐)
段序:头 → 常量表 → 函数表 → 字节码 → 槽表段 → 值段 → 元数据段(预留) → SHA-256 尾
2.6 其他定案
- 型号 bump:STATOR1 → STATOR2(格式大变,老 .stb 被型号校验明确拒绝)
- I/Q/M 六条 LOAD/STORE 合并为 LOAD/STORE 两条(单一值区,语义标签交给 sidecar)——待确认(见 §4)
- 结构体 v1 只留编码(LOADF + 元数据段)不实现语法——待确认(见 §4)
3. 与 V1 的差异对照
| 项 |
V1(现状) |
V2(草案) |
| 指令长度 |
固定 32bit |
变长 4/8/16B,长度在 opcode |
| opcode |
0..33 乱序,无位域 |
[len:2|op:6] + [fmt:4|type:4] 位域 |
| 寄存器编号 |
8 位(256/帧) |
8 位(256/帧,不变) |
| 变量访问 |
立即数槽号直接寻址 |
槽表引用 → 值区(两级间接) |
| 槽 |
8B 定宽 |
8B 引用表({addr:u32}) |
| 值区 |
定宽 8B/变量 |
变宽紧凑(1/2/8B) |
| 宽度信息 |
无(定宽) |
type 位段(RISC-V lb/lh/lw 式) |
| 类型 |
BOOL/INT/TIME |
14 IEC 标量 + REAL 预留 |
| 结构体 |
不支持 |
元数据段字段表(预留) |
| 寻址空间 |
槽 65535(512KB) |
槽 2^32、值区 4GB |
| 初值 |
槽内 |
值段(逻辑分段,同文件) |
| 跳转/pc |
条数单位 |
字节单位(待确认 §4) |
| 型号 |
STATOR1 |
STATOR2 |
4. 待确认问题
| # |
问题 |
选项 |
推荐 |
| 1 |
跳转偏移单位字节化:off32(字节,相对下一条)、pc/code_offset/code_len 全字节单位、code 段 16 字节对齐 |
接受 / 保持条数 |
接受(变长指令下按条数算偏移不成立) |
| 2 |
type 位段宽度:type:4(16 种,14 标量+REAL+预留 1,结构体走元数据)vs type:5(32 种,寄存器位段借位) |
type:4 / type:5 |
type:4 + 元数据段 |
| 3 |
长度组映射:00=4B、01=8B、10=16B、11=32B 预留 |
接受 / 2B 粒度 |
接受 4/8/16 |
| 4 |
I/Q/M 合并:六条 LOAD_I/M/GLOBAL、STORE_Q/M/GLOBAL 合并为 LOAD/STORE 两条 |
合并 / 保留 |
合并 |
| 5 |
结构体 v1 范围:只留编码(LOADF + 元数据段)不实现语法 |
预留 / 实现 |
预留 |
| 6 |
ST 语言层类型支持:12 类型名进关键字全量支持 vs 仅类型系统支持 |
全量 / 仅系统 |
全量(声明即可用) |
| 7 |
类型转换规则:隐式升宽(SINT→INT→DINT→LINT、BYTE→WORD→…)允许、降宽禁止 |
按此 / 全显式 |
隐式升宽 |
| 8 |
字面量:IEC 进制前缀(2#/8#/16#)是否 v1 支持 |
十进制 only / 进制前缀 |
十进制 only |
5. 影响面清单
| 模块 |
改动 |
| isa |
Op.h 重排(位域)、Instr.h 变长 pack/拆、Encode disasm 表驱动、Types 宽度/符号表 + 饱和模板化 |
| compiler |
machine.toml V2(type 表 14 条 + fmt/type 位段列)、MachineConfig 互锁校验、Codec 变长、Codegen(槽表+值区布局、初值写值段、E_* 发射器)、Stb 新头/段 |
| vm |
Image 新头/段校验、Machine 取指变长 + 两级访问(槽表→值区)+ 按 type 读写 |
| executor |
slot_bool 按 BOOL 读 1 字节(小改) |
| tests |
isa/vm/machine/codegen/compiler 全部重写;cases 20 个重新生成产物 |
| docs |
指令与映像、指令配置、stb文件格式、寄存器码、指令执行(line1 推演重算)、扫描周期、初步计划、README |
6. 实施阶段(每阶段独立可验证 + 提交)
- 规格冻结:文档先行——本文件确认全部待确认项后,重写指令与映像.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 lb/lh/lw 式,对应「槽表条目带类型」被否)
- 初值组织:用户选「整合 .stb 内分段」(ELF 式)
- 寻址规模:用户选「全 32 位」(槽号 u32 + 地址 u32)
- 指令长度:用户定「变长指令,长度编码在 opcode」;此前 128bit 固定长度方案被否
- 寄存器:用户定「编号 8 位(256/帧)维持现状」,容量恒定式 8bit×256=16bit×128=32bit×64=64bit×32
- 类型扩展:用户提出 IEC 整数族 12 种(BYTE..ULINT)