并行进位加法器

news2025/2/24 17:57:53

前言

在文章逻辑运算加法器中,介绍了两种加法运算方式,串行进位加法器进位选择加法器,我们给出了逻辑门的实现并给出了C语言描述,本篇文章介绍另外一种加法计算方法:并行进位加法器

写在前面

  • 使用 ⨁ \bigoplus 表示异或
  • 使用 + + +号表示或
  • AB表示A与B

门延迟

首先介绍一个概念,门延迟
我们知道,集成电路的主要工作单位是晶体管,晶体管虽然状态的改变非常迅速,但是毕竟有延迟,尤其随着晶体管串行数量的增大,延迟不可小觑。我们把一组电路中最大串行逻辑门的延迟门数量之和称为该电路的延迟门。延迟门是衡量电路性能的标志,下面是基本逻辑门的延迟门数量:

  • 与门,非门,或门延迟门设置为1
  • 与非门,或非门延迟门设置为2
  • 异或门延迟门设置为3,因为异或门是使用一个或门,一个与非门进行与门操作实现的。

并行进位加法器

全先行进位加法

我们从前面的文章能知道,串行进位加法器的主要性能瓶颈在于每一项的进位值需要前面的计算结果。对于n位的两个相加的值 X X X Y Y Y,我们再次给出进位值和计算值的公式:
{ F i = ( X i ⨁ Y i ) ⨁ C i − 1 , 计算值 C i = ( X i C i − 1 ) + ( Y i C i − 1 ) + ( X i Y i ) , 进位值 \begin{cases} F_i = (X_i \bigoplus Y_i) \bigoplus C_{i-1},计算值\\ C_i = (X_i C_{i-1}) + (Y_i C_{i-1}) + (X_i Y_i ),进位值 \end{cases} {Fi=(XiYi)Ci1,计算值Ci=(XiCi1)+(YiCi1)+(XiYi),进位值

用电路表示 F i F_i Fi的值为:
在这里插入图片描述

用电路表示 C i C_i Ci的值为,可以看到进位的计算的门延迟是2:
在这里插入图片描述

根据布尔运算
C i = ( X i C i − 1 ) + ( Y i C i − 1 ) + ( X i Y i ) = X i Y i + ( X i + Y i ) C i − 1 C_i =(X_i C_{i-1}) + (Y_i C_{i-1}) + (X_i Y_i ) = X_i Y_i + (X_i+Y_i)C_{i-1} Ci=(XiCi1)+(YiCi1)+(XiYi)=XiYi+(Xi+Yi)Ci1
也就是说:
C 1 = X 1 Y 1 + ( X 1 + Y 1 ) C 0 C_1 = X_1 Y_1 + (X_1+Y_1)C_{0} C1=X1Y1+(X1+Y1)C0
C 2 = X 2 Y 2 + ( X 2 + Y 2 ) C 1 = X 2 Y 2 + ( X 2 + Y 2 ) ( X 1 Y 1 + ( X 1 + Y 1 ) C 0 ) = X 2 Y 2 + ( X 2 + Y 2 ) ( X 1 Y 1 ) + ( X 2 + Y 2 ) ( X 1 + Y 1 ) C 0 \begin{aligned} C_2 &= X_2 Y_2 + (X_2+Y_2)C_{1}\\ &=X_2 Y_2 + (X_2+Y_2)(X_1 Y_1 + (X_1+Y_1)C_{0})\\ &=X_2 Y_2 + (X_2+Y_2)(X_1 Y_1) + (X_2+Y_2)(X_1+Y_1)C_{0} \end{aligned} C2=X2Y2+(X2+Y2)C1=X2Y2+(X2+Y2)(X1Y1+(X1+Y1)C0)=X2Y2+(X2+Y2)(X1Y1)+(X2+Y2)(X1+Y1)C0
C 3 = X 3 Y 3 + ( X 3 + Y 3 ) C 2 = X 3 Y 3 + ( X 3 + Y 3 ) ( X 2 Y 2 + ( X 2 + Y 2 ) ( X 1 Y 1 ) + ( X 2 + Y 2 ) ( X 1 + Y 1 ) C 0 ) = X 3 Y 3 + ( X 3 + Y 3 ) ( X 2 Y 2 ) + ( X 3 + Y 3 ) ( X 2 + Y 2 ) ( X 1 Y 1 ) + ( X 3 + Y 3 ) ( X 2 + Y 2 ) ( X 1 + Y 1 ) C 0 \begin{aligned} C_3 &= X_3 Y_3 + (X_3+Y_3)C_{2}\\ &=X_3 Y_3 + (X_3+Y_3)(X_2 Y_2 + (X_2+Y_2)(X_1 Y_1) + (X_2+Y_2)(X_1+Y_1)C_{0})\\ &=X_3 Y_3 + (X_3+Y_3)(X_2 Y_2) + (X_3+Y_3)(X_2+Y_2)(X_1 Y_1)+(X_3+Y_3)(X_2+Y_2)(X_1+Y_1)C_{0} \end{aligned} C3=X3Y3+(X3+Y3)C2=X3Y3+(X3+Y3)(X2Y2+(X2+Y2)(X1Y1)+(X2+Y2)(X1+Y1)C0)=X3Y3+(X3+Y3)(X2Y2)+(X3+Y3)(X2+Y2)(X1Y1)+(X3+Y3)(X2+Y2)(X1+Y1)C0

我们假设 P i = X i + Y i P_i = X_i+Y_i Pi=Xi+Yi G i = X i Y i G_i = X_iY_i Gi=XiYi,也就是 P i P_i Pi是一个逻辑或门, G i G_i Gi是一个逻辑与门,上面的公式可以写成如下形式:
C 1 = G 1 + P 1 C 0 C_1 = G_1 + P_1C_{0} C1=G1+P1C0
C 2 = G 2 + P 2 G 1 + P 2 P 1 C 0 C_2= G_2 + P_2G_1+ P_2P_1C_{0} C2=G2+P2G1+P2P1C0
C 3 = G 3 + P 3 G 2 + P 3 P 2 G 1 + P 3 P 2 P 1 C 0 C_3= G_3 + P_3G_2+P_3P_2G_1+P_3P_2P_1C_{0} C3=G3+P3G2+P3P2G1+P3P2P1C0
同理:
C 4 = G 4 + P 4 G 3 + P 4 P 3 G 2 + P 4 P 3 P 2 G 1 + P 4 P 3 P 2 P 1 C 0 C_4= G_4 + P_4G_3+P_4P_3G_2+P_4P_3P_2G_1+P_4P_3P_2P_1C_{0} C4=G4+P4G3+P4P3G2+P4P3P2G1+P4P3P2P1C0

即然 C 4 、 C 3 、 C 2 、 C 1 C_4、C_3、C_2、C_1 C4C3C2C1都能使用 C 0 C_0 C0来表示,那么我们就可以通过设计电路来同时计算 C 4 、 C 3 、 C 2 、 C 1 C_4、C_3、C_2、C_1 C4C3C2C1的值,然后根据计算后的值进行每一位的加法运算。设计后电路图如下:
在这里插入图片描述

上面的电路称为先行进位部件,简称CLA(Carry Lookahead Unit)

我们把输入的 X 、 Y X、Y XY和数值位的计算添加进来,然后把 C i C_i Ci的值也添加到加法器,这样便组成了一个全先行进位加法,电路图如下:
在这里插入图片描述

我们看一下上面电路的门延迟:

  1. X i 、 Y i X_i、Y_i XiYi输入后需要计算 G i 、 P i G_i、P_i GiPi,因为可以并行计算,门延迟数为1
  2. G i 、 P i G_i、P_i GiPi C i − 1 C_{i-1} Ci1开始计算 C i C_i Ci,根据CLA的电路图,需要门延迟数为2
  3. 这个时候步骤1与步骤2共需要门延迟为3,巧的是,这两步执行过程过程中,数值位也在并行着,并且 M i = X i ⨁ Y i M_i = X_i \bigoplus Y_i Mi=XiYi异或操作门延迟正好也是3,也就是到现在为止,一共的门延迟为3
  4. 然后开始计算 M i ⨁ C i M_i \bigoplus C_i MiCi异或操作,门延迟为3,加上之前的操作,所有的门延迟一共为6

下面,给出CLA电路的C语言描述:

/**
 * CLA电路的C语言描述,计算4位的加法值
 * in_1:输入X
 * in_2:输入Y
 * c0:默认的进位项
 */
extern long alu_add_cla(long in_1, long in_2, long* c0);

long alu_add_cla(long in_1, long in_2, long* c0)
{
    // 初始结果为0
    long result = 0;
    
    // 下面这四组并行,每一组在电路中需要1级门延迟
    long x1 = alu_bit(in_1, 0); // 获取输入1的第0位
    long y1 = alu_bit(in_2, 0); // 获取输入2的第0位
    long p1 = or_gate(x1, y1);
    long g1 = and_gate(x1, y1);
    
    long x2 = alu_bit(in_1, 1); // 获取输入1的第1位
    long y2 = alu_bit(in_2, 1); // 获取输入2的第1位
    long p2 = or_gate(x2, y2);
    long g2 = and_gate(x2, y2);
    
    long x3 = alu_bit(in_1, 2); // 获取输入1的第2位
    long y3 = alu_bit(in_2, 2); // 获取输入2的第2位
    long p3 = or_gate(x3, y3);
    long g3 = and_gate(x3, y3);
    
    long x4 = alu_bit(in_1, 3); // 获取输入1的第3位
    long y4 = alu_bit(in_2, 3); // 获取输入2的第3位
    long p4 = or_gate(x4, y4);
    long g4 = and_gate(x4, y4);
    
    // CLA电路实现,需要门延迟2
    long c1 = or_gate(g1, and_gate(p1, *c0));
    long c2 = or_gate(or_gate(g2, and_gate(p2, g1)),and_gate(and_gate(p2, p1), *c0));
    long c3 = or_gate(or_gate(or_gate(g3, and_gate(p3, g2)), and_gate(and_gate(p3, p2), g1)), and_gate(and_gate(and_gate(p3, p2), p1), *c0));
    long c4 = or_gate(or_gate(or_gate(or_gate(g4, and_gate(p4, g3)), and_gate(and_gate(p4, p3), g2)), and_gate(and_gate(and_gate(p4, p3), p2), g1)), and_gate(and_gate(and_gate(and_gate(p4, p3), p2), p1), *c0));
    
    // 异或操作,门延迟3,与上面的并行
    long m1 = xor_gate(x1, y1);
    long m2 = xor_gate(x2, y2);
    long m3 = xor_gate(x3, y3);
    long m4 = xor_gate(x4, y4);
    
    // 最后的异或计算,门延迟3
    long r1 = xor_gate(m1, *c0);
    long r2 = xor_gate(m2, c1);
    long r3 = xor_gate(m3, c2);
    long r4 = xor_gate(m4, c3);
    
    result |= r4<<3;
    result |= r3<<2;
    result |= r2<<1;
    result |= r1;
    // 将进位值返回给c0
    *c0 = c4;
    return result;
}

有了四位的全先行进位加法器我们可以实现多位的加法器了,这里还可以分为两种:

  • 单级先行进位加法器
  • 多级先行进位加法器

单级先行进位加法器

首先看第一种:
单级先行进位加法器是将 n n n个全先行进位加法器串起来,可以实现 4 n 4n 4n位的加法运算,我们计算一下对于 4 n 4n 4n位的单级先行进位加法器,门延迟是多少?

  1. 每一个全先行进位加法器需要前面一个CLA的 C C C输出,第一个CLA的输出为 C 4 C_4 C4,我们从前面的介绍很容易计算出从开始到 C 4 C_4 C4输出需要门延迟为3,其中计算 P P P G G G占1,计算 C C C占2,也就是3个门延迟之后,第二个全先行进位加法器可以开始了
  2. 要知道,这时候所有的全先行进位加法器的 P P P G G G都在第1步的时候并发完成了,所以,后面的所有全先行进位加法器的 C C C输出都消耗2个门延迟。
  3. 所以到最后一个全先行进位加法器获取到上一个CLA的 C C C输入时,一共消耗2n-1个门延迟。然后开始计算最后一个全先行进位加法器的数值位,要注意,最后一个全先行进位加法器的数值位计算完成时,前面所有的全先行进位加法器的数值位都应该计算完成了,因为他们都是并行的。
  4. 最后一个数值位的计算和最终输出的进位同时进行,一共消耗3个门延迟,一共消耗2n+2个门延迟

下面这是一个16位的加法器示意图:
在这里插入图片描述

现在我们可以给出64位加法器的C语言描述了,因为有了之前CLA的定义,非常简单:

/**
 * CLA电路的串行加法器
 * in_1:输入X
 * in_2:输入Y
 * bits:计算的位数
 * c0:默认的进位项
 */
extern long alu_add_cla_64(long in_1, long in_2,long bits, long* c0);

long alu_add_cla_64(long in_1, long in_2,long bits, long* c0)
{
    long result = 0;
    for(int i = 0;i<bits;i+=4)
    {
        result |= alu_add_cla(in_1>>i,in_2>>i,c0)<<i;
    }
    return result;
}

int main(int argc, const char * argv[]) 
{
    int c= 0;
    long r0 = alu_add_cla_64(-398, 283, 64, &c);
    printf("r0 = %ld\n",r0);
    long r1 = alu_add_cla_64(398, 283, 64, &c);
    printf("r1 = %ld\n",r1);
}

输出结果为:

r0 = -115
r1 = 681

多级先行进位加法器

最后,我们在研究一下多级先行进位加法器,所谓多级先行进位加法器就是将多个全先行进位加法器并起来,而不是串起来,先看一下16位的两级先行进位加法器,整个逻辑是下面这个样子:

  1. 四个全先行进位加法器分别同时执行四位的与操作和或操作,获取 P P P G G G,这步消耗1个门延迟
  2. 然后通过与门和或门操作获取 P m i P_{mi} Pmi G m i , i G_{mi},i Gmii是指的当前全先行进位加法器的索引, P m P_m Pm G m G_m Gm是这样一种定义(这步消耗2个门延迟)
    P m 1 = P 4 P 3 P 2 P 1 G m 1 = G 4 + P 4 G 3 + P 4 P 3 G 2 + P 4 P 3 P 2 G 1 \begin{aligned} P_{m1}&=P_4P_3P_2P_1\\ G_{m1}&=G_4+P_4G_3+P_4P_3G_2+P_4P_3P_2G_1 \end{aligned} Pm1Gm1=P4P3P2P1=G4+P4G3+P4P3G2+P4P3P2G1
  3. 然后开始计算 C C C的值,因为我们之前知道全先行进位加法器怎么根据输入的 C C C计算四位的输出 C C C。现在的问题就是如何同时获取每个全先行进位加法器的输入 C C C,即获取 C 4 C_4 C4 C 8 C_8 C8 C 12 C_{12} C12 C 16 C_{16} C16,参考之前的实现,我们可以用下面的方式实现,这一步消耗2个门延迟:
    C 4 = G m 1 + P m 1 C 0 C 8 = G m 2 + P m 2 G m 1 + P m 2 P m 1 C 0 C 12 = G m 3 + P m 3 G m 2 + P m 3 P m 2 G m 1 + P m 3 P m 2 P m 1 C 0 C 16 = G m 4 + P m 4 G m 3 + P m 4 P m 3 G m 2 + P m 4 P m 3 P m 2 G m 1 + P m 4 P m 3 P m 2 P m 1 C 0 \begin{aligned} &C_4=G_{m1}+P_{m1}C_0\\ &C_8=G_{m2}+P_{m2}G_{m1}+P_{m2}P_{m1}C_0\\ &C_{12}=G_{m3}+P_{m3}G_{m2}+P_{m3}P_{m2}G_{m1}+P_{m3}P_{m2}P_{m1}C_0\\ &C_{16}=G_{m4}+P_{m4}G_{m3}+P_{m4}P_{m3}G_{m2}+P_{m4}P_{m3}P_{m2}G_{m1}+P_{m4}P_{m3}P_{m2}P_{m1}C_0\\ \end{aligned} C4=Gm1+Pm1C0C8=Gm2+Pm2Gm1+Pm2Pm1C0C12=Gm3+Pm3Gm2+Pm3Pm2Gm1+Pm3Pm2Pm1C0C16=Gm4+Pm4Gm3+Pm4Pm3Gm2+Pm4Pm3Pm2Gm1+Pm4Pm3Pm2Pm1C0
  4. 这一步就跟之前的全先行进位加法器一样了,因为四个输入 C C C都已经获取到了,从这一步到计算全部完成需要2+3个门延迟,2是为了计算全先行进位加法器中的每个 C C C值,3是最后的那步异或操作。

下面给出16位两级先行进位加法器的电路图:
在这里插入图片描述

好了,了解了两级先行进位加法器以后,就可以构建三级的先行进位加法器。三级能够进行64位的加减操作,对于我们目前来说足够了,并且三级的并行操作能使性能达到最优。

三级的先行进位加法器构建如下:

  • 首先有16个4位先行进位加法器
  • 然后16个4位先行进位加法器把 P m i P_{mi} Pmi G m i G_{mi} Gmi传递给4位的BCLA部件,应该有4个BCLA部件,然后,还是根据下面的公式,构建第三层4位的BCLA部件
    P m 1 = P 4 P 3 P 2 P 1 G m 1 = G 4 + P 4 G 3 + P 4 P 3 G 2 + P 4 P 3 P 2 G 1 不过公式应该换成 P m m 1 = P m 4 P m 3 P m 2 P m 1 G m m 1 = G m 4 + P m 4 G m 3 + P m 4 P m 3 G m 2 + P m 4 P m 3 P m 2 G m 1 \begin{aligned} P_{m1}&=P_4P_3P_2P_1\\ G_{m1}&=G_4+P_4G_3+P_4P_3G_2+P_4P_3P_2G_1\\ 不过公式应该换成\\ P_{mm1}&=P_{m4}P_{m3}P_{m2}P_{m1}\\ G_{mm1}&=G_{m4}+P_{m4}G_{m3}+P_{m4}P_{m3}G_{m2}+P_{m4}P_{m3}P_{m2}G_{m1}\\ \end{aligned} Pm1Gm1不过公式应该换成Pmm1Gmm1=P4P3P2P1=G4+P4G3+P4P3G2+P4P3P2G1=Pm4Pm3Pm2Pm1=Gm4+Pm4Gm3+Pm4Pm3Gm2+Pm4Pm3Pm2Gm1
  • 现在相当于先计算第三层的BCLA,根据 P m m i P_{mmi} Pmmi G m m i G_{mmi} Gmmi C 0 C_0 C0能够计算出 C 16 C_{16} C16 C 32 C_{32} C32 C 48 C_{48} C48 C 64 C_{64} C64
  • 根据 P m i P_{mi} Pmi G m i G_{mi} Gmi C 0 C_0 C0能够计算出 C 4 C_4 C4 C 8 C_8 C8 C 12 C_{12} C12
  • 根据 P m i P_{mi} Pmi G m i G_{mi} Gmi C 16 C_{16} C16能够计算出 C 20 C_{20} C20 C 24 C_{24} C24 C 28 C_{28} C28
  • 根据 P m i P_{mi} Pmi G m i G_{mi} Gmi C 32 C_{32} C32能够计算出 C 36 C_{36} C36 C 40 C_{40} C40 C 44 C_{44} C44
  • 根据 P m i P_{mi} Pmi G m i G_{mi} Gmi C 48 C_{48} C48能够计算出 C 52 C_{52} C52 C 56 C_{56} C56 C 60 C_{60} C60
  • 到现在为止,剩下的就使计算具体的每个 C C C值了,应该很熟悉了。

最后,给出三级先行进位加法器的C语言描述,代码比较多,为了展示电路级别的操作,逻辑写的比较复杂,其实实际上很多操作都是并行触发的

/**
 * 三级先行进位加法器
 * in_1:输入X
 * in_2:输入Y
 * bits:计算的位数
 * c0:默认的进位项
 * return:返回计算结果
 */
extern long alu_add_bcla_64(long in_1, long in_2,long bits, long* c0);

long alu_add_bcla_64(long in_1, long in_2,long bits, long* c0)
{
    // 计算p、g,一共64位
    long out_p = alu_or(in_1, in_2,sizeof(long)*8);
    long out_g = alu_and(in_1, in_2,sizeof(long)*8);
    // 第二级p、g,一共16位
    long out_pm=0;
    long out_gm=0;
    // 第三极p、g,一共4位
    long out_pm2=0;
    long out_gm2=0;
    // 计算第二级p、g,应该是并行的
    for(int i=0;i<16;i++)
    {
        long p4 =alu_bit(out_p,i*4+3);
        long p3 =alu_bit(out_p,i*4+2);
        long p2 =alu_bit(out_p,i*4+1);
        long p1 =alu_bit(out_p,i*4+0);
        
        long g4 =alu_bit(out_g,i*4+3);
        long g3 =alu_bit(out_g,i*4+2);
        long g2 =alu_bit(out_g,i*4+1);
        long g1 =alu_bit(out_g,i*4+0);
        out_pm|=((and_gate(and_gate(and_gate(p4, p3), p2), p1))<<i);
        out_gm|=((or_gate(or_gate(or_gate(g4, and_gate(p4, g3)), and_gate(and_gate(p4, p3), g2)), and_gate(and_gate(and_gate(p4, p3), p2), g1)))<<i);
    }
    // 计算第三极p、g,应该是并行的
    for(int i=0;i<4;i++)
    {
        long p4 =alu_bit(out_pm,i*4+3);
        long p3 =alu_bit(out_pm,i*4+2);
        long p2 =alu_bit(out_pm,i*4+1);
        long p1 =alu_bit(out_pm,i*4+0);
        
        long g4 =alu_bit(out_gm,i*4+3);
        long g3 =alu_bit(out_gm,i*4+2);
        long g2 =alu_bit(out_gm,i*4+1);
        long g1 =alu_bit(out_gm,i*4+0);
        out_pm2|=((and_gate(and_gate(and_gate(p4, p3), p2), p1))<<i);
        out_gm2|=((or_gate(or_gate(or_gate(g4, and_gate(p4, g3)), and_gate(and_gate(p4, p3), g2)), and_gate(and_gate(and_gate(p4, p3), p2), g1)))<<i);
    }
    
    // 根据第三极p、g和c0计算c16、c32、c48、c64,应该是并行的
    long p4 =alu_bit(out_pm2,3);
    long p3 =alu_bit(out_pm2,2);
    long p2 =alu_bit(out_pm2,1);
    long p1 =alu_bit(out_pm2,0);
    
    long g4 =alu_bit(out_gm2,3);
    long g3 =alu_bit(out_gm2,2);
    long g2 =alu_bit(out_gm2,1);
    long g1 =alu_bit(out_gm2,0);
    
    long c16 = or_gate(g1, and_gate(p1, *c0));
    long c32 = or_gate(or_gate(g2, and_gate(p2, g1)),and_gate(and_gate(p2, p1), *c0));
    long c48 = or_gate(or_gate(or_gate(g3, and_gate(p3, g2)), and_gate(and_gate(p3, p2), g1)), and_gate(and_gate(and_gate(p3, p2), p1), *c0));
    // c64是最终输出的c0
    long c64 = or_gate(or_gate(or_gate(or_gate(g4, and_gate(p4, g3)), and_gate(and_gate(p4, p3), g2)), and_gate(and_gate(and_gate(p4, p3), p2), g1)), and_gate(and_gate(and_gate(and_gate(p4, p3), p2), p1), *c0));
    
    // 准备计算一级的所有c值,下面这些是二级所有的c值
    long c_2[4]={*c0,c16,c32,c48};
    // 最终输出结果
    long result = 0;
    // 当前计算第几位
    int r = 0;
    for(int i=0;i<4;i++)
    {
        // 根据二级的c值计算一级的c值
        long p4 =alu_bit(out_pm,i*4+3);
        long p3 =alu_bit(out_pm,i*4+2);
        long p2 =alu_bit(out_pm,i*4+1);
        long p1 =alu_bit(out_pm,i*4+0);
        
        long g4 =alu_bit(out_gm,i*4+3);
        long g3 =alu_bit(out_gm,i*4+2);
        long g2 =alu_bit(out_gm,i*4+1);
        long g1 =alu_bit(out_gm,i*4+0);
        
        long c1 = or_gate(g1, and_gate(p1, c_2[i]));
        long c2 = or_gate(or_gate(g2, and_gate(p2, g1)),and_gate(and_gate(p2, p1), c_2[i]));
        long c3 = or_gate(or_gate(or_gate(g3, and_gate(p3, g2)), and_gate(and_gate(p3, p2), g1)), and_gate(and_gate(and_gate(p3, p2), p1), c_2[i]));
        // 这个没啥用,其实可以不用计算,但是其实电路中也没啥影响,毕竟都是并行的,都消耗2个门延迟
        //long c4 = or_gate(or_gate(or_gate(or_gate(g4, and_gate(p4, g3)), and_gate(and_gate(p4, p3), g2)), and_gate(and_gate(and_gate(p4, p3), p2), g1)), and_gate(and_gate(and_gate(and_gate(p4, p3), p2), p1), c_2[i]));
        // 根据1级的c值计算0级所有的c值
        long c_1[4]={c_2[i],c1,c2,c3};
        for(int j=0;j<4;j++)
        {
            long p4 =alu_bit(out_p,i*16+j*4+3);
            long p3 =alu_bit(out_p,i*16+j*4+2);
            long p2 =alu_bit(out_p,i*16+j*4+1);
            long p1 =alu_bit(out_p,i*16+j*4+0);
            
            long g4 =alu_bit(out_g,i*16+j*4+3);
            long g3 =alu_bit(out_g,i*16+j*4+2);
            long g2 =alu_bit(out_g,i*16+j*4+1);
            long g1 =alu_bit(out_g,i*16+j*4+0);
            
            long c1 = or_gate(g1, and_gate(p1, c_1[j]));
            long c2 = or_gate(or_gate(g2, and_gate(p2, g1)),and_gate(and_gate(p2, p1), c_1[j]));
            long c3 = or_gate(or_gate(or_gate(g3, and_gate(p3, g2)), and_gate(and_gate(p3, p2), g1)), and_gate(and_gate(and_gate(p3, p2), p1), c_1[j]));
            //long c4 = or_gate(or_gate(or_gate(or_gate(g4, and_gate(p4, g3)), and_gate(and_gate(p4, p3), g2)), and_gate(and_gate(and_gate(p4, p3), p2), g1)), and_gate(and_gate(and_gate(and_gate(p4, p3), p2), p1), c_1[j]));
            // 将c值写入result,result就相当于一个64位的电路
            result |= c3<<(r+3);
            result |= c2<<(r+2);
            result |= c1<<(r+1);
            result |= c_1[j]<<(r);
            r+=4;
        }
    }
    // 这里保存进位值
    *c0 = c64;
    // 两个异或操作获取位的计算值
    return alu_xor(alu_xor(in_1, in_2,sizeof(long)*8), result,sizeof(long)*8);
}

int main(int argc, const char * argv[]) 
{
    long c= 0;
    long r0 = alu_add_bcla_64(-398, 283, 64, &c);
    printf("r0 = %ld\n",r0);
    long r1 = alu_add_bcla_64(398, 283, 64, &c);
    printf("r1 = %ld\n",r1);
}

结果为:

r0 = -115
r1 = 681

总结

我们从不断优化的方案可以看出时间和空间的权衡方案,性能和速度的提升几乎必然伴随着电路的复杂度提高,需要更多的空间来安排电路的排线,需要更多的空间来放置更多的逻辑门。本篇文章完成时,荷兰的2纳米光刻机已经开始交付给intel。可预见的是,集成电路还会有大幅提升的空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1340864.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

rime中州韵 symbols.custom.yaml 配置

今天我们所做的配置&#xff0c;将实现扩展符号的输入效果&#xff0c;如下&#x1f447;&#xff1a; 基础扩展符号的配置 要实现输入法能够输入扩展的符号&#xff0c;我们需要在输入方案中引入扩展符号集。 如果你使用的输入方案是 wubi_pinyin.schema.yaml&#xff0c;…

计算机中找不到vcruntime140.dll无法启动此程序怎么解决?

无法继续执行代码&#xff0c;因为找不到vcruntime140.dll”。那么&#xff0c;vcruntime140.dll是什么文件&#xff1f;它的作用是什么&#xff1f;当它丢失时会对电脑产生什么影响&#xff1f;本文将为您详细介绍vcruntime140.dll文件的相关知识&#xff0c;并提供五种解决vc…

Rhinos各版本安装指南

下载链接 https://pan.baidu.com/s/1L5qeUPMW32d7zR-GlVVZIw?pwd0531 温馨提示&#xff1a;若您下载的安装包与该安装步骤不同&#xff0c;说明您使用的是之前被淘汰的安装包&#xff0c;请通过该页面的下载链接重新下载。 1.鼠标右击【Rhino8.1(64bit)】压缩包&#xff08…

VuePress、VuePress-theme-hope 搭建个人博客 1【快速上手】 —— 防止踩坑篇

vuePress官网地址 &#x1f449; 首页 | VuePress 手动安装 这一章节会帮助你从头搭建一个简单的 VuePress 文档网站。如果你想在一个现有项目中使用 VuePress 管理文档&#xff0c;从步骤 3 开始。 步骤 1: 创建并进入一个新目录 mkdir vuepress-starter cd vuepress-star…

模型系列:增益模型Uplift Modeling原理和案例

模型系列&#xff1a;增益模型Uplift Modeling原理和案例 目录 1. 简介1. 第一步2. 指标3. 元学习器 3.1 S-学习器3.2 T-学习器3.3 T-学习器相关模型 简介 Uplift是一种用于用户级别的治疗增量效应估计的预测建模技术。每家公司都希望增加自己的利润&#xff0c;而其中一个…

深度解析 | 什么是超融合数据中心网络?

数据中心网络连接数据中心内部通用计算、存储和高性能计算资源&#xff0c;服务器间的所有数据交互都要经由网络转发。当前&#xff0c;IT架构、计算和存储技术都在发生重大变革&#xff0c;驱动数据中心网络从原来的多张网络独立部署向全以太化演进。而传统的以太网无法满足存…

简述Redis备份策略以及对应的实现机制

引言 Redis作为高性能的内存数据库&#xff0c;数据的安全性至关重要。一旦数据丢失&#xff0c;可能会对业务造成重大影响。因此&#xff0c;备份Redis数据是每个Redis使用者都必须考虑的问题。本文将介绍Redis的备份策略以及对应的实现机制。 一、备份策略 1.1 定期备份 …

视频编辑软件,视频添加图片水印软件

你是否曾经为了制作一个简单的视频而头痛不已&#xff1f;是否觉得视频编辑软件的操作复杂&#xff0c;让人望而却步&#xff1f;【视频剪辑高手】将彻底改变这一现状&#xff01;它以简单、高效、创意为核心&#xff0c;为用户提供一站式的视频编辑解决方案。 所需工具&#…

du和df

du 和df 不一致的问题&#xff1a; 情况如下&#xff1a; innode 没有满 同事求助&#xff0c; 他在删掉一个很大的文件后&#xff0c; 磁盘空间依旧没释放。上去一看&#xff0c; 果然 df 看到磁盘空间占用依旧是100%&#xff0c;等等 du 看了一把&#xff0c;磁盘空间剩余很…

什么是MLOps?

人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;应用激动人心的发展浪潮也许会让人相信&#xff0c;企业交付ML产品的能力也在迅速提高。但现实情况是&#xff0c;ML内部流程很难跟上行业的整体发展……但若以MLOps的形式则有希望解决此问题&#xff…

基于遗传算法的航线规划

MATLAB2016b可以正常运行 基于遗传算法的无人机航线规划资源-CSDN文库

【网络安全 | 扫描器】御剑安装及使用教程详析

御剑是一款传统的Web网络安全综合检测程序&#xff0c;支持对PHP、JSP、ASPX等文件进行扫描&#xff0c;具备全扫描、网络安全扫描和主机安全扫描能力&#xff0c;方便发现网站漏洞。 文章目录 下载使用教程 本文对御剑的安装及使用教程进行详析 下载 下载地址读者可自行上网…

ARM CCA机密计算软件架构之RMI领域管理接口与RSI领域服务接口

领域管理接口 领域管理接口&#xff08;RMI&#xff09;是RMM与正常世界主机之间的接口。 RMI允许正常世界虚拟机监视器向RMM发出指令&#xff0c;以管理领域。 RMI使用来自主机虚拟机监视器的SMC调用&#xff0c;请求RMM的管理控制。 RMI使得对领域管理的控制成为可能&…

Python新手上路:“用Python和Pygame创造你的流星雨”

文章目录 一、前言二、下载安装过程1.官网下载安装包2.安装python过程第一步第二步第三步第四步第五步安装完成 3.简单测试Python3.1 检查 Python 版本号3.2 打开 Python 解释器3.3 输入你的第一个代码3.4 运行 Python 脚本 4.安装Pygame4.1 cmd命令安装Pygame4.2 pip升级4.3 安…

所有逐个位置相加的方法

989. 【加法模板】秒杀所有逐位相加 参考教程

python学习14

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

桥接模式-举例

概叙&#xff1a;桥接模式用一种巧妙的方式处理多层继承存在的问题&#xff0c; 用抽象关联取代了传统的多层继承&#xff0c; 将类之间的静态继承关系转换为动态的对象组合关系&#xff0c; 使得系统更加灵活&#xff0c;并易于扩展&#xff0c; 同时有效控制了系统中类的个数…

使用pytorch搭建ResNet并基于迁移学习训练

这里的迁移学习方法是载入预训练权重的方法 net resnet34()# load pretrain weights# download url: https://download.pytorch.org/models/resnet34-333f7ec4.pthmodel_weight_path "./resnet34-pre.pth"assert os.path.exists(model_weight_path), "file {}…

Keras多分类鸢尾花DEMO

完整的一个小demo&#xff1a; pandas1.2.4 numpy1.19.2 python3.9.2 import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas import DataFrame from scipy.io import loadmat from sklearn.model_selection import train_test_split impor…

硅像素传感器文献调研(三)

写在前面&#xff1a; 引言&#xff1a;也是先总结前人的研究结果&#xff0c;重点论述其不足之处。 和该方向联系不大&#xff0c;但还是有值得学习的地方。逻辑很清晰&#xff0c;易读性很好。 1991年—场板半阻层 使用场板和半电阻层的高压平面器件 0.摘要 提出了一种…