Files
Interpreter/Doc/isa/指令集优化.md
T
Admin b70bea6b54 文档:指令集优化 V2 草案(变长指令/槽表值区/IEC 类型扩展/待确认问题)
- 动机:opcode 位域化、8B 定宽槽浪费、类型扩展、结构体预留、变长指令
- 已定案:变长指令(长度组在 opcode)、寄存器 8 位编号维持、槽表→值区
  两级模型、宽度编码进 opcode、初值同文件分段、全 32 位寻址、STATOR2
- 待确认:跳转字节化 / type:4 vs 5 / 长度组映射 / I/Q/M 合并 / 结构体范围
  / ST 层类型支持 / 转换规则 / 字面量
- 影响面清单 + 6 阶段实施计划 + 决策历史
2026-08-24 10:46:25 +08:00

10 KiB
Raw Blame History

指令集优化(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)的自然覆盖,由格式决定整条长度
字节 0        字节 1       字节 2   字节 3   字节 4   字节 5..13(按长度组)
[len:2|op:6] [fmt:4|type:4] rd:8   rs1:8   rs2:8   扩展区
长度组 指令长度 覆盖格式 字段
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 数据模型:槽表(引用)→ 值区(数据)

槽表段(静态引用表,8B/条)           值段(初值,紧凑变宽)
┌─────────────────────────┐          ┌──────────────────────────┐
│ { addr:u32, 预留:u32 }  │ ──地址──▶ │ BOOL 1B(1 对齐)          │
│ 槽 0..n_slots-1          │          │ INT  2B(2 对齐)          │
└─────────────────────────┘          │ TIME 8B8 对齐)          │
                                     │ 结构体 = 连续字段块(预留)  │
                                     └──────────────────────────┘
  • 访问:LOAD rd, slotaddr = 槽表[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 引用)、值区地址 u324GB)

2.4 类型系统:IEC 整数族扩展

type 位段候选:type:416 种)——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 对齐)

0..71   原 15 字段(magic/版本/cycle_limit/dt_ms/hash/entry/n_globals/n_i/n_q/n_m/
        n_consts/n_funcs + offset_const/funcs/code
64      offset_slots      ← 槽表段(原 offset_fb 改义,FB 并入值区)
68      offset_values     ← 值段
72..103 型号标识(STATOR2
104     n_slots           ← 新增
108     n_values          ← 新增(值段字节数)
112..127 预留

段序:头 → 常量表 → 函数表 → 字节码 → 槽表段 → 值段 → 元数据段(预留) → SHA-256 尾

2.6 其他定案

  • 型号 bumpSTATOR1 → 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 预留
结构体 不支持 元数据段字段表(预留)
寻址空间 槽 65535512KB 槽 2^32、值区 4GB
初值 槽内 值段(逻辑分段,同文件)
跳转/pc 条数单位 字节单位(待确认 §4
型号 STATOR1 STATOR2

4. 待确认问题

# 问题 选项 推荐
1 跳转偏移单位字节化:off32(字节,相对下一条)、pc/code_offset/code_len 全字节单位、code 段 16 字节对齐 接受 / 保持条数 接受(变长指令下按条数算偏移不成立)
2 type 位段宽度type:416 种,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 V2type 表 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. 实施阶段(每阶段独立可验证 + 提交)

  1. 规格冻结:文档先行——本文件确认全部待确认项后,重写指令与映像.md / 指令配置.md / stb文件格式.md
  2. isa 重构:变长 Instr + 位域 Op + Encode + isa_test
  3. compiler 侧machine.toml V2 + MachineConfig + Codec + Codegen + Stb + 对应测试
  4. vm 侧Image + Machine(两级访问)+ vm_test
  5. executor + 全链路cases 20 个 + cli 测试 + line1 产物重生成
  6. 文档收尾:指令执行推演、扫描周期、初步计划、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