Gem5 全系统模拟CXL设备/协议

全系统模拟

官方教程:Gem5官方教程 全系统模拟一共需要三部分

  • gem5.opt
  • 内核镜像
  • 磁盘镜像

不过我们并不需要所有都自己编译,gem5提供了不同处理器架构的预编译文件,可以在gem5 resource中搜索需要的文件

一、编译Gem5.opt

本机环境: Ubuntu 22.04

需要安装如下依赖

sudo apt install build-essential git m4 scons zlib1g zlib1g-dev libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev python-dev python

安装完依赖之后,进入项目的Gem5目录,之下如下命令编译出gem5.opt

bash 复制代码
scons build/X86/gem5.opt -j <your cores + 1>

二、 获取资源

  • 已经编译gem5.opt,当前位于 gem5 根目录,编译得到X86架构的 build/X86/gem5.opt

  • 获取内核镜像

    bash 复制代码
    wget http://dist.gem5.org/dist/v22-0/kernels/x86/static/vmlinux-4.4.186

    这里使用的是预编译过的 4.4.186 linux内核,当然也可以选择其他版本比如4.19.83

    如果需要其他内核版本则需要自行编译Linux内核,请参考Linux 内核编译编译得到根目录下的vmlinux

  • 获取磁盘镜像

    磁盘镜像解压之后稍微有点大,大概25GB左右

    bash 复制代码
    wget http://dist.gem5.org/dist/v22-0/images/x86/ubuntu-18-04/parsec.img.gz
    gzip -d parsec.img.gz

三、开始全系统模拟

模拟的命令要手敲! 不要用 Makefile, 坑死我了......

创建目录

bash 复制代码
mkdir full-system-image
mkdir full-system-image/disks
mkdir full-system-image/kernel
cp vmlinux-4.4.186 full-system-image/kernel
cp parsec.img full-system-image/disks
# 保存模拟结果
mkdir fs-result

这里的 diskskernel 目录名不要修改

配置全局M5_PATH

bash 复制代码
vim ~/.bashrc

添加full-system-image的路径,假定gem5目录保存在~下

bash 复制代码
export M5_PATH=~/gem5/full-system-image

这一步可以每次都在终端里手动输入, 如果你确定路径不变的话建议直接写到 .bashrc 中,比较方便

bash 复制代码
source ~/.bashrc

修改路径信息

在gem5根目录下

bash 复制代码
vim configs/common/SysPaths.py

找到 paths=['dist/m5/system', 'n/poolfs/z/dist/m5/system'] 将第二个路径修改为full-system-image目录

python 复制代码
paths=['dist/m5/system', '~/gem5/full-system-image']

开始模拟

配置项设置模拟的kernel镜像地址和磁盘的地址。 下面这段是原始的,但不能用,最近的gem5 已经移除了configs/example/fs.py,需使用下面那段命令。

bash 复制代码
此段错误
build/X86/gem5.opt -d fs-result configs/example/fs.py \
                  --disk=full-system-image/disks/parsec.img \
                  --kernel=full-system-image/kernel/vmlinux-4.4.186
bash 复制代码
此段正确
build/X86/gem5.opt -d fs-result configs/deprecated/example/fs.py \
                  --disk=full-system-image/disks/parsec.img \
                  --kernel=full-system-image/kernel/vmlinux-4.4.186

这里的-d后面是全系统模拟结果的目录,默认是m5out, --disk和--kernel则分别是磁盘和内核的路径

此时开始模拟,终端会输出一些信息,我们新开一个终端然后登录端口等待. gem5 提供了登陆的工具, 我们只需简单的编译使用即可

bash 复制代码
cd utils/term
make
sudo install -o root -m 555 m5term /usr/local/bin

最后一行的命令是将名为 "m5term" 的文件安装到 "/usr/local/bin" 目录中,并将文件的所有者(Owner)设置为 root 用户,权限(Permission)设置为 555, 这样我们就可以在全局使用 m5term 了

bash 复制代码
m5term localhost 3456

除了 m5term 我们也可以使用一般 linux 发行版自带的 telnet, 他们的功能完全相同. 但是使用 telnet localhost 3456 的时候会出现输入重复显示一行的问题, 所以还是使用 m5term 比较好

这里可以在 .bashrc 中设置一下比如 alias m5c='m5term localhost 3456' 方便后续使用

初次启动全系统模拟需要等待很长一段时间(大概30分钟),之后就会进入bash了,这里的交互操作响应是很缓慢的

在启动模拟的过程中可以看到 gem5 端和登陆端都有很多 log 信息, 其中不乏 warnning 和 error, 我们暂时忽略即可并无大碍

保存checkpoint

每次都重新模拟太慢了,我们可以保存checkpoint以便后续快速进入,也可以保存所做的修改

bash 复制代码
m5 checkpoint

退出全系统

bash 复制代码
m5 exit

如果只是退出telnet的话使用 ctrl + d 后输入quit即可.

使用checkpoint进入

依然是上面那个文件问题

bash 复制代码
build/X86/gem5.opt -d fs-result configs/example/fs.py \
                  --disk=full-system-image/disks/parsec.img \
                  --kernel=full-system-image/kernel/vmlinux-4.4.186 \
                  --checkpoint-dir=fs-result \
                  -r 1
bash 复制代码
build/X86/gem5.opt -d fs-result configs/deprecated/example/fs.py \
                  --disk=full-system-image/disks/parsec.img \
                  --kernel=full-system-image/kernel/vmlinux-4.4.186 \
                  --checkpoint-dir=fs-result \
                  -r 1

这里的--checkpoint-dir为checkpoint保存的路径, -r参数用于指定哪个checkpoint,1即为第一个checkpoint,当指定的目录中有多个checkpoint时,多个checkpoint的排序是按照系统创建checkpoint的ticks进行排序的

也就是说, 如果依次使用 m5 checkpoint 保存了三次, 那么想要使用最后一次的进入模拟应该使用 -r 3

进入系统后执行

如果您使用默认配置进入全系统模拟之后打算执行一些测试程序, 我们并不需要一直坐在电脑前等待直到进入进入命令行交互, gem5提供了 --script 参数用于指定进入后执行的 shell 脚本, 您可以编写一个shell脚本完成你的测试, 然后只需要在启动模拟的命令行中加入该参数并指定所用脚本即可, 如下所示

bash 复制代码
build/X86/gem5.opt -d fs-result configs/example/fs.py \
                  --disk=full-system-image/disks/parsec.img \
                  --kernel=full-system-image/kernel/vmlinux-4.4.186 \
                  --script=configs/boot/hack_back_ckpt.rcS

修改磁盘镜像

在fs中操作是很慢的, 所以通常需要在磁盘中配置环境或者预先编译一些代码.这里可以使用挂载的方式修改磁盘文件

我们这里使用之前下载的 full-system-image/disks/parsec.img 磁盘镜像

bash 复制代码
cd full-system-image/disks
# 在disks目录下创建一个挂载镜像文件的目录
mkdir local_mnt
sudo mount -o loop,offset=$((2048*512)) parsec.img local_mnt
sudo mount -o bind /proc local_mnt/proc
sudo mount -o bind /dev local_mnt/dev
sudo mount -o bind /dev/pts local_mnt/dev/pts
sudo mount -o bind /sys local_mnt/sys

# 进入磁盘映像
cd local_mnt
sudo chroot ./

这里简单解释一下挂载, 挂载是将一个文件系统连接到另一个文件系统上的过程,使得被连接的文件系统能够通过目录结构来访问。在Linux系统中,挂载是通过VFS(虚拟文件系统)层实现的。VFS是一个抽象层,它将不同的文件系统类型封装在一起,使得它们可以被以相同的方式来访问。

当我们执行挂载命令时,操作系统会为文件系统映像文件分配一个设备号,并将该文件系统与一个目录进行关联,使得该目录成为文件系统的根目录。此时,我们可以通过该目录来访问文件系统中的文件和目录。实际上,VFS会将目录和文件名翻译成文件系统特定的I/O操作,并将其发送到相应的文件系统驱动程序中。

-o loop 指使用循环设备(loop device)来挂载文件系统,这允许将文件作为块设备处理。offset=$((2048*512)) 指设置文件系统映像文件的偏移量(offset),这样操作系统就能够在正确的位置找到文件系统。在这个命令中,偏移量被设置为2048*512,这意味着文件系统从文件的第2048个块开始,并且每个块的大小为512字节

挂载完成之后我们就可以进入 local_mnt 中对磁盘进行操作了,比如这里我们在 /home 下创建一个文件

bash 复制代码
echo "hello world" > /home/test.txt

修改结束后取消挂载即可

bash 复制代码
cd ..
sudo umount local_mnt/proc
sudo umount local_mnt/dev/pts
sudo umount local_mnt/dev
sudo umount local_mnt/sys
sudo umount local_mnt

如果卸载时出现 umount: /mnt: target is busy. 之类的报错, 说明卸载磁盘正在使用,导致无法直接卸载。需要将当前使用数据盘的进程杀掉,才能卸载. 通常来说是你的 bash进程 没有退出这个 local_mnt 文件夹

bash 复制代码
# 查看正在使用磁盘的进程
fuser -mv local_mnt
# 杀死正在使用磁盘的进程
fuser -kv local_mnt

此时parsec.img就已经被修改了,我们再次启动全系统模拟就可以看到磁盘上的修改了

其他注意事项

首先需要明确的是 gem5 fs模拟需要两部分核心内容: kernel 和 disk, checkpoint 仅作一次当前模拟器中计算机运行状态的保存, 如果您在保存 checkpoint 之后修改了 kernel 或者 disk 那么再次使用这个 checkpoint 进入会存在很大的问题, 需要重新启动模拟

这里进入全系统时我们使用的是默认的 CPU 类型(AtomicSimpleCPU), 后续如果您尝试使用不同类型的 CPU, DRAM 等等您可能发现直接使用诸如X86TimingSimpleCPU启动fs慢的离谱(这是真的,我大概用了6个小时 ), 这是因为 fs 启动会走一遍 linux 启动的流程, 检查各项配置, 您的 CPU 模型或者其他因素可能会大大影响启动进入模拟的时间. 但通常来说我们并不关心如何启动, 而是关心启动之后运行时的效果. 这时候有一个比较聪明的做法是先使用默认的模式启动, 例如

bash 复制代码
build/X86/gem5.opt -d fs-result configs/example/fs.py \
--disk=full-system-image/disks/parsec.img \
--kernel=full-system-image/kernel/vmlinux-5.4.49-cxl \
--mem-size=1GB

进入系统后保存 checkpoint 后退出, 接着在使用 checkpoint 恢复的时候修改参数 , 例如这里使用了 --cpu-type=X86TimingSimpleCPU --restore-with-cpu=X86TimingSimpleCPU 以 X86TimingSimpleCPU 的模式启动 CPU, 并修改 DRAM 类型为 NVM_2400_1x64

bash 复制代码
build/X86/gem5.opt -d fs-result configs/example/fs.py \
--disk=full-system-image/disks/parsec.img --kernel=full-system-image/kernel/vmlinux-5.4.49-cxl \
--checkpoint-dir=fs-result \
-r 1 \
--mem-type=NVM_2400_1x64 \
--cpu-type=X86TimingSimpleCPU --restore-with-cpu=X86TimingSimpleCPU \
--mem-size=1GB

您可以使用下面的选项查看所有 fs 提供的选项

bash 复制代码
./build/X86/gem5.opt configs/example/fs.py --help

注意有一些因素(例如mem-size)影响了 checkpoint 的内容, 所以您不能在使用 checkpoint 恢复时修改 mem-size, 此选项需要和启动时相同

相关参数

  • -n NUM_CPUS: CPU的数量,默认为1
  • --sys-voltage SYS_VOLTAGE: 系统电压,默认为1V
  • --sys-clock SYS_CLOCK: 系统时钟频率,默认为2GHz
  • --list-mem-types: 列出可用的内存类型
  • --mem-type: 内存类型,默认为DDR3_1600_8x8
  • --mem-channels MEM_CHANNELS: 内存通道数,默认为2
  • --mem-ranks MEM_RANKS: 内存等级数,默认为2
  • --mem-size MEM_SIZE: 内存容量,默认为2GB
  • --enable-dram-powerdown: 是否启用DRAM休眠
  • --mem-channels-intlv MEM_CHANNELS_INTLV: 内存通道间隔,默认为256
  • --memchecker: 是否启用内存检查器
  • --external-memory-system EXTERNAL_MEMORY_SYSTEM: 使用外部内存系统
  • --tlm-memory TLM_MEMORY: 使用TLM内存模型
  • --caches: 是否启用缓存
  • --l2cache: 是否启用L2缓存
  • --num-dirs NUM_DIRS: 目录数,默认为1
  • --num-l2caches NUM_L2CACHES: L2缓存数量,默认为1
  • --num-l3caches NUM_L3CACHES: L3缓存数量,默认为0
  • --l1d_size L1D_SIZE: L1数据缓存大小,默认为64kB
  • --l1i_size L1I_SIZE: L1指令缓存大小,默认为64kB
  • --l2_size L2_SIZE: L2缓存大小,默认为2MB
  • --l3_size L3_SIZE: L3缓存大小,默认为16MB
  • --l1d_assoc L1D_ASSOC: L1数据缓存关联度,默认为2
  • --l1i_assoc L1I_ASSOC: L1指令缓存关联度,默认为2
  • --l2_assoc L2_ASSOC: L2缓存关联度,默认为8
  • --l3_assoc L3_ASSOC: L3缓存关联度,默认为16
  • --cacheline_size CACHELINE_SIZE: 缓存行大小,默认为64字节
  • --ruby: 是否使用Ruby内存子系统
  • -m TICKS: 执行的总时钟数,默认为0
  • --rel-max-tick TICKS: 相对最大时钟数,默认为0
  • --maxtime MAXTIME: 执行的最长时间,默认为0
  • -P PARAM: gem5参数文件
  • --list-cpu-types: 列出可用的CPU类型
  • --cpu-type: CPU类型,默认为TimingSimpleCPU
  • --list-bp-types: 列出可用的分支预测类型
  • --list-indirect-bp-types: 列出可用的间接分支预测类型
  • --ruby:启用Ruby内存层次结构模拟器。
  • -m/--num-cpus:模拟的CPU数量。
  • --rel-max-tick/--maxtick:当达到相对或绝对最大时钟周期时停止仿真。
  • --maxtime:以毫秒为单位的仿真最大时长。
  • -P/--param:设置指定组件的参数。例如,"-P system.cpu_cluster.l1.strg_size = 32768"将L1数据缓存的大小设置为32KB。
  • --list-cpu-types:列出可用的CPU类型。
  • --cpu-type:选择要使用的CPU类型。
  • --list-bp-types:列出可用的分支预测器类型。
  • --list-indirect-bp-types:列出可用的间接分支预测器类型。
  • --bp-type/--indirect-bp-type:选择要使用的分支预测器类型/间接分支预测器类型。
  • --list-rp-types:列出可用的重定向策略类型。
  • --list-hwp-types:列出可用的硬件预取类型。
  • --l1i-hwp-type/--l1d-hwp-type/--l2-hwp-type:选择要使用的L1指令/数据缓存或L2缓存的硬件预取类型。
  • --checker:启用组件之间的一致性检查器。
  • --cpu-clock:CPU时钟频率,以GHz为单位。
  • --smt:启用超线程。
  • --elastic-trace-en:启用弹性跟踪。此标志用于记录与其他仿真节点通信的指令流。
  • --inst-trace-file/--data-trace-file:指定指令/数据跟踪文件名。
  • --dist/--dist-sync-on-pseudo-op/--is-switch/--dist-rank/--dist-size/--dist-server-name/--dist-server-port/- --dist-sync-repeat/--dist-sync-start:这些标志用于在分布式仿真环境中使用,其中多个仿真进程在不同的计算机上运行。
相关推荐
Jamence30 分钟前
【深度学习数学知识】-贝叶斯公式
人工智能·深度学习·概率论
feifeikon33 分钟前
机器学习DAY4续:梯度提升与 XGBoost (完)
人工智能·深度学习·机器学习
凡人的AI工具箱40 分钟前
每天40分玩转Django:实操多语言博客
人工智能·后端·python·django·sqlite
Jackilina_Stone43 分钟前
【自动驾驶】3 激光雷达③
人工智能·自动驾驶
HUIBUR科技1 小时前
从虚拟到现实:AI与AR/VR技术如何改变体验经济?
人工智能·ar·vr
QQ_7781329741 小时前
基于云计算的资源管理系统
人工智能·云计算
伊一大数据&人工智能学习日志1 小时前
OpenCV计算机视觉 01 图像与视频的读取操作&颜色通道
人工智能·opencv·计算机视觉
soulteary1 小时前
使用 AI 辅助开发一个开源 IP 信息查询工具:一
人工智能·tcp/ip·开源·ip 查询
爱补鱼的猫猫1 小时前
2、Bert论文笔记
论文阅读·人工智能·bert
起名字什么的好难2 小时前
conda虚拟环境安装pytorch gpu版
人工智能·pytorch·conda