示例项目
ZStudio 中内置了部分示例项目,用户可以直接从主菜单导入并跟随示例项目熟悉 ZStudio 基本使用流程及各项功能。
matrix_cmplx_mult
本节将用 matrix_cmplx_mult 示例项目演示如何用 ZIGen 创建自定义指令集,并应用于虚拟 SoC 模型,使用 ZProf 进行性能分析与设计优化。
打开 matrix_cmplx_mult 解决方案
用户可以遵循以下步骤在 ZSolution 中打开示例项目:
-
在菜单栏选择"文件" > "从示例解决方案开始",在下拉框中选择 matrix_cmplx_mult 并打开。
-
将 base 项目设置为当前活动项目,选择 Release 配置和 RISC-V 架构,点击"构建",并在构建控制台中确认构建输出。
-
成功构建后,需要指定执行性能分析的目标虚拟开发板,将 base 项目设置为当前活动项目,点击菜单栏 "性能分析" > "配置"。
- 选择开发板:在下拉框中选择"内置"
- 仿真器虚拟开发板:在下拉框中选择"RocketChip"作为目标虚拟开发板。
-
将 base 项目设置为当前活动项目,点击菜单栏 "性能分析" > "启动性能分析"生成该项目的性能分析数据,性能分析完成之前不要重新执行该行为,以免生成错误数据。性能分析完成后,结果将在编辑区打开。
接下来,我们将创建自定义指令并将其应用于 base 项目的源码中从而提升其在 RocketChip 虚拟开发板上的表现。
创建自定义指令集
用户可以从下拉菜单 中选择 ZExplorer 切换模式。
用户可以使用我们准备好的文件进行一键导入,单击
(更多操作..) >
(导入指令集)打开导入指令集弹窗,在文件系统中找到位于
/home/{user_name}/ZStudio_Workspace/Solutions/matrix_cnmplx_mult/Extension
文件夹下的 .dspmult.zsext 文件并打开。
此外,也可以遵循以下步骤熟悉指令创建过程:
点击
(新建指令集) 按钮创建 dspmult 自定义指令集。
添加 zkmxda 自定义指令
-
右键 dspmult 指令集节点,在上下文菜单中选择"新建指令",为新建指令命名为 zkmxda 然后点击"创建"。
-
进入指令编辑页面,并为自定义指令指定配置选项。
-
功能单元:从下拉框中选择 Simd 功能单元,参考功能单元支持表。
-
长度:从下拉框中选择 32 位指令长度。
-
架构:从下拉框中选择 RV32&RV64 处理器架构。
-
汇编语言: 自定义指令的汇编语言表示,即自定义指令的助记符,将根据用户定义的指令格式自动生成。
-
-
添加自定义指令格式
通过编辑编码字段定义指令 zkmxda 的格式,在弹窗中分配可用的编码空间。
- 起始索引 & 字段位宽: 控制编码具体位数和位置。
- 字段类型 & 字段值: 选择字段类型并填入字段值。
用户可以在编码表中检查自定义指令的格式,右键编码字段中的行,可以编辑或删除该行的字段,直到确定指令格式。
-
在指令行为代码编辑区中描述自定义指令的执行流程。
behaviorfor (uint32_t i = 0; i < XLen / 32; ++i) {
int16_t r1 = getHalf(rs1, 2 * i);
int16_t r2 = getHalf(rs2, 2 * i);
int32_t tmp = 0x80008000;
if (getWord(rs1, i) != tmp || getWord(rs2, i) != tmp) {
int32_t res = sext<16>(getHalf(rs1, 1 + 2 * i)) * sext<16>(r2) +
sext<16>(r1) * sext<16>(getHalf(rs2, 1 + 2 * i));
setWord(rd, i, res);
} else {
setWord(rd, i, 0x7fffffff);
setVxsat(DI);
}
}
自定义指令 zkmxda 的编码及行为如下图所示:
添加 zsmdrs 自定义指令
-
右键 dspmult 指令集节点,创建另一条自定义指令 zsmdrs。
-
进入指令编辑页面,为自定义指令 zsmdrs 指定与 zkmxda 完全一致的配置。
-
定义 zsmdrs 的编码格式并描述其执行流程。
behaviorfor (uint32_t i = 0; i < XLen / 32; ++i) {
int64_t Tmp = (int16_t)getHalf(rs1, 2 * i) * (int16_t)getHalf(rs2, 2 * i) -
(int16_t)getHalf(rs1, 1 + 2 * i) * (int16_t)getHalf(rs2, 1 + 2 * i);
setWord(rd, i, Tmp);
}