Files
Interpreter/Doc/isa/指令集优化.md
T
Admin 3ec803c5a8 文档:指令集优化——补 REAL/LREAL(float/double)、FB/FC 内联现状与 V2 基址寻址方向
- §2.4 类型表 16 种满编(type:4),含 C 对应列;浮点表示/常量 tag/字面量
- §2.7 新增:V1 三种调用处理(FB 内联/FC CALL/CAL_*)+ V2 基址寻址消除内联膨胀
- §3 差异表加 FB 行;§4 待确认加 FB 共享体与浮点字面量;§7 决策历史补记
2026-08-24 10:52:46 +08:00

13 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 标量族扩展(16 种满编)

type 位段:type:416 种)16 个 IEC 标量满编零预留BOOL + 位串 4 + 有符号 4 + 无符号 4 + TIME + REAL + LREAL);结构体/字符串/数组不占位段,走元数据段字段表(LOADF rd, slot, field_id,宽度从元数据查)。将来新增标量类型需扩 type:5(32 种)——待确认(见 §4 项 2)。

type 类型 宽度 符号 C 对应 type 类型 宽度 符号 C 对应
0 BOOL 1B bool 8 LINT 8B int64_t
1 BYTE 1B uint8_t 9 USINT 1B uint8_t
2 WORD 2B uint16_t 10 UINT 2B uint16_t
3 DWORD 4B uint32_t 11 UDINT 4B uint32_t
4 LWORD 8B uint64_t 12 ULINT 8B uint64_t
5 SINT 1B int8_t 13 TIME 8B 有(ms) int64_t
6 INT 2B int16_t 14 REAL 4B IEEE754 float
7 DINT 4B int32_t 15 LREAL 8B IEEE754 double
  • type 位段红利:CMP/算术按类型自动语义——无符号类型无符号比较、整数饱和到类型宽度(模板化)、浮点走 IEEE 754(无饱和,溢出→±inf)、读取按宽度+符号/零扩展
  • 浮点表示REAL 4B / LREAL 8B,值区 4/8 字节对齐;寄存器 int64 位模式搬运(REAL 低 4 字节),运算时按 type 重解释
  • 常量表 tag 契约升级:tag = type 位段值(0..15),REAL=14 / LREAL=15 存位模式
  • ST 字面量:浮点十进制字面量(1.5-2.5e3)v1 是否支持——待确认(见 §4 项 10)

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

2.7 调用与内联策略(V1 现状 + V2 方向)

V1 现状POU 调用三种处理方式:

对象 V1 处理 原因
用户 FBFUNCTION_BLOCK 调用点内联展开(字节码随调用点数膨胀) 12.8 定案:FB 体访问绝对字段地址LOAD_GLOBAL rd, 基槽+字段序),不同实例基址不同,共享函数体无法复用;无递归、无动态实例 → 内联安全
FUNCTIONFC 独立函数 + CALL fn_id 帧栈 FC 无状态,参数/结果走寄存器约定(r1..r7 / r0),无字段地址冲突;递归在前层被拒(用例 19)
内建 FBTON/CTU/…) CAL_* 指令(VM 运行时原语 do_cal 定时器/计数器是 VM 侧状态机,天然共享

代价:内联 = 字节码膨胀(FB 每调用一次复制一份体),V1 规模可接受;寄存器码.md 注记「以后可升级为基址寄存器寻址指令」。

V2 机会:槽表模型下 FB 体可共享——FB 实例字段经「槽表条目 → 值区地址」定位,若引入基址寻址指令(如 LOAD rd, base_slot, field_off / STORE base_slot, field_off, rs,base 槽取自寄存器或立即数),FB 体编译一次、运行时按实例基址定位字段,消除内联膨胀。16 字节长度组(SLOT+off)已为此预留。是否实施 → 待确认(见 §4 项 9)。

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 预留
结构体 不支持 元数据段字段表(预留)
FB 调用 用户 FB 内联展开(字节码膨胀) 基址寻址指令共享 FB 体(待确认 §4)
寻址空间 槽 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
9 FB 共享体:基址寻址指令(LOAD/STORE rd, base_slot, field_off)消除用户 FB 内联膨胀 实施 / 维持内联 实施(16B 长度组已预留)
10 REAL/LREAL:浮点类型与 C float/double 对应(4B/8BIEEE 754);type 位段随之满编 16 标量(零预留) type:4 满编 / type:5 留扩展 见 §2.4

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 整数族(BYTE..ULINT 12 种)+ REAL/LREAL= C float/doubleIEEE 754
  • 调用策略:确认 V1 用户 FB 内联 / FUNCTION 走 CALL / 内建 FB 走 CAL_*;V2 探索基址寻址指令消除内联膨胀
  • 类型扩展:用户提出 IEC 整数族 12 种(BYTE..ULINT