移植系统到 Rocket Chip on VCU128

背景 最近需要在 VCU128 上搭建一个 SOC,然后想到可以把 OpenSBI、U-Boot 和 Linux 移植到这个平台上方便测试,于是又开始折腾这些东西。代码仓库都已经开源: rocket-chip-vcu128 opensbi u-boot linux Rocket Chip on VCU128 第一部分是基于之前 rocket2thinpad 在 Thinpad 上移植 Rocket Chip 的经验,做了一些更新,主要是因为 VCU128 的外设不大一样,同时我也要运行更复杂的程序,主要做了这些事情: 添加了 VCU128 的内存和外设:HBM、SPI、I2C、UART、ETH 打开了更多核心选项:S-mode 和 U-mode 主要踩过的坑: BSCAN 不工作,估计是因为一些参数不对,@jsteward 之前在 zcu 平台上做了一些测试,估计要用类似的办法进行修改;我最后直接去掉了这部分逻辑 这个板子的 PHY RESET 信号要通过 I2C 接口访问 TI 的 Port Expander,所以没法直接连,要通过 gpio 输出来手动 reset SPI Startup Flash 的时序配置,见我之前的博客 Xilinx PCS/PMA IP 也会自己挂一个设备到 MDIO bus上,应该有自己的 PHY 地址,而不要和物理的 PHY 冲突 U-Boot 在 U-Boot 上花了比较多的时间,用它的目的主要是:

Read More

ESXi 常用信息

常用链接 检查 CPU microcode 版本: vsish -e cat /hardware/cpu/cpuList/0 | grep -i -E 'family|model|stepping|microcode|revision' ESXi 从 6.7 到 6.7U1 升级时出现版本问题 ESXi 6.7 OEM 版本下载 ESXi 7.0 OEM 版本下载 ESXi 7.0 标准版下载 NUC 11 ESXi 7.0 网卡支持 $ esxcli software vib install -d $PWD/Net-Community-Driver_1.2.0.0-1vmw.700.1.0.15843807_18028830.zip 离线升级方法 下载 Offline Bundle 文件 上传到 ESXi datastore 中 在 /vmfs/volumes/ 里找到更新文件 查询 profile 列表 esxcli software sources profile list -d <zip> 更新到 profile esxcli software profiel update -p <profile> -d <zip> ref: Upgrade or Update a Host with Image Profiles

Read More

AXI Quad SPI 时序理解

背景 之前一直没搞懂 Vivado 中 xdc 需要怎么编写,遇到一些必须要写 xdc 的时候就很头疼,不知道怎么写才可以得到正确的结果。今天分析了一下 AXI Quad SPI 的时序 xdc,终于理解了其中的含义。 AXI Quad SPI AXI Quad SPI 是一个 SPI 的控制器,它支持 XIP(eXecute In Place)模式,即可以暴露一个只读 AXI Slave 接口,当接受到读请求的时候,就按照标准的 SPI Flash 命令去对应的地址进行读取,然后返回结果。由于不同厂家的 SPI Flash 支持有所不同,所以 IP 上的设置可以看到厂家的选择。 特别地,一个常见的需求是希望访问 Cfg(Configuration) Flash,亦即用来保存 Bitstream 的 Flash。当 FPGA 上电的时候,如果启动模式设置为 SPI Flash,FPGA 就会向 Cfg Flash 读取 Bitstream,Cfg Flash 需要连接到 FPGA 的指定引脚上,当 FPGA 初始化的时候由内部逻辑驱动,初始化完成后又要转交给用户逻辑。转交的方式就是通过 STARTUP 系列的 primitive。 通常,如果要连接外部的 SPI Flash,需要连接几条信号线到顶层,然后通过 xdc 把信号绑定到引脚上,然后引脚连接了一个外部的 SPI Flash。但由于 Cfg Flash 比较特殊,所以信号从 AXI Quad SPI 直接连到 STARTUP 系列的 primitive 上。如果是采用 STARTUPE2 原语的 7 系列的 FPGA,那么只有时钟会通过 STARTUPE2 pritimive 连接到 SPI Flash 上,其他数据信号还是正常通过顶层绑定;如果是采用 STARTUPE3 原语的 UltraScale 系列的 FPGA,那么时钟和数据都通过 STARTUPE3 primitive 连接到 SPI Flash。

Read More

研究 k8s 网络工作原理

背景 用 k8s 也有一段时间了,之前遇到过 iptables 等出现问题,导致 k8s 节点间网络出现问题,于是想研究一下 k8s 的网络工作原理。 Docker 网络 首先研究一下 Docker 网络连接是如何实现的。Docker 首先会创建一个 bridge,名为 bridge0: $ ip a show docker0 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:c4:87:73:bf brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:c4ff:fe87:73bf/64 scope link valid_lft forever preferred_lft forever 默认情况下,每个容器都会有单独的一个 netns,然后创建一对 veth pair,一端留在 global netns,另一端放到容器中。在 global netns 中的 veth 端口会加入到 docker0 中:

Read More

浅谈乱序执行 CPU

背景 最早学习乱序执行 CPU 的时候,是在 Wikipedia 上自学的,后来在计算机系统结构课上又学了一遍,但发现学的和现在实际采用的乱序执行 CPU 又有很大区别,后来又仔细研究了一下,觉得理解更多了,就想总结一下。 经典 Tomasulo 参考 Stanford 教材 经典 Tomasulo,也是 Wikipedia 上描述的 Tomasulo 算法,它的核心是保留站。指令在 Decode 之后,会被分配到一个保留站中。保留站有以下的这些属性: Op:需要执行的操作 Qj,Qk:操作数依赖的指令目前所在的保留站 ID Vj,Qk:操作数的值 Rj,Rk:操作数是否 ready(或者用特殊的 Qj,Qk 值表示是否 ready) Busy:这个保留站被占用 此外还有一个 mapping(Wikipedia 上叫做 RegisterStat),记录了寄存器是否会被某个保留站中的指令写入。 指令分配到保留站的时候,会查询 RegisterStat,得知操作数寄存器是否 ready,如果不 ready,说明有一个先前的指令要写入这个寄存器,那就记录下对应的保留站 ID。当操作数都 ready 了,就可以进入计算单元计算。当一条指令在执行单元中完成的时候,未出现 WAW 时会把结果写入寄存器堆,并且通过 Common Data Bus 进行广播,目前在保留站中的指令如果发现,它所需要的操作数刚好计算出来了,就会把取值保存下来。 这里有一些细节:因为保留站中的指令可能要等待其他指令的完成,为了保证计算单元利用率更高,对于同一个计算类型(比如 ALU),需要有若干个同类的保留站(比如 Add1,Add2,Add3)。在 Wikipedia 的表述中,每个保留站对应了一个计算单元,这样性能比较好,但自然面积也就更大。如果节省面积,也可以减少计算单元的数量,然后每个计算单元从多个保留站中获取计算的指令。 可以思考一下,这种方法的瓶颈在什么地方。首先,每条指令都放在一个保留站中,当保留站满的时候就不能发射新的指令。其次,如果计算单元的吞吐跟不上保留站的填充速度,也会导致阻塞。 这种方法的一个比较麻烦的点在于难以实现精确异常。精确异常的关键在于,异常之前的指令都生效,异常和异常之后的指令不生效,但这种方法无法进行区分。 从寄存器重命名的角度来看,可以认为这种方法属于 Implicit Register Renaming,也就是说,把 Register 重命名为保留站的 ID。 再分析一下寄存器堆需要哪些读写口。有一条规律是,寄存器堆的面积与读写口个数的平方成正比。对于每条发射的指令,都需要从寄存器堆读操作数,所以读口是操作数x指令发射数。当执行单元完成计算的时候,需要写入寄存器堆,所以每个执行单元都对应一个寄存器堆的写口。 硬件实现的时候,为了性能,希望保留站可以做的比较多,这样可以容纳更多的指令。但是,保留站里面至少要保存操作数的值,会比较占用面积,并且时延也比较大。 ROB(ReOrder Buffer) 参考教材 为了实现精确异常,我们需要引入 ROB。在上面的 Tomasulo 算法中,计算单元计算完成的时候,就会把结果写入到寄存器堆中,因此精确异常时难以得到正确的寄存器堆取值。既然我们希望寄存器堆的状态与顺序执行的结果一致,我们需要引入 ROB。

Read More

Locale 影响排序的特殊副作用

背景 最近在答疑的时候,发现同一条命令在不同系统上行为不同,一开始以为是 bash 版本问题,排查后最后发现是 locale 的问题。一个例子如下: $ cat poc.txt | tr '\\n' ' ' 1 + - * / \ a b A B 一 二 测 试 α $ LANG="" sort poc.txt | tr '\\n' ' ' * + - / 1 A B \ a b α 一 二 测 试 $ LANG="zh_CN.UTF-8" sort poc.txt | tr '\\n' ' ' * + - / \ 1 测 二 试 一 a A b B α $ LANG="en_US.

Read More

一次从 RHEL 6 到 CentOS 7 的更新

背景 有一台 RHEL 6 的服务器,各种软件版本太老了,用起来很难受,因此想升级。一开始想升级到 RHEL 7,但是发现必须要从 RedHat 下载 ISO,比较慢,所以我就先切换到 CentOS 6,再升级到 CentOS 7 过程 RHEL 6 Pre upgrade 一开始还是打算升级到 RHEL 7,所以跟随 RedHat 的文档去做 pre upgrade check,发现有一步要跑好久,网上搜了一下,发现这个步骤会扫描已有的各种程序,检查升级以后会不会出现不能运行的问题。但是如果有很多小文件,这一个过程就会进行很久,好在可以设置 exclusion 目录。最后检查出来的结果就是 GNOME 没法升级,建议卸载。 倒腾了一下升级工具,发现需要离线安装,比较麻烦,我就干脆换 CentOS 了。 RHEL 6 -> CentOS 6 首先,把软件源都切换到 CentOS,这一步很简单,因为包都是一样的。只不过,因为 CentOS 6 在 centos-vault 里面,所以用起来比较麻烦。 CentOS 6 -> CentOS 7 由于 CentOS 6 到 CentOS 7 升级涉及的改动比较多,官方提供了一个升级工具。一开始,我想直接升级到 CentOS 7 最新版本,但是报错,看到网上说可以升级到 CentOS 7 的早期版本,试了一下,确实没问题。 一通升级以后,重启,进入更新过程,发现很多包都安装失败了。重启以后,因为找不到 rootfs,挂在了 dracut 的 initramfs 里面。

Read More

轶事一则

7.31 号周六的时候,发现 Intel Intrinsics Guide(https://software.intel.com/sites/landingpage/IntrinsicsGuide/) 出现错误,加载数据失败,于是在 Intel 的网站上提交了一个 bug。 8.2 号的时候,Intel 发邮件过来,说已经复现了问题,已经汇报给了后端团队。邮件原文: Thank you for bringing this to our attention. We have verified and encountered the same issue. Please know that we have escalated this issue to our backend technical team. We will get back to you as soon as we have an update. Have a nice day ahead! 8.4 号的时候,Intel 再次发邮件过来,说后端团队正在处理这个问题,会尽快完成修复,请我耐心等待。这个时候我去网站上看,还是有问题。邮件原文: Our backend team is still working on this issue.

Read More

配置 homebridge-broadlink-rm-pro

背景 最近发现空调遥控器电池有点不足,有时候会自动关机,于是拿出以前买的 Broadlink RM mini 3 充当远程的空调遥控器使用。为了方便手机上配置,分别采用了官方的 App 智慧星和 homebridge 进行配置。 步骤 首先用官方的智慧星配置好 Broadlink RM mini 3 的网络,然后配置 homebridge-broadlink-rm-pro。最早的插件作者不怎么更新了,这个版本是目前用的比较多的一个 fork。 安装好以后,在 Home 里面可以看到 Scan Code 的开关。打开以后,用遥控器在 Broadlink RM mini 3 附近按按键,就可以在 Homebridge 日志里看到 hex code 了。然后,就按照插件教程里的方法写配置,例子如下: { "platform": "BroadlinkRM", "name": "Broadlink RM", "accessories": [ { "name": "Air Conditioner", "type": "air-conditioner", "noHumidity": true, "minTemperature": 26, "maxTemperature": 28, "defaultCoolTemperature": 27, "data": { "off": "2600...", "cool28": { "data": "2600..." }, "cool27": { "data": "2600.

Read More

轶事一则

7.17 号周六的时候,一位朋友 @elenacliu 发现深研院网站的一个文档链接,文档中标题写的是 2021,但是网页的标题显示的是 2006 年。于是我发邮件给深研院的招生办,抄送本部的研招办,提交了这个 issue。 7.19 号周一上午的时候,本部的研招办回复了一封邮件,没有理解我想表达的意思,可能以为我是要报考的学生,让我关注明年发布的文档。 7.19 号周一下午的时候,深研院招生办回复了邮件,说“谢谢你的反馈”,不过没有提到是否进行了修复。我晚上再查看页面的时候,发现新的文档链接已经修复了问题。

Read More