RISCV_FPU_RV32D类型指令集

根据有符号,无符号,需要前处理,不需要前处理,后处理,等分类

指令类型指令示例符号性前处理需求后处理需求特殊说明
乘加指令fmadd.dfmsub.d,
fnmsub.dfnmadd.d
有符号✔️✔️融合乘加操作,需处理舍入
基础算术指令fadd.dfsub.d,
fmul.dfdiv.dfsqrt.d
有符号✔️✔️需处理NaN/无穷
符号注入指令fsgnj.dfsgnjn.d,
fsgnjx.d
有符号直接操作符号位
比较指令feq.dflt.dfle.d有符号✔️需处理NaN比较规则
极值指令fmin.dfmax.d有符号✔️需处理NaN和符号
类型转换指令fcvt.s.dfcvt.d.s,
fcvt.w.dfcvt.wu.d,
fcvt.d.wfcvt.d.wu
混合✔️✔️整数/浮点互转需舍入
分类指令fclass.d有符号✔️生成浮点属性掩码
数据移动指令fmv.d.xfmv.x.d无符号直接位传输

一共26条双精度的指令,最近在添加浮点功能,特意了解学习了一下

1.浮点乘加指令

指令:fmadd.dfmsub.dfnmadd.dfnmsub.d

  • 功能:执行融合乘加操作 (a × b) ± c,支持取反。

  • 操作步骤:

    1. 输入检查:检测操作数是否为NaN或无穷,若任一操作数为NaN,结果直接为NaN。

    2. 乘法:计算 a × b,处理中间结果的符号和指数。

    3. 加法:将乘积与 c 相加,处理对齐指数(规格化)。

    4. 取反:根据指令类型(fnmadd/fnmsub)对结果符号取反。

    5. 舍入:根据FRM模式舍入结果,更新fflags(溢出、精度损失等)。

  • 规格化需求:是(乘法和加法阶段均需对齐指数)。

  • 关键代码:

    // 伪代码示例:fmadd.d
    wire [63:0] product = fp_multiply(a, b);
    wire [63:0] sum = fp_add(product, c);
    wire [63:0] result = (opcode == FNMSUB) ? -sum : sum;
    result = fp_round(result, frm); // 舍入处理
  • 异常标志:无效操作(NaN输入)、溢出、下溢、精度损失。

2.基础算数指令

指令:fadd.dfsub.dfmul.dfdiv.dfsqrt.d

  • 功能:双精度浮点加减乘除及平方根。

  • 操作步骤:

    1. 输入规格化:将非规格化数(Denormal)转换为规格化形式。

    2. 符号处理:

      • fsub.d 转换为 a + (-b)

      • fsqrt.d 输入为负数时返回NaN(除非输入为-0)。

    3. 运算核心:

      • 加减法:对齐指数,尾数加减,规格化结果。

      • 乘除法:计算尾数乘积/商,调整指数。

      • 平方根:迭代算法(如牛顿-拉夫逊法)或查找表。

    4. 舍入与规格化:对结果舍入并规格化为IEEE 754格式。

  • 规格化需求:是(输入和输出均需规格化)。

  • 关键代码:

    wire [63:0] a_norm = normalize(a); wire [63:0] b_norm = normalize(b); wire [63:0] sum = fp_add_core(a_norm, b_norm); sum = fp_round(sum, frm);

  • 异常标志:无效操作(如sqrt(-x))、除零、溢出、下溢。

3. 符号注入指令

指令:fsgnj.dfsgnjn.dfsgnjx.d

  • 功能:直接操作浮点数的符号位,不改变数值。

  • 操作步骤:

    1. 符号位提取:从源操作数获取符号位。

    2. 符号计算:

      • fsgnj.d:用b的符号替换a的符号。

      • fsgnjn.d:用~b的符号替换a的符号。

      • fsgnjx.d:符号位为a.sign ^ b.sign

    3. 拼接结果:将新符号与a的指数和尾数拼接。

  • 规格化需求:否(符号位直接操作,无需调整数值)。

  • 关键代码:

    verilog

    复制

    // 伪代码示例:fsgnjx.d
    wire new_sign = a[63] ^ b[63];
    assign result = {new_sign, a[62:0]};
  • 异常标志:无(除非输入为NaN,但符号位仍可操作)。

4. 浮点比较指令

指令:feq.dflt.dfle.d

  • 功能:比较两个双精度数,结果写入整数寄存器。

  • 操作步骤:

    1. NaN处理:

      • 任一操作数为NaN时,feq.d返回0,flt.d/fle.d返回0并标记无效操作。

    2. 数值比较:

      • feq.da == b

      • flt.da < b(考虑符号)。

      • fle.da ≤ b

    3. 结果写回:比较结果(0或1)写入整数寄存器。

  • 规格化需求:是(需规格化后比较)。

  • 关键代码:

    wire is_nan = fp_is_nan(a) || fp_is_nan(b); assign result = is_nan ? 0 : (a == b); fflags.invalid = is_nan; // 标记无效操作

  • 异常标志:无效操作(若比较NaN)。

5. 极值指令

指令:fmin.dfmax.d

  • 功能:返回两个浮点数的最小值或最大值(按数值,非信号)。

  • 操作步骤:

    1. NaN处理:若任一操作数为NaN,返回非NaN数;若均为NaN,返回NaN。

    2. 符号与数值比较:

      • 负数小于正数。

      • fmin.d选择更小的数值(考虑符号)。

    3. 返回结果:选择后的值直接输出,无需舍入。

  • 规格化需求:是(需规格化后比较)。

  • 关键代码:

     if (a is NaN) result = b; else if (b is NaN) result = a; else result = (a < b) ? a : b;

  • 异常标志:无效操作(若输入为NaN)

6. 类型转换指令

指令fcvt.s.dfcvt.d.sfcvt.w.dfcvt.wu.dfcvt.d.wfcvt.d.wu

  • 功能:单/双精度浮点与整数(有/无符号)相互转换。

  • 操作步骤:

    1. 整数转浮点:

      • 符号扩展(有符号整数)或零扩展(无符号整数)。

      • 规格化整数为浮点格式。

    2. 浮点转整数:

      • 处理溢出(超出整数范围时返回最大/最小值)。

      • 根据舍入模式(FRM)截断或舍入。

    3. 单双精度互转:

      • 扩展或截断尾数,调整指数偏置。

  • 规格化需求:是(转换过程需规格化)。

  • 关键代码:

    integer_t int_val; if (fp_val >= 2^31-1) int_val = 0x7FFFFFFF; else if (fp_val <= -2^31) int_val = 0x80000000; else int_val = (fp_val >= 0) ? floor(fp_val) : ceil(fp_val);

  • 异常标志:无效操作(NaN输入)、溢出(超出整数范围)。

7. 分类指令

指令fclass.d

  • 功能:生成描述浮点数值类别的10位掩码。

  • 操作步骤:

    1. 位检查:分析符号位、指数、尾数。

    2. 生成掩码:

      • 每位对应一种类别(如负无穷、负规格化数、正零等)。

  • 规格化需求:否(直接检查位模式)。

  • 关键代码:

    verilog

    复制

    // 伪代码示例:fclass.d
    wire is_neg_inf = (exp == 0x7FF) && (sign == 1) && (frac == 0);
    wire is_pos_zero = (exp == 0) && (sign == 0) && (frac == 0);
    assign mask = {is_snan, is_qnan, is_neg_inf, ..., is_pos_zero};
  • 异常标志:无。

8.load与store指令

  fld(Load Double)指令

功能:

将内存中的 64位双精度浮点数 加载到目标浮点寄存器 f[rd] 中。

指令格式:

复制

fld rd, offset(rs1)
  • rs1:基址寄存器(整数寄存器),存储内存地址。

  • offset:12位有符号立即数偏移量(字节寻址)。

  • rd:目标浮点寄存器(需为偶数编号,因占用两个单精度寄存器空间)。

操作步骤:
  1. 地址计算:

    • 计算有效地址:effective_addr = reg[rs1] + sign_extend(offset)

    • 检查地址是否 对齐到8字节(若未对齐,触发 地址不对齐异常 misaligned exception)。

  2. 内存读取:

    • 从 effective_addr 读取 64位数据(大端或小端由系统决定)。

    • 若内存访问越界或权限不足,触发 Load Page Fault 异常。

  3. 数据写入寄存器:

    • 将读取的64位数据直接写入浮点寄存器 f[rd](无需格式转换)。

    • 若实现为单精度寄存器组(如RV32),需占用 f[rd] 和 f[rd+1] 两个连续寄存器。

  4. 异常处理:

    • 地址不对齐:若 effective_addr % 8 != 0,触发异常。

    • 缺页异常:访问无效内存地址时触发。

  5. 寄存器编号对齐:在RV32中,rd 必须为偶数(如 f0f2),因为双精度数占用两个寄存器。原子性要求:64位加载在RV32中可能需要两次32位内存访问,需确保原子性(避免中间状态被中断)。

 fsd(Store Double)指令

功能

将浮点寄存器 f[rs2] 中的 64位双精度浮点数 存储到内存中。

指令格式

复制

fsd rs2, offset(rs1)
  • rs1:基址寄存器(整数寄存器),存储内存地址。

  • offset:12位有符号立即数偏移量(字节寻址)。

  • rs2:源浮点寄存器(需为偶数编号)。

操作步骤
  1. 地址计算

    • 计算有效地址:effective_addr = reg[rs1] + sign_extend(offset)

    • 检查地址是否 对齐到8字节(若未对齐,触发 地址不对齐异常)。

  2. 寄存器数据读取

    • 从浮点寄存器 f[rs2] 读取64位数据(RV32中需组合 f[rs2] 和 f[rs2+1])。

  3. 内存写入

    • 将64位数据写入 effective_addr 指向的内存位置。

    • 若内存访问越界或权限不足,触发 Store Page Fault 异常。

  4. 异常处理

    • 地址不对齐:若 effective_addr % 8 != 0,触发异常。

    • 缺页异常:访问无效内存地址时触发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值