RISC-V MCU中文社区

【分享】 【分享】E203添加浮点数方法:寄存器设计

发表于 开源蜂鸟E203 2023-05-06 15:25:46
6
3902
6

报名编号:CICC2969

团队名称:火锅队

学校名称:广东工业大学

1. E203的整数通用寄存器

新手设计一个浮点数寄存器,可以参考整数通用寄存器的设计方法。先从上帝视角看下E203的通用寄存器如何和其他模块连接的。

从上图看到,整数通用寄存器 regfile 主要和三个模块相连接:指令抓取单元IFU, 派遣单元disp,写回仲裁模块 WB Arb。IFU 在预译码时将源操作数寄存器的索引值传给 regfile 模块。disp 模块从 regfile 获得源操作数后,会把源操作数传给后面的电路模块。WB Arb 模块将需要写入数据的寄存器索引号和写回的数据传给 regfile。

接下来的问题就是:

(1)整数通用寄存器需要多少个寄存器?

(2)寄存器的位宽多少?

(3)regfile 如何知道 IFU 要他读出数据?

(4)读数据和写数据会同时出现吗?

对于问题(1)和问题(2):根据 RISC-V 指令,整数通用寄存器拥有 32 个寄存器,即 XLEN = 32。指令有 32 位指令和 64 位指令,E203 只能实现 32 位指令,因此 regfile 是 32 个 32 位寄存器。

对于问题(3):我们可以看下 regfile 的输入信号都有些什么。下图是 regfile 的对外端口:


左边是输入端口,右边是输出端口,其中标蓝的是与 IFU相连的端口,标 黄的是与 disp相连的端口。可以看到,regfile 并没有通信协议,一旦 IFU 给到 regfile 地址,regfile 就会输出相应的源操作数。进入 regfile 的代码后,可以看到如果是读寄存器,则源操作数将在地址输入的同一个时钟周期输出,如果是写寄存器,就要在写入信号输入的下一个时钟周期改写寄存器。

对于问题(4):从问题(3)的回答中可以知道,读信号和写信号是不会在同一个周期出现的,因此不需要考虑读写冲突的问题。

2. E203的 CSR 寄存器(控制状态寄存器)

按照笔者的理解,控制状态寄存器 CSR 的作用是让编写程序的人知道当前机器的状态是什么,是否出现了异常或中断,是否开启了某些模块的功能或者关闭了某些功能。程序知道了这些状态后才能知道要执行哪些代码。程序亦可以改写 CSR 使得机器进入某些状态。

按照 RISC-V 的规定,浮点指令的实现需要另外设置一个32位的控制状态寄存器。由于 E203 已经实现了 32 位的整数部分的控制状态寄存器,因此浮点指令的控制状态寄存器可以在 E203 的 CSR 代码中添加。浮点的控制状态寄存器有两部分:

其中 frm 存放舍入模式编号,当指令选择动态舍入模式时,才会选择使用浮点 CSR 中的 frm 中写入的舍入模式,否则使用指令指定的舍入模式。至于舍入模式有哪些,可以chatgpt一下,也可以直接看RISC-V手册。fflags的含义如下图:


对于RV32, 手册规定使用 32 位的 mstatus 寄存器,其中的 [14:13] 位为 FS,用于标记浮点指令的执行状态。当 FS =00b 时,浮点单元关闭,此时输入的任何浮点指令都会被视为非法指令从而产生中断。FS = 01b 和 FS = 10b 需要程序来设置,硬件无法对 FS 写入这两个数。当 FS = 01b 或 10b 时,一旦执行浮点指令,立刻会变成 FS = 11b, 这需要硬件实现。

3. E203的浮点寄存器的实现

3.1 通用寄存器实现

笔者只实现了单精度的浮点指令,因此数据长度都是 32 位的,和整数长度一致。因此考虑将 regfile 直接复制一份改个名字当作浮点数通用寄存器。需要注意的是,由于RISC-V 的规定,整数通用寄存器的第 0 个寄存器 x0 必须是全零,然而浮点通用寄存器没有这个要求。因此在复制 regfile 时要把使得 x0 = 0 的代码给删掉,剩下的可以不用改动。另外,由于浮点指令的乘加融合指令需要第三个源操作数,因此需要增加一段读 rs3 的代码,这部分代码也可以照葫芦画瓢。

至于浮点寄存器 fregfile 如何与其他部分相连接,亦可以照葫芦画瓢,按照第一张图的连接方式进行模块相连:

知道了怎么连接,但还有问题没有解决:

(1)IFU 是怎么知道是要读出 regfile 的数据还是 fregfile 的数据?

(2)WB Arb 是怎么知道是要写 regfile 还是 fregfile ?

(3)disp 是怎么知道要派遣 rs data 还是 frs data?

对于这三个问题,笔者将在下一节《E203添加浮点数方法:译码和派遣模块设计》中讲述。

3.2 浮点 CSR 寄存器设计

参照官方例程的 NICE 协处理器的代码,可以知道,官方在 CSR 模块引出了一条线 nice_xs_off 给到其他模块当中,该标记为用于标记 nice 处理器是否被开启。因此笔者参照该方法也引出了一个端口给其他模块用于标记浮点单元是否被开启。但是浮点 CSR 设计的第一个难点是:frm 和 fflags 有另外的 CSR 寄存器地址,独立于 fcsr 的地址。为了解决这个问题,根据浮点 CSR 的读写指令由普通 CSR 读写指令实现的特点,笔者在 CSR 寄存器中写入读写 fcsr 的 Verilog 代码,逻辑是:当frm 或者 fflags 任意一个需要修改时,都要修改 fcsr;当需要修改 fcsr 时,必须一起修改 frm 和 fflags。其中的代码参考了 E203 原来的 CSR 读写寄存器的代码的格式。

浮点 CSR 设计的第二个难点是:硬件写 fcsr 和 FS 时,数据到底从哪来。根据 E203 的数据冲突处理方法,CSR 指令的执行必须要在 OITF 为空的时候。因此不用考虑浮点指令执行后写 fcsr 或 FS 请求和 CSR 指令写 fcsr     FS 请求同时到来的冲突。为此,笔者决定在 CSR 内部判断 fcsr 或 FS 是否需要被修改。考虑指令是否会被冲刷得问题:由于 E203 是 2 级流水线,因此指令一旦进入 EXU 单元,就算出现中断,也不会被冲刷掉,即被看作执行完毕,因此 fcsr 或 FS 的读写不需要考虑是否会被冲刷掉的问题。基于上面两方面的考虑,笔者决定,硬件写入 FS 的数据来源于译码模块,一旦译码模块指示正在执行的指令为浮点指令,CSR 就判断是否需要修改 FS。硬件写入 fcsr 的数据来源于 FPU,即在浮点运算执行完后即可传入数据给 fcsr。下图是 csr 的输入与输出端口,左边输入右边输出。


以上就是本帖的内容。



喜欢6
用户评论 (6)
  • Hideaki

    2023-06-03 10:16:48 Hideaki 1#

    结云村猫车侠

    大佬,想请教一下,FPU中与外部的握手接口应该如何设计呢?如果是多周期的话

    我也想问,请问解决了吗


  • 结云村猫车侠

    2023-05-25 08:52:18 结云村猫车侠 2#

    大佬,想请教一下,FPU中与外部的握手接口应该如何设计呢?如果是多周期的话

  • 结云村猫车侠

    2023-05-16 14:10:53 结云村猫车侠 3#

    Lalaland

    在RISC-V特权架构手册的Table2.2当中给出了frm,fflags 和 fcsr 的CSR寄存器地址,你可以去看下。

    嗯嗯谢谢,我后来去看了明白了

  • Lalaland

    2023-05-16 13:51:44 Lalaland 4#

    结云村猫车侠

    您好,请问您说的“frm 和 fflags 有另外的 CSR 寄存器地址,独立于 fcsr 的地址

    ”是什么意思呢?我的理解是frm和fflags字段都在fcsr寄存器中,为什么还独立于fcsr的地址呢?

    在RISC-V特权架构手册的Table2.2当中给出了frm,fflags 和 fcsr 的CSR寄存器地址,你可以去看下。

  • 结云村猫车侠

    2023-05-13 12:21:01 结云村猫车侠 5#

    您好,请问您说的“frm 和 fflags 有另外的 CSR 寄存器地址,独立于 fcsr 的地址

    ”是什么意思呢?我的理解是frm和fflags字段都在fcsr寄存器中,为什么还独立于fcsr的地址呢?

  • 木头คิดถึง

    2023-05-06 15:51:43 木头คิดถึง 6#

    老铁666

Lalaland

Lalaland 实名认证

懒的都不写签名

积分
问答
粉丝
关注
  • RV-STAR 开发板
  • RISC-V处理器设计系列课程
  • 培养RISC-V大学土壤 共建RISC-V教育生态
RV-STAR 开发板