• Rocket


    https://mp.weixin.qq.com/s/TSwKL_qm-b-0e8x7r--hhg

     
    简单介绍Atomics中数学运算、逻辑运算的实现。
     
     
    1. io
     
    Atomics是一个硬件模块,他继承自Modules:
     
    IO端口定义如下:
    其中:
    a. write: 是否写操作;
    b. a:输入操作类型及一个操作数;
    c. data_in:输入另一个操作数;
    d. data_out:输出计算结果;
     
    2. Arithmetic params
     
    处理channel a传入的params:
     
    Channel A上的ArithmeticData消息的params定义如下:
    对应代码,可以看到params各比特的意义:
    a. io.a.params(2):如果这一位为1,则表明运算为加法运算;
    b. io.a.params(1):如果这一位为1,则表明为无符号运算;
    c. io.a.params(0):如果这一位为1,则表明为取最大值运算;如果为0,则为取最小值运算;
     
    3. Arithmetic
     
    数学运算逻辑的实现如下:
     
    1) signBit
     
    io.a.mask中的每一位对应着io.a.data中的一个字节。mask中为0的位对应的字节无效,不参与运算。mask中为1的位对应的字节才可以参与运算。那么io.a.data的符号,则由io.a.mask中最高的值为1的位对应的字节决定。
     
    signBit的意义即为取出mask中最高的一个为1的位。只有mask中最高的值为1的位对应的比特值为1,其余比特的值都为0。这样可以作为掩码选出io.a.data中决定符号的字节。
     
    这个左移一位相与的实现,有一个隐含条件:mask中值为1的比特要连续。
     
    这一点由规范中对io.a.mask的要求来满足:
     
    2) inv_d
     
    如果是加法,则直接使用原值即可。如果是减法,则需要取反加一。
     
    3) sum
     
    相加:
    a. 把io.a.mask中的每一位扩展为8位:FillInterleaved(8, io.a.mask)
    b. 使用扩展之后的掩码去掩io.a.data,把无效的字节掩掉:FillInterleaved(8, io.a.mask) & io.a.data
    c. 与inv_d相加: + inv_d
     
    根据inv_d的取值,决定结果是和还是差:io.a.data - io.data_in = io.a.data + ~io.data_in + 1。
    所以如果sum是差值,那么还需要加1才是真正的差值。
     
    4) sign
     
    计算输入参数的符号:
    a. 输入参数x是一个UInt;
    b. 取出x中每一个字节的最高位:x.toBools().grouped(8).map(_.last).toList
    c. 把最高位组成一个UInt;
    d. 取出最高有效字节的最高位:& signBit
    e. 以Bool类型输出最高位:.orR()
     
    5) pick_a
     
    如果运算是比较大小的话,是选择第一个参与比较的数字a,还是选择比较对象d:
    如果选择较大的数,而a大于d则选择a;
     
    6) a_bigger
     
    a是不是比d大:
     
    a. 如果a和d的符号不同,则取决于a_bigger_uneq的值,这个下面介绍。
     
    b. 如果a和d的符号相同,则取决于两者之差的符号,即取决于sum的符号,及sign_s的值。
     
    这里的一个小trick是sum并不是真正的差值,而是差值减了1的值。即:
     
    sign_s是sum的符号,sign_s == 0等价于sum >= 0:
    a - d >= 1的情况下,a一定大于d,不包括a == d的情况。
     
    这里利用了a == d的情况下,取a或者d都是一样的,来规避求差值需要减1的逻辑消耗。
     
    7) a_bigger_uneq
     
    这个名字中的uneq意思就是a和d的符号不同:
    A. 如果unsigned == 1:
    a. 如果sign_a == 1,那么sign_d == 0,a更大,a_bigger_uneq == 1;
    b. 如果sign_a == 0,那么sign_d == 0,a更小,a_bigger_uneq == 0;
     
    B. 如果unsigned == 0:
    a. 如果sign_a == 1为负数,那么sign_d == 0为正数,a更小,a_bigger_uneq == 0;
    b. 如果sign_a == 0为正数,那么sign_d == 0为负数,a更大,a_bigger_uneq == 1;
     
    可以看到a_bigger_uneq可以很好的表示两个数值的大小。
     
    4. Logical
     
    Logical的计算比较简单,把第一个参数和第二个参数相应的位组合在一起,总共有四种情况,组成序号0/1/2/3,根据这个序号去查表即可得到逻辑运算的结果:
     
    5. 运算结果输出
     
    可能输出的有四个值:0=d, 1=a, 2=sum, 3=logical
     
    根据每一种操作(io.a.opcode决定)所需要值确定一个序号,然后再使用这个序号从序列中取值即可:
    这里根据io.a.mask,逐个字节取值。无效字节使用io.data_in中的值。
  • 相关阅读:
    ajax提交转码解码
    关于idea开发工具常用的快捷键
    oracle 查询某个时间段数据
    hibernate : object references an unsaved transient instance 问题
    log4j日志
    JS关键字 import
    代码正常,junit却报错原因及解决方法
    hdu 5868 Polya计数
    hdu 5893 (树链剖分+合并)
    hdu 5895 广义Fibonacci数列
  • 原文地址:https://www.cnblogs.com/wjcdx/p/11211457.html
Copyright © 2020-2023  润新知