跳到主要内容

自定义指令集扩展

ZStudio 中内置了自定义指令工具 ZIGen, 方便用户使用图形界面添加自定义指令并生成动态库。ZIGen 可以配合 ZStudio 中其他工具一起使用进行高效快速的架构探索。关于创建并使用自定义指令并的示例项目,请参考 add 示例项目。

创建自定义指令集

ZIGen 视图侧栏中列出了内置的 RISC-V 基本整数指令和标准扩展,用户可以创建新的指令集以扩展 RISC-V 基础的指令集架构来满足更高的要求。

在主菜单中,点击"视图" > "ZIGen"打开指令生成工具,开始创建自定义指令:

  1. 新建指令集

    点击 new-extension-button (新建指令集) 创建一个全新的空指令集。

  2. 新建指令

    右键指令集节点,在上下文菜单中选择"新建指令",为新建指令命名然后点击"创建"。用户也可以直接点击 ZIGen 侧栏右上角 new-instruction-button (新建指令) 进行指令创建。

  3. 进入指令编辑页面,并为自定义指令指定配置选项。

    • 功能单元:选择自定义指令需要的专用硬件资源(VPU, IntAlu 等)。用户在虚拟开发板模型 CPU 层级的 EXU 组件中指定与自定义指令相同的功能单元即可在该功能单元中使用自定义指令。 参考 CPU 组件微架构和以下功能单元支持表。

      功能单元支持表
      Function UnitDescription
      IntAlu整数运算单元
      IntBru整数分支单元
      IntMult整数乘法单元
      IntDiv整数除法单元
      FloatAdd浮点加法单元
      FloatCmp浮点比较单元
      FloatCvt浮点转换单元
      FloatMult浮点乘法单元
      FloatMultAcc浮点乘累加单元
      FloatDiv浮点除法单元
      FloatMisc浮点杂项单元
      FloatSqrt浮点平方根单元
      MemRead内存读取单元
      MemWrite内存写入单元
      FloatMemRead浮点内存读取单元
      FloatMemWrite浮点内存写入单元
      VPU向量处理单元
      SIMD单指令多数据
      Builtin包含除 Cus 以外以上所有类型
      Cus0/Cus1/Cus2/Cus3/Cus4预留给用户进行自定义
    • 长度:选择自定义指令的长度(16 位/32 位)。

    • 架构:选择自定义指令适用的处理器架构(RV32/RV64)。

    • 汇编语言:自定义指令的汇编语言表示,即自定义指令的助记符,将根据用户定义的指令格式自动生成。

    创建自定义指令
  4. 添加自定义指令编码

    通过编辑编码字段定义指令的格式。点击 add-button (添加) 并在弹窗中分配可用的编码空间,分段的立即数类型的字段支持一次性添加完。

    Add *imm* type encoding field

    ZStudio 提供了内置的 16/32 位指令格式模板,用户可以点击 import-template-button (导入模板) 选择一个模板应用于当前编码字段,也可以点击 export-as-template-button (导出为模板) 将定义好的指令格式保存为模板进行复用。所用指令模板都可以通过模板管理进行查看和编辑。

    添加编码字段
    • 起始索引 & 字段位宽: 控制编码具体位数和位置。
    • 字段类型 & 字段值: 参考下方表格,选择字段类型并填入字段值。
    编码字段的类型
    字段类型描述
    opcode操作码用于定义指令的基本类型,用户创建新指令时,将根据指令长度生成 opcode 默认值。opcode 仅支持修改字段值,不支持修改其字段类型,起始位置及位宽。
    functionfunct 字段用于进一步区分不同的指令,funct 字段的具体位数和位置取决于指令的类型和长度。
    reg寄存器包含 "GPR,GPRC,FRR,FRRC 和 VR" 五个子类型。用户需要为每个寄存器分配位数并设置"读取,写入,读取/写入"方向;每条自定义指令中仅允许存在一个输出。
    imm立即数即指令中的常数值,立即数允许带符号或不带符号,允许有不同的长度。用户需要为立即数分配具体的位数并指定偏移值(offset)。
    customFlag自定义字段允许用户命名一个新的字段类型,为其分配具体的位数,并设置为常量值。
  5. 检查自定义指令编码

    用户可以在编码表中检查自定义指令的格式,并在编码字段中右键需要调整的行,进行编辑或删除字段,直到确定指令格式。

    在编码表中检查自定义指令格式
  6. 定义指令行为

    在指令行为代码编辑区中描述自定义指令的执行流程,异常处理逻辑,其他约束等。

    定义指令行为
  7. 预览自定义指令

    右键指令集并选择"预览",检查指令集中的所有自定义指令。上方搜索框可以帮助用户进行快速查找。点击指令左侧的齿轮按钮,可以重新打开指令编辑页面,调整指令格式(内置指令不支持编辑)。

    预览自定义指令集
  8. 生成自定义指令动态库

    右键指令集并选择"生成动态库",在运行控制台查看生成进度并等待右下角" 指令扩展<extension_name>生成动态库成功。 " 的消息提示。生成的动态库将显示在动态库导航下。

    提示

    用户可以通过右上角的 more-action-button (More Actions...) 控制所有指令集和动态库导航视图的可见性。

    生成动态库

每个自定义指令集都将生成一个动态库及一个头文件,其中包括指令集中的所有指令。编译器和仿真器需要调用的动态库将保存在文件系统中的 Home/{user_name}/ZStudio_Workspace/lib 目录下;程序所需包含的宏定义将保存在文件系统中的 Home/{user_name}/ZStudio_Workspace/include 目录下。

使用自定义指令集

在下拉菜单中选择 ZSolution 切换模式,并尝试将自定义指令集用于新建项目中。

进入 ZSolution 并创建新项目

关于在程序中使用自定义指令集的示例项目,请参考 add

  1. 在解决方案和项目中使用自定义指令集

    • 在编码中包含自定义指令集的头文件。
    • 在编码中使用需要的自定义指令。
    包含头文件并使用自定义指令编码
    提示

    如果编码写汇编可以不去包含该头文件。

  2. 更改构建配置

    点击 gear-button (构建配置)按钮,在构建配置中指定 Arch 和 ABI。Arch 格式为 {standard_feature}_x{custom_extension}, 其中 x 是添加自定义指令集的前缀,目前支持的 RISC-V 架构 arch/abi 选项组合为:

    march=rv32eac/ilp32e@march=rv32eac@mabi=ilp32e
    march=rv32ea_zca_zcb_zcmp_zcmt/ilp32e@march=rv32ea_zca_zcb_zcmp_zcmt@mabi=ilp32e
    march=rv32ec/ilp32e@march=rv32ec@mabi=ilp32e
    march=rv32ec_zmmul/ilp32e@march=rv32ec_zmmul@mabi=ilp32e
    march=rv32emac/ilp32e@march=rv32emac@mabi=ilp32e
    march=rv32ema_zca_zcb_zcmp_zcmt/ilp32e@march=rv32ema_zca_zcb_zcmp_zcmt@mabi=ilp32e
    march=rv32emc/ilp32e@march=rv32emc@mabi=ilp32e
    march=rv32em_zca_zcb_zcmp_zcmt/ilp32e@march=rv32em_zca_zcb_zcmp_zcmt@mabi=ilp32e
    march=rv32e_zca_zcb_zcmp_zcmt/ilp32e@march=rv32e_zca_zcb_zcmp_zcmt@mabi=ilp32e
    march=rv32e_zmmul_zca_zcb_zcmp_zcmt/ilp32e@march=rv32e_zmmul_zca_zcb_zcmp_zcmt@mabi=ilp32e
    march=rv32imafdc/ilp32d@march=rv32imafdc@mabi=ilp32d
    march=rv32iac/ilp32@march=rv32iac@mabi=ilp32
    march=rv32ia_zca_zcb_zcmp_zcmt/ilp32@march=rv32ia_zca_zcb_zcmp_zcmt@mabi=ilp32
    march=rv32ic/ilp32@march=rv32ic@mabi=ilp32
    march=rv32ic_zmmul/ilp32@march=rv32ic_zmmul@mabi=ilp32
    march=rv32imac/ilp32@march=rv32imac@mabi=ilp32
    march=rv32imac_xxldsp/ilp32@march=rv32imac_xxldsp@mabi=ilp32
    march=rv32imac_zba_zbb_zbc_zbs/ilp32@march=rv32imac_zba_zbb_zbc_zbs@mabi=ilp32
    march=rv32imac_zba_zbb_zbc_zbs_xxldsp/ilp32@march=rv32imac_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32
    march=rv32imafc/ilp32f@march=rv32imafc@mabi=ilp32f
    march=rv32imafc_xxldsp/ilp32f@march=rv32imafc_xxldsp@mabi=ilp32f
    march=rv32imafc_zba_zbb_zbc_zbs/ilp32f@march=rv32imafc_zba_zbb_zbc_zbs@mabi=ilp32f
    march=rv32imafc_zba_zbb_zbc_zbs_xxldsp/ilp32f@march=rv32imafc_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32f
    march=rv32imafc_zp052b/ilp32f@march=rv32imafc_zp052b@mabi=ilp32f
    march=rv32imafc_zp052b_xandes/ilp32f@march=rv32imafc_zp052b_xandes@mabi=ilp32f
    march=rv32imafdc/ilp32d@march=rv32imafdc@mabi=ilp32d
    march=rv32imafdc_xxldsp/ilp32d@march=rv32imafdc_xxldsp@mabi=ilp32d
    march=rv32imafdc_zba_zbb_zbc_zbs/ilp32d@march=rv32imafdc_zba_zbb_zbc_zbs@mabi=ilp32d
    march=rv32imafdc_zba_zbb_zbc_zbs_xxldsp/ilp32d@march=rv32imafdc_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32d
    march=rv32imafdc_zp052b/ilp32d@march=rv32imafdc_zp052b@mabi=ilp32d
    march=rv32imafdc_zp052b_xandes/ilp32d@march=rv32imafdc_zp052b_xandes@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcd_zcf/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcd_zcf_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf_xxldsp@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcf_zcmp_zcmt/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_xxldsp@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=ilp32d
    march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32d
    march=rv32imaf_zca_zcb_zcf_zcmp_zcmt/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt@mabi=ilp32f
    march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_xxldsp/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_xxldsp@mabi=ilp32f
    march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=ilp32f
    march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32f
    march=rv32ima_zca_zcb_zcmp_zcmt/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt@mabi=ilp32
    march=rv32ima_zca_zcb_zcmp_zcmt_xxldsp/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt_xxldsp@mabi=ilp32
    march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=ilp32
    march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32
    march=rv32imc/ilp32@march=rv32imc@mabi=ilp32
    march=rv32im_zca_zcb_zcmp_zcmt/ilp32@march=rv32im_zca_zcb_zcmp_zcmt@mabi=ilp32
    march=rv32i_zca_zcb_zcmp_zcmt/ilp32@march=rv32i_zca_zcb_zcmp_zcmt@mabi=ilp32
    march=rv32i_zmmul_zca_zcb_zcmp_zcmt/ilp32@march=rv32i_zmmul_zca_zcb_zcmp_zcmt@mabi=ilp32
    march=rv64imafdc/lp64d@march=rv64imafdc@mabi=lp64d
    march=rv64imafdcv/lp64d@march=rv64imafdcv@mabi=lp64d
    march=rv64imafdv/lp64d@march=rv64imafdv@mabi=lp64d
    march=rv64imac/lp64@march=rv64imac@mabi=lp64
    march=rv64imac_zba_zbb_zbc_zbs/lp64@march=rv64imac_zba_zbb_zbc_zbs@mabi=lp64
    march=rv64imafc/lp64f@march=rv64imafc@mabi=lp64f
    march=rv64imafc_zba_zbb_zbc_zbs/lp64f@march=rv64imafc_zba_zbb_zbc_zbs@mabi=lp64f
    march=rv64imafdc/lp64d@march=rv64imafdc@mabi=lp64d
    march=rv64imafdc_zba_zbb_zbc_zbs/lp64d@march=rv64imafdc_zba_zbb_zbc_zbs@mabi=lp64d
    march=rv64imafd_zca_zcb_zcd/lp64d@march=rv64imafd_zca_zcb_zcd@mabi=lp64d
    march=rv64imafd_zca_zcb_zcd_zba_zbb_zbc_zbs/lp64d@march=rv64imafd_zca_zcb_zcd_zba_zbb_zbc_zbs@mabi=lp64d
    march=rv64imafd_zca_zcb_zcmp_zcmt/lp64d@march=rv64imafd_zca_zcb_zcmp_zcmt@mabi=lp64d
    march=rv64imafd_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/lp64d@march=rv64imafd_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=lp64d
    march=rv64imaf_zca_zcb_zcmp_zcmt/lp64f@march=rv64imaf_zca_zcb_zcmp_zcmt@mabi=lp64f
    march=rv64imaf_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/lp64f@march=rv64imaf_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=lp64f
    march=rv64ima_zca_zcb_zcmp_zcmt/lp64@march=rv64ima_zca_zcb_zcmp_zcmt@mabi=lp64
    march=rv64ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/lp64@march=rv64ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=lp64

    在构建配置中指定 Arch 和 ABI

    当用户在构建配置中指定架构(Arch)后,构建项目无需单独指定头文件路径,头文件将被包含在代码中,自定义指令集生成的动态库将链接到可执行文件中。

  3. 构建项目并检查构建结果

    点击项目快捷控制中的 build-button 按钮并在构建控制台中检查构建输出。

  4. 运行项目并检查运行结果

    点击项目快捷控制中的 run-button 按钮并在运行控制台中检查运行输出。

指令集导入和导出

ZStudio 支持导入本地自定义指令集或将指令集导出为 .zsext 格式文件,帮助用户与团队成员进行跨平台协作创建自定义指令集。

导入指令集

用户点击 import-extension-button (Import Extension) 打开导入指令集弹窗,在资源管理器中找到 .zsext 文件并打开。导入的指令集将显示在 ZIGen 视图侧栏,用户可以编辑或者往导入指令集中添加自定义指令。

导出指令集

用户右键选择导出指令集 并在弹窗中输入导出文件的保存位置和文件名。ZStudio 将创建一个 {file_name}.zsext 文件并在编辑器中打开。

导出的 .zsext 文件可以分享给团队成员,或者在其他平台的 ZStudio 中导入进行跨平台协作。

导出指令集编码

ZIGen 同样支持将自定义的指令集导出为 txt 格式编码表,用户可以通过导出指令集编码表,进一步设计架构,验证以及输出指令集架构文档。

用户右键某个指令集节点,选择"导出指令集编码",在弹出的对话框中指定导出 .txt 文件名及保存路径。

指定导出指令集名和保存位置

用户可以在右下角的通知栏中查看导出进度,导出文件将在编辑器中打开并保存在 Home/ZStudio (Linux)或 C:\Users\{User_name}\ZStudio (Windows)目录下。

导出指令集编码

模板管理

ZExplorer 提供模板管理工具用于查看,编辑和管理所有内置和用户自定义的指令模板。在主菜单点击"视图" > "模板管理" 进入模板管理面板。

打开指令模板管理面板

所有内置和用户添加的指令模板按指令长度进行分类,用户可以收起或展开"16bits"或"32bits"寻找并快速定位想要的指令格式。

指令模板左侧的齿轮按钮提供了对模板进行复制,重命名,删除的选项;用户也可以在模板管理页面直接编辑指令格式。右键需要编辑的字段单元格选择"编辑字段",在弹窗中更改字段的长度,类型和字段值。文件图标为锁的内置指令模板不支持编辑,但是用户可以复制该模板后编辑副本。