每周分享第 24 期

在线波形绘制 https://wavedrom.com/editor.html Python 波形绘制 https://github.com/wallento/wavedrompy GDB 8.3 发布 http://www.phoronix.com/scan.php?page=news_item&px=GDB-8.3-Debugger-Released 命令行自动搜索 StackOverflow https://github.com/WindSoilder/hors 从 C 到 Rust 的翻译 https://github.com/immunant/c2rust SHA-1 碰撞攻击新进展 https://www.zdnet.com/article/sha-1-collision-attacks-are-now-actually-practical-and-a-looming-danger/ macOS 配置 AD 管理员组 https://derflounder.wordpress.com/2011/02/17/adding-groups-from-your-directory-service-to-your-macs-admin-group/ ssh 后自动安装并打开 code-server 同步配置 https://github.com/cdr/sshcode HTTP Sunset 头 https://tools.ietf.org/html/rfc8594

Read More

在 FPGA 上实现路由器(2)

前言 月初的时候,有了一个完整可用的路由器(上一篇系列博文),但当时测了一下速度,只有几十 Mb/s ,只要往上提就会失效,得 reset 才能继续。当时也先没管性能的事情,先把和 OS 交互的部分做了。现在又回头来做性能调优。 之前,逻辑部分的主频只有 10 MHz ,这自然不行,不提高肯定做不到千兆。于是试着把主频拉高, FIFO 加大,然后遇到了很多问题,慢慢修复了,学到了很多新知识,目前也接近千兆的水平了吧,贴图: TCP 测速: UDP 测速: 测试环境是 macOS 虚拟机外打虚拟机内,走网桥把虚拟机和一个 USB 网卡接起来,然后从另一个 USB 网卡打到路由器。 尝试 700Mb/s 接下来讲讲,在这个过程中遇到了什么问题,怎么解决的。第一个是速度过快就会挂,这肯定是丢包逻辑没写对,后来在仿真里开够了时间,于是就找到了一个 BUG ,其实就是一行的修复。接着就是提高主频,但大家也知道,CPU不能随便超频,由于各种延迟的原因,比如 Setup 时间,如果超了一个时钟周期的时间,本来应该下个周期就得到新数据的,结果到了下下周期才有,那有的状态可能就乱了,我目前遇到的也主要就是这个问题。 于是就对着 Timing 里汇报的各种问题修啊修,发现了很多以前没有注意到的问题,它们不影响功能,但是会让逻辑变慢。第一个问题是 High Fanout ,以上就是说一个输出接到了很多输入,这看起来没啥问题,但数设课上也讲过,每个门的输入输出电流是有限制的,例如按书上的数据,一个门输出只能带十个门,更多只能级联一层。级联的话,延迟自然就高了。后来发现,这里的原因是,开了一个大的数组,但是没有变成 RAM ,综合出了几千个逻辑单元,自然是出问题。解决方法很简单,用 xpm_memory_tpdram 即可。这样一搞,主频就能上 200MHz 了。 这个时候测了一下,发现 UDP 能打到 700Mb/s 了,TCP 由于丢包率比较高,只有 400Mb/s ,距离预期还有一段距离。于是继续进行优化。 向 900Mb/s 进发 要继续提速,自然要提高主频。下一个主频目标就是 250MHz 。随着提高主频,时序的要求也会更高,自然也出现了新的问题。 这次的问题主要在于,一个路径上逻辑门数过多,多的有7到10个,每一步零点几到一点几纳秒,叠起来4纳秒哪里够用。于是把一些不需要依赖条件的逻辑挪到条件外面,这样就减少了一些路径的依赖。 解决了这个以后,现在的 WNS (Worst Negative Slack)只剩下 0.6 ns 了。这时候的问题一部分还是来自于逻辑门过多,但这个时候就没这么简单了,只能继续细化流水线,打一拍,这样才能把延迟降下来。 虽然 Timing 没有完全解决,但还是写进了 FPGA 中。幸好工作一切正常,就得到了上面那个图片的结果,接近千兆的速度了。

Read More

每周分享第 23 期

VS Code Remote https://code.visualstudio.com/blogs/2019/05/02/remote-development Rust 命令行看图片 https://github.com/atanunq/viu GCC 9.1 发布 https://readhacker.news/s/42Ruk Rust 的 Unikernel https://github.com/hermitcore/libhermit-rs Rust 的 QRCode 库 https://www.reddit.com/r/rust/comments/bk7z2x/announcing_bardecoder_a_qr_detector_and_decoder/ 鲁迅说过搜索引擎 http://cx.luxunmuseum.com.cn/ JIT 的 golang REPL https://github.com/gijit/gi Github 私有 Package Repo https://github.com/features/package-registry

Read More

给 Rocket Chip 挂接串口外设

前沿 最近在给 rCore 添加 Rocket Chip 支持。下面讲讲最近做了哪些工作,遇到了哪些坑,都是怎么解决的。 踩坑过程 Rocket Chip 运行代码 首先分析了一下已有的代码和工作方式,这个 Rocket Chip (ucb-bar/fpga-zynq)的设计大概是这样的:在 PS 上通过 fesvr 向 Rocket Chip 写入程序。Rocket Chip 本身暴露出一个 TSI ,一个串口的调试接口,通过 Zynq Adapter 挂到了 PS 下的 AXI 总线,暴露出若干个寄存器,大概如下: /** * Address Map * 0x00 - serial out FIFO data * 0x04 - serial out FIFO data available (words) * 0x08 - serial in FIFO data * 0x0C - serial in FIFO space available (words) * 0x10 - system reset * 0x20 - req FIFO data * 0x24 - req FIFO data available (words) * 0x28 - data FIFO data * 0x2C - data FIFO data available (words) * 0x30 - resp FIFO data * 0x34 - resp FIFO space available (words) * 0x38 - nsectors * 0x3C - max request length */ 前面的是调试接口,后面的是 block device 和 network ,我们暂时还没有用到这些 UCB BAR 做的私货。在 Vivado 中,地址 Offset 是 0x43C00000 ,所以代码中就这样访问对应的物理地址:

Read More

每周分享第 22 期

AXI-Stream Components https://github.com/alexforencich/verilog-axis go self update 库 https://github.com/rhysd/go-github-selfupdate Atomic Pi https://www.cnx-software.com/2019/04/26/buy-atomic-pi-cherry-trail-sbc/ 静态网站生成器 Hugo https://github.com/gohugoio/hugo C++ enum 的反射 https://github.com/Neargye/magic_enum 又一个开源的反编译器 https://github.com/BoomerangDecompiler/boomerang

Read More

在 Linux 中用 C 代码获取 DNS 服务器列表

最近在做一个作业的时候,发现里面有个步骤是获取 Linux 系统中的 DNS 服务器列表,它的方法很粗暴,直接 cat grep cut 再处理。我就在想有没有完全代码的实现,然后搜了一下,果然有: #include <resolv.h> // ... res_init(); // _res.nsaddr_list is an array of resolvers 用到了全局变量 _res ,虽然很 hacky ,但是至少是工作的,不清楚兼容性几何。

Read More

每周分享第 21 期

来了来了 Rust stackful generator 库 https://github.com/Xudong-Huang/generator-rs wireshark tui https://termshark.io/ Pythonm 加 annotation 的调试 https://github.com/cool-RR/PySnooper Haskell 又一个教程 https://github.com/alpacaaa/zero-bullshit-haskell 直接在 Rust 中写 Python https://docs.rs/inline-python/0.2.0/inline_python/ 直接把 regex 捕捉到的 group 丢到 struct 里 https://crates.io/crates/recap XDP 层的抓包 https://github.com/cloudflare/xdpcap AWS 开始提供香港的云服务 https://www.allthingsdistributed.com/2019/04/aws-region-asia-pacific-hong-kong.html

Read More

在 FPGA 上实现路由器

最近在做 FPGA 上硬件的路由器,感觉接近一个基本可用的阶段了吧,大概谈一谈做这个的思路、过程和踩过的坑。 首先,做实验用的板子是 Alinx AX7021 ,FPGA 是 Xilinx xc7z020clg484-2 ,扩展板上有 4PL+1PS 个网口和千兆 KSZ9031RNX PHY ,采用的接口是 RGMII 。一开始做的自然是做 RGMII ,但是遇到了困难,RGMII在千兆模式下传输的是 DDR 信号,而时序和延迟就是个比较麻烦的事情。一开始先直接拿 Xilinx 的 AXI Ethernet IP 来用,然后上 ILA 看到了 IDDR 后的信号,第一次看到了完整的以太网帧,从 Preamble 和 SFD 到最后的 FCS 。于是就特别振奋,想着手写 RGMII ,先做收,再做发。确实,收很容易,很快就做出来了,但是写总是出问题,当时也不懂跨时钟域的一些问题,总之各种没调出来。于是就退而求其次,选择了 Xilinx 的 Tri Mode Ethernet IP 了。 Tri Mode Ethernet IP 有很多选项,为了简单,直接采用了 AXI-Stream 的接口,不要 AXI4-Lite 什么的,都不要,因为我需要直接写剩余的逻辑。其他东西能省也都省掉了。这个 IP 确实很给力,很快就可以完成收和发的操作了,这次终于知道了怎么处理跨时钟域的问题 — XPM FIFO ASYNC ,一下推进了很大的进度。 既然可以收,也可以发了,就扩展到多个网口。这个 IP 中可以选择 Shared Logic 在内部,也可以在外部,研究了一下发现,应该是一个放内部,其余选外部,然后接起来就可以了。不过目前为了简单,还是只用了俩端口。在这个基础上,就开始解析收进来的以太网帧了。 第一步自然是填 ARP 表,自然问题来了,如果多个网口同时进来数据,怎么保证 ARP 表读写的正确性?自然就想到总线上需要做仲裁,于是写了一个简单的总线仲裁,顺带学习到了 unique case(z) 和 priority case(z) 的语法。然后 ARP 表怎么实现呢,大概就是一个哈希表,然后表里维护了(IP,MAC,PORT)三元组,然后实现了一些冲突和覆盖的处理逻辑,做这些的同时也对各个模块编写相应的测试。有了 ARP 表,就可以在解析以太网帧的时候,拆解出里面的信息,然后请求 ARP 表总线,然后写入。

Read More

jiegec.xyz 域名即将停用

最早买域名的时候,买的是 jiegec.xyz ,后来发现了更好的域名,于是这个老域名一直就是一个简单的网页转址。很快,它就要过期了,我也不打算续费了,大家继续用我的新域名吧。 P.S. 忽然发现我之前配的 acme.sh 没有配自动 nginx -s reload ,所以之前 ssl 证书时间凉了。

Read More