目的:它是 xilinx 公司发布的一个协同仿真环境示例,用来验证 CHI 协议 cache coherency 的实现。
组件:整个环境的组件包括两大部分,QEMU 和 systemc model 。主要的仓库有 libsystemctlm-soc , systemctlm-cosim-demo, qemu.
QEMU 本身就是一款模拟器,可以跨平台模拟不同架构的 cpu 和 Machine。在这里用来运行 linux 内核来模拟真实 CPU 的行为, xilinx 对 QEMU 进行进行了改造。 QEMU 模拟器本身并不支持 cache 而是直接访问内存,xilinx 对其进行了改造,增加了内存控制器仿真的功能,使其更像物理 CPU,将对 memory 的直接访问变成了对内存控制器设备的访问。之后在内存控制器中将访存行为转化成 和 systemc 的接口,由 systemc 来通过总线事务来完成并将结果返回给 QEMU, 这里的接口是 xilinx 自定义的 remote port。
在 systemc-cosim 中,它就是个 glue ,实际的工作都是使用 libsystemctlm 中的组件进行组装,一方面和 QEMU 通信连接,一方面模拟访存行为事务。在这里我们主要验证 CHI 协议的实现,在 libsystemctlm 中的 remote-port-tlm-memory-master 和 remote-port-tlm-memory-slave 完成事务转换, 他们每个都是单方向传输数据,合起来完成双工。
System Clock Demo
+--------------------+
| SystemC-TLM |
+--------+ | |
| | Remote Port | Memory Mapped Regs |
| QEMU |<--------------->+-------+------------+
| | | CLK | 0X4000000 |
+--------+ +-------+------------+
| ... | ... |
+-------+------------+
使用文档: systemctlm-cosim-demo/docs/zynq-7000-getting-started-guide.md
环境分为几个部分:QEMU 模拟器,模拟器内运行的软件(xilinx 内核,dtb,initrd), systemc model 和基本的交叉编译环境.
host 环境: x86_64 ubuntu 20.04
交叉编译工具链工具地址, 下载编译器和 sysroot 环境,编译器中除了编译工具它也自带了sysroot 环境,可以尝试使用 gcc 中的sysroot。
sysroot 环境提供头文件,静态链接库,动态链接库,在这里主要是编译busybox, 所以只需要头文件和静态库就 OK 了。
https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/
gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
sysroot-glibc-linaro-2.25-2019.12-aarch64-linux-gnu.tar.xz
在这里只使用 arm64 的核,其他平台的 qemu 暂时不需要。
$ https://github.com/Xilinx/qemu.git
$ git checkout
$ mkdir build; cd build
$ ../configure --target-list="aarch64-softmmu" --enable-fdt --disable-kvm --disable-xen
$ make -j
$ ls qemu-system-aarch64
$ git clone https://github.com/Xilinx/systemctlm-cosim-demo.git
$ cd systemctlm-cosim-demo
$ git submodule update --init libsystemctlm-soc
# Create the Makefile configeration
cat << EOF | tee .config.mk
CXXFLAGS=-std=c++11
SYSTEMC=/path/to/systemc/
HAVE_VERILOG=n
HAVE_VERILOG_VERILATOR=y
HAVE_VERILOG_VCS=y
VM_TRACE=1
EOF
# Build the demo
make zynq_demo -j
$ git clone https://github.com/buildroot/buildroot.git
$ cd buildroot
$ git checkout 36edacce9c2c3b90f9bb11
从 xilinx 下载其他 Zynq-7000 的配置文件,主要是内核配置和 dts .
# Pull the .dtsi files for the Zynq-7000
wget https://raw.githubusercontent.com/Xilinx/qemu-devicetrees/master/zynq-pl-remoteport.dtsi
wget https://raw.githubusercontent.com/Xilinx/linux-xlnx/master/arch/arm/boot/dts/zynq-7000.dtsi
# kernel 5.4.75 zynq-zc702.dts
wget https://raw.githubusercontent.com/torvalds/linux/6e97ed6efa701db070da0054b055c085895aba86/arch/arm/boot/dts/zynq-zc702.dts
# Include zynq-pl-remoteport.dtsi in zynq-zc702.dts
echo "#include \"zynq-pl-remoteport.dtsi\"" >> zynq-zc702.dts
# Fetch xilinx_zynq_defconfig
wget https://raw.githubusercontent.com/Xilinx/linux-xlnx/3fbb3a6c57a43342a7daec3bbae2f595c50bc969/arch/arm/configs/xilinx_zynq_defconfig
# Setup the Buildroot compilation configeration
rm .config .config.old -f
cat << EOF | tee ".config"
BR2_arm=y
BR2_cortex_a9=y
BR2_ARM_ENABLE_NEON=y
BR2_ARM_ENABLE_VFP=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_BOOTLIN=y
BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_ARMV7_EABIHF_GLIBC_STABLE=y
BR2_TARGET_GENERIC_GETTY_PORT="ttyPS0"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="5.4.75"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="xilinx_zynq_defconfig"
BR2_LINUX_KERNEL_UIMAGE=y
BR2_LINUX_KERNEL_UIMAGE_LOADADDR="0x8000"
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_CUSTOM_DTS_PATH="zynq-7000.dtsi zynq-zc702.dts zynq-pl-remoteport.dtsi"
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_GZIP=y
BR2_TARGET_ROOTFS_EXT2=y
#BR2_TARGET_ROOTFS_TAR is not set
EOF
# Build
make clean && make olddefconfig
./utils/brmake
在遇到错误时,请查看 br.log , 根据提示修复错误。时间会比较长,请耐心等待
问题如下:
make[3]: Entering directory 'output/build/host-m4-1.4.17/lib'
/usr/bin/gcc -I. -I/var/lib/trimui-toolchain//usr/include -O2 -I/var/lib/trimui-toolchain//usr/include -c -o glthread/lock.o glthread/lock.c
/usr/bin/gcc -I. -I/var/lib/trimui-toolchain//usr/include -O2 -I/var/lib/trimui-toolchain//usr/include -c -o freadahead.o freadahead.c
freadahead.c: In function 'freadahead':
freadahead.c:91:3: error: #error "Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
#error "Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
^~~~~
make[3]: *** [Makefile:1842: freadahead.o] Error 1
make[3]: Leaving directory 'output/build/host-m4-1.4.17/lib'
make[2]: *** [Makefile:1602: all] Error 2
make[2]: Leaving directory 'output/build/host-m4-1.4.17/lib'
make[1]: *** [Makefile:1506: all-recursive] Error 1
make[1]: Leaving directory 'output/build/host-m4-1.4.17'
make: *** [Makefile:1461: all] Error 2
[解法如下](link: https://steward-fu.github.io/website/handheld/trimui/fix_m4.htm):
$ cd output/build/host-m4-1.4.17
$ sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' lib/*.c
$ echo "#define _IO_IN_BACKUP 0x100" >> lib/stdio-impl.h
$ make
2022-11-30T02:11:10 libfakeroot.c: In function ‘statx’:
2022-11-30T02:11:10 libfakeroot.c:102:50: error: ‘_STAT_VER’ undeclared (first use in this function)
2022-11-30T02:11:10 102 | #define INT_NEXT_FSTATAT(a,b,c,d) NEXT_FSTATAT64(_STAT_VER,a,b,c,d)
2022-11-30T02:11:10 |
解法如下:
$ vim output/build/host-fakeroot-1.25.3/libfakeroot.c
//添加宏定义
#define _STAT_VER 0
具体现场当时直接略过了
$ vi output/build/host-m4-1.4.18/lib/c-stack.c
删除 #indef SIGSTKSZ的宏定义,直接用宏定义,大部分内核不会修改这个这个值
# define SIGSTKSZ 16384
在 package 中列出了它所需的各种包,在 name.mk 中写了当时的链接,可能会因为各种原因链接访问不了,直接在网上找到对应的包下载对应的版本
,放到 dl 目录下。buildroot 中的脚本会仔细比对压缩包的后缀名,请保持和 name.mk 一致。
# 通信的 unix socket 文件位置
$ mkdir /home/linux/tools
# 启动 qemu 在 terminal 1
$ ./qemu-system-aarch64 -M arm-generic-fdt-7series -m 1G -kernel buildroot/output/images/uImage -dtb buildroot/output/images/zynq-zc702.dtb --initrd buildroot/output/images/rootfs.cpio.gz -serial /dev/null -serial mon:stdio -display none -net nic -net nic -net user -machine-path /home/linux/tools -icount 0,sleep=off -rtc clock=vm -sync-quantum 1000000 -monitor telnet:127.0.0.1:3333,server,nowait
# 启动 systemc model 在 terminal 2
$ ./zynq_demo unix:/home/linux/tools/qemu-rport-_cosim@0 1000000
--------------------------------------------------分割线,以下是 buildroot 单独的版本--------------------------------------------------
1. 下载 busybox, 解压
2. 配置 busybox 编译选项
$ wget https://busybox.net/downloads/busybox-1.34.1.tar.bz2
$ tar xf busybox.tar.xz
$ make menuconfig
build static library //在小的嵌入式环境中,initrd运行时还没有其他运行环境,需要静态链接
set cross compile //设置 linarao gcc 的地址
set sysroot //设置sysroot环境到 linaro gcc
dtb 文件本身可以使用 dtc 工具编译,不过直接编译无法识别 include 语法,所以放在 内核环境下编译。
$ git clone https://github.com/Xilinx/linux-xlnx.git
$ cd linux-xlnx; git checkout origin/zynq/dt -b dt
$ cd arch/arm64/boot/dts/xilinx
$ wget https://raw.githubusercontent.com/Xilinx/qemu-devicetrees/master/zynq-pl-remoteport.dtsi
$ wget https://raw.githubusercontent.com/Xilinx/linux-xlnx/master/arch/arm/boot/dts/zynq-7000.dtsi
# kernel 5.4.75 zynq-zc702.dts
$ wget https://raw.githubusercontent.com/torvalds/linux/6e97ed6efa701db070da0054b055c085895aba86/arch/arm/boot/dts/zynq-zc702.dts
# Include zynq-pl-remoteport.dtsi in zynq-zc702.dts
$ echo "#include \"zynq-pl-remoteport.dtsi\"" >> zynq-zc702.dts
$ cd arch/arm64/configs/
# Fetch xilinx_zynq_defconfig
$ wget https://raw.githubusercontent.com/Xilinx/linux-xlnx/3fbb3a6c57a43342a7daec3bbae2f595c50bc969/arch/arm/configs/xilinx_zynq_defconfig
$ make ARCH=arm64 CROSS_COMPILE=linaro/gcc/path xilinx_zynq_defconfig
$ make ARCH=arm64 CROSS_COMPILE=linaro/gcc/path Image.gz -j
$ make ARCH=arm64 xilinx/zynq-zc702.dtb