建模虚拟 SoC
ZVB 是用于架构探索和优化的 SoC 虚拟建模工具,用户可以在 ZVB 中利用丰富的内置组件进行架构设计并实现虚拟模型搭建。
快速上手
为了帮助用户快速熟悉 ZVB 的使用方法,此处准备了一个简单的示例。请跟随示例利用内置组件创建最基础的虚拟开发板并尝试运行可执行文件。
-
创建虚拟开发板
在主菜单选择 "文件" > "新建虚拟开发板"或者直接点击 (新建虚拟开发板) 按钮。在弹窗中将开发板文件命名为 Demo.zvb,开发板命名为 Demo,并调整频率(设置为 1000)和其他属性,然后点击"创建"。在左侧导航栏列表中找到刚才新建的虚拟开发板并打开空白画布。
-
添加组件
ZVB 支持使用内置组件搭建虚拟开发板并运行可执行文件,用户可以将组件导航中列出的所有可用内置组件拖拽至画布中。在此示例中,点击并拖拽 CPU 组件 InOrder5StagesCPU, 内存总线组件 NonCoherentXBar 以及内存组件 SimpleMemoryModel 至画布中。
-
连接已添加的组件
在两个组件之间建立连接只需要绘制一根线从其中一个组件的 out 类型引脚连接至另一个组件的 in 类型引脚,即在建立两个组件之间的逻辑连接。在此示例中,我们需用将 CPU 组件 InOrder5StagesCPU 的所有 out 引脚连接至内存总线组件 NonCoherentXBar 的 in 引脚,将内存总线组件 NonCoherentXBar 的 out 引脚连接至内存组件 SimpleMemoryModel 的 in 引脚。为确保虚拟开发板的正确性,需要删除所有多余的引脚端口。
-
控制组件属性
画布中所有的组件都可以通过双击在 右侧面板打开该组件的属性编辑栏。双击画布中的 NonCoherentXBar 组件,在右侧的端口编辑区单击删除按钮以减少 out 类型引脚的端口数量。同时需要将内存组件的内存地址范围设置为
0x0:0x100000000
,以确保虚拟板可以运行 ELF 文件。 -
在创建的虚拟开发板上运行 ELF 文件
右击 Demo 开发板并选择"运行 ELF 文件",在弹窗中指定 ELF 文件的路径并点击"运行"。在运行控制台中检查运行输出。
ZVB 用户界面
ZVB 虚拟建模工具提供简单易用的界面帮助用户创建和编辑虚拟开发板。
-
工具栏(Toolbar):工具栏中包含了 ZVB 常用的命令快捷键,悬浮至快捷键上可获取使用提示。
-
左侧面板(Left-hand side panel):左侧面板包含虚拟开发板,组件以及运行中的虚拟开发板导航视图。用户可以使用 Ctrl+F 在到导航中进行快速搜索。
-
编辑区(Main editor):包含虚拟开发板的画布,即虚拟开发板的创建及编辑区域。
-
右侧面板(Right-hand side panel):画布中组件的属性和端口可以在右侧面板中进行更改。
导航
左侧面板中包含虚拟开发板,组件以及运行中的虚拟开发板导航视图,用户可以通过右上角的 (More Actions...) 控制所有视图的可见性。
组件导航中以目录树结构显示了 ZVB 中的所有组件,点击导航栏右侧 (全部折叠) 按钮可以收起所有子节点,以便快速定位到自己需要的组件类型,也可以使用Ctrl+F在到导航中进行快速搜索。
当组件较多时,用户可以自定义组件的分类方式,将组件进行分层展示,例如,增加"source"层级以区分内置组件和自定义组件。右键组件类型节点并选择"显示分类",在组件层级设置弹窗中将"source"添加至已选择的类型列表 ,然后点击"确定"。
完成设置后,可以看到左侧组件导航按照用户自定义的层级进行重新分类,所有类型都新增了"builtin"和"custom"的子节点。
用户也可以自定义虚拟开发板的分类方式,右键虚拟开发板导航的空白区域并选择"显示分类",在虚拟开发板层级设置弹窗中选择需要增加的分类层级,点击 “>” 添加到至已选择的类型列表 ,并通过上下箭头调整层级顺序。
虚拟开发板导航栏将按照用户自定义的层级进行重新分类,所有虚拟开发板将以"source"作为一级分类节点,以"vendor"作为二级分类节点。
组件导航的一级节点将固定为组件类别,而虚拟开发板的所有层级节点都可以由用户自定义。
虚拟开发板编辑器
虚拟开发板编辑器即搭建和编辑虚拟开发板的主画布,用户可以在此处添加,移动,连接所有组件,并自定义组件的属性以探索最佳的 SoC 架构方案设计。
用户可以通过以下快捷键和常用操作控制画布及画布上的组件。
画布控制 | 快捷键或操作 |
---|---|
浏览画布 | 右键点击画布空白处向任意方向拖拽 |
画布缩放 | 鼠标悬浮画布上,按住 Ctrl 向上滑动滚轮放大,向下滑动滚轮缩小 |
画布居中 | 鼠标悬浮画布上,右键菜单选择"居中" |
撤销 | 聚焦画布,使用快捷键 Ctrl+Z |
重做 | 聚焦画布,使用快捷键 Ctrl+Shift+Z |
保存 | 聚焦画布,使用快捷键 Ctrl+S 或使用工具栏按钮 |
属性和端口
右侧面板中的属性(Property)和端口(Port)视图允许用户编辑当前画布中的组件属性。当用户双击选中画布中的组件时,属性和端口栏将显示该组件相关的特定属性和端口设置。
鼠标悬浮在上可以获取每种属性设置的提示信息,用户通过属性视图中的下拉框或者输入框编辑属性值,若用户输入的属性值不合法,将会收到错误提示。 通过端口视图中的按钮可以更改画布中组件的引脚数量。
自定义虚拟开发板
ZVB 允许用户基于内置虚拟开发板进行编辑和自定义,或从零开始搭建自己设计的虚拟开发板。
- 新建空白虚拟开发板:在主菜单选择 "文件" > "新建虚拟开发板" 或者点击 (新建虚拟开发板) 按钮创建空白画布。用户需要在在新建虚拟开发板弹窗中定义开发板的名字,描述,频率以及其他属性。
- 拷贝已有虚拟开发板:在虚拟开发板导航中右键点击某个开发板并选择"拷贝",在弹窗中重新定义开发板的名字,描述,频率以及其他属性并点击"创建"。
创建成功后,画布将在编辑区打开。虚拟开发板将在导航栏"custom"节点下列出。(如果未找到"custom"节点,请参考如何在导航栏中自定义分类层级。
层级和组件
ZVB 中提供了 SoC 和 CPU 两种层级帮助用户搭建更真实的虚拟开发板。
-
SoC 层级
通常来说在 SoC 层级可以将 CPU 与其他外设组件连接,例如总线,内存,终端,网络和磁盘等。
参考快速上手中演示的示例,搭建一个最基础的开发板只需要 CPU, 总线和内存三个内置组件。除了连接最基础的内存以外,用户也可以添加其他外设,如下图所示,添加中断控制器 PLIC 来管理 Uart、磁盘、以太网和其他设备的中断。
-
CPU 层级
进入 CPU 层级,用户可以定义 CPU 的 pipeline。
用户可以在 datapatch 节点下找到所有 CPU 内部的组件,常用组件如下表:
CPU 层级组件 组件 描述 PCReg 用于创建指令 Fetch 从内存中读取指令 Regfile 读写寄存器 VPU 执行向量指令 EXU 运行标量指令以及访存指令的地址生成 LSU 运行访存指令 Commit 退休指令 WriteBack 将指令结果写回 Exception 处理异常及终端
用户可以右键单击 CPU 类型组件选择"打开下层",或者选中并使用Enter快捷键来进入 CPU 内部层级操作。如果需从 CPU 层级返回 SoC 层级,只需按Esc或右键单击空白处,然后选择"返回上层"。
用户可以在组件导航中使用Ctrl+F进行快速搜索找到所有内置或自定义组件,然后将其从导航列表中拖放至画布上。用户可以通过以下方式控制画布中的组件:
放置:左键单击并拖拽以移动组件,松开鼠标以放置组件。
删除:左键点击组件,使用快捷键 Delete。
多选:按住 Ctrl 键选择多个组件;或左键拖动框选多个组件。
缩放:将鼠标悬停在组件上,直到组件右下角出现黑色圆点。单击并拖动圆点以放大或缩小组件。
拷贝:右键单击组件,然后选择"复制",在画布任意处再次右键选择"粘贴"。粘贴的组件会与原始对象重合,用户需要从原始组件中拖动出新组件。
改变组件端口位置:左键点击组件,使用快捷键 shift+R。
层级切换:左键点击 CPU 组件,快捷键 Enter 进入 CPU 层级,Esc 返回 SoC 层级。
另存为模板:右键单击画布中的对象,然后选择"保存为模板",编辑弹窗中的组件属性并创建。该组件将根据其类型在组件导航中列出。
定义组件属性
画布中所有组件的属性都可以在右侧属性编辑面板中进行更改,属性编辑面板会根据当前选中的组件动态显示可编辑的属性内容。 所有更改都将与画布中的组件同步保存,例如下图所示,用户可以在属性栏中编辑组件的名称(Name)、地址(Range)和其他属性。
CPU 组件微架构
用户可以定义 CPU 类型组件支持的 ISA 及扩展。
- 双击 CPU 类型组件以打开其属性编辑面板。
- 从 Base Instruction Set 和 Extensions 下拉列表中指定 CUP 支持的指令集及扩展。
用户也可以定义 CPU 内部执行单元运行的指令类型,ZVB 支持使用用户在 ZIGen 中自定义的指令集,用户需要在 CPU 层级 Execute 类型组件中指定与自定义指令集对应的功能单元,参考以下功能单元支持表。
Function Unit | Description |
---|---|
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 | 预留给用户进行自定义 |
用户可以遵循以下步骤配置执行单元中运行的指令类型:
- 右键单击 CPU 类型的组件然后选择"打开下层"。
- 双击 EXU0 组件以打开其属性编辑面板。
- 点击 以添加 Op List。
- 从下拉框中选择"Op Desc"。
- 指定 EXU0 组件选择功能单元。
用户需要确定在 ZIGen 中为自定义指令指定选择了同样的功能单元。关于如何创建自定义指令,请参考创建自定义指令集。
定义组件端口并连接组件
用户可以通过端口编辑栏中的增减按钮来控制组件的引脚。单击 (增加) or (删除) 以控制组件的引脚数量。灰色按钮表示所选组件的端口数量是固定的,无法自定义更改。
为了确保虚拟开发板能正常工作,用户需要删除除固定端口外所有未与其他端口连接的冗余端口。
目前一共有四种类型的端口,每种类型的端口可能存在 in、out 和 inout 三种不同的方向,只有相同类型端口可以进行连接,连接遵循由 in 端口到 out 端口的基本原则。inout 端口同时具有输入和输出的特性。一般来说只有虚拟端口(Virt Port)存在 inout 方向引脚。
端口类型 | 描述 | 组件使用说明 |
---|---|---|
访存端口(Memory Port) | 用于传递访问内存的请求以及数据 | 1.存在于各种 Bus 或者外设中(用于接收访存请求并进行处理回馈);2.存在于 datapatch 中的 Fetch 和 LSU 类型组件中(需要访问内存) |
中断端口(Interrupt Port) | 用于传递中断信号 | 存在于可以产生中断以及接收中断的组件 |
指令端口(Instruction Port) | 用于传递指令以及相关控制信号 | 存在于 datapatch 类型的组件 |
虚拟端口(Virt Port | 作为用来连接 CPU 内部与外部组件的通道 | 只存在于 CPU 类型组件中,例如,CPU 内部的 Fetch 需要通过虚拟端口进行一次转接以访问内存 |
用户将鼠标悬浮导组件端口上,从一个组件的 out 类型引脚点击并拖拽可绘制一根线连接到另一个组件的 in 类型引脚来创建组件之间的逻辑连接,此时画布中所有可连接的端口和组件显示高亮。
以虚拟开发板运行 ELF 文件
要在已经搭建完成或者内置的虚拟开发板上运行 ELF 文件,请在虚拟开发板导航中右键单击某个虚拟开发板,然后选择"运行 ELF 文件"。在弹窗中ELF 文件路径中选择要运行的可执行文件,然后单击"运行"。用户可以在运行控制台中检查运行输出。