Chipyard Docker——坑外有坑 搭好chipyard的环境之后,便开始做一些简单开发,Berkeley提供了用户定制协处理器的接口,方便在Rocketchip上拓展一些自定义的硬件加速模块。

一、RoCC入门资料

整理过一些RoCC(Rocket of Costum)开发的实用资料:

  1. RoCC最大公约数
  2. Design and programming of a coprocessor for a RISC-V architecture

二、RoCC模块

写了一个矩阵向量乘法的加速器,增加了三条核心拓展指令:

  • push : 从内存传入向量至RoCC
  • mvm : 执行矩阵向量乘法(权重矩阵已提前写好)
  • save : 从RoCC传出结果至内存

完成功能测试之后,希望性能,于是在RoCC_mvm指令前后添加时钟数计时,结果发现打印的周期数远远小于估算的周期数,最终计算结果是对的。 image.png

难道gcc -O2 优化改变了指令执行顺序?反汇编查看执行的指令,确实也是这个顺序!为之奈何?——波形时序图。

调出几个关键信号:

  • inst_real: 实际执行的指令
  • RoCC : RoCC内部状态机状态
  • inst_pre:这是自己预想的时序图 图片1.png

发现执行mvm指令之后,RoCC进入mvm状态,但计算还没结束,cpu紧接着执行后面的读时钟和打印指令,最后计算完毕之后,才执行save,保证了计算结果的正确性,但计时不正确。

三、捡到贝壳

之前一致觉得RoCC运算的时候,流水线会停滞,没想到CPU还是可以做其他事情的,那么是否可以在RoCC计算的时候,CPU做一些准备数据的工作呢,这样可以充分利用计算资源,实现完美的时间管理! image.png

四、知其所以

为什么是这样的时序呢?之前做芯来科技E203协处理器的时候,确实和预想的逻辑一样,RocketChip为什么不同呢?看内存一致性模型相关的资料,结合官方手册The RISC-V Instruction Set Manual,找到一些线索。

内存一致性模型是描述多核访存的时候,应该遵守什么样的规则,不同的规则对应不同的模型,不同的模型在性能、编程难度等方面也不同。访存的读写指令在流水线上是多周期完成的,为了避免出错,可以有这样一个模型:读或写完成之后,再写或读下一条指令。这就是SC(Sequential consistency,顺序一致性模型)。按这个模型设计的处理器,编程友好,但性能会差一些。

为了提高性能,需要对读写放宽限制。为了充分释放CPU的计算能力,读比写的优先级会更高,因此可以放宽“写完之后再读”的限制:如果读写地址不同,还没写完毕,就可以执行下一条读指令。这就是TSO(Total Store Order,强顺序模型)。

如果放宽“写完之后再写”的限制,那么会得到PSO模型(partial store ordering)。

如果完全放宽读写限制,那么会的到WMO(weak memory ordering,弱一致性模型),而这里的Rocketchip就是采用RVWMO模型。缺少了这些限制,性能能够提升,但为了保证程序执行的正确性,RISC-V提供了同步指令“fence”。

所以为了保证我的拓展指令功能正确,需要在push和save指令前后添加同步指令:push完毕之后,才能执行计算,计算完毕之后,才能保存数据。这样才可以保证功能的正确性:

图片2.png

以上的模型可以用下表总结: image.png

有关内存一致性模型的内容很复杂,不知让大佬们掉了多少头发,只能简单介绍点皮毛,还很可能理解错~

无意中从计时的错误发现一种提高性能的方法,还是挺神奇的。

标签: riscv, 内存模型

仅有一条评论

  1. 李同学 李同学

    同学你好,我是中科院的学生。和这个方向一致,能加个微信吗?我的:lipewx008

添加新评论