// ************************************************************************** //
//                                                                            //
//    eses                   eses                                             //
//   eses                     eses                                            //
//  eses    eseses  esesese    eses   Embedded Systems Group                  //
//  ese    ese  ese ese         ese                                           //
//  ese    eseseses eseseses    ese   Department of Computer Science          //
//  eses   eses          ese   eses                                           //
//   eses   eseses  eseseses  eses    University of Kaiserslautern            //
//    eses                   eses                                             //
//                                                                            //
// ************************************************************************** //


[16]nat x;
[16]nat y;
[17]nat s;

thread RadixBAddCarryLookahead16 {
    bool g0,g1,g2,g3,g4,g5,g6,g7,g8,g9,g10,g11,g12,g13,g14,g15;
    bool p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15;
    nat x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15;
    nat y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15;
    nat s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16;
    x0 = x[0];
    x1 = x[1];
    x2 = x[2];
    x3 = x[3];
    x4 = x[4];
    x5 = x[5];
    x6 = x[6];
    x7 = x[7];
    x8 = x[8];
    x9 = x[9];
    x10 = x[10];
    x11 = x[11];
    x12 = x[12];
    x13 = x[13];
    x14 = x[14];
    x15 = x[15];
    y0 = y[0];
    y1 = y[1];
    y2 = y[2];
    y3 = y[3];
    y4 = y[4];
    y5 = y[5];
    y6 = y[6];
    y7 = y[7];
    y8 = y[8];
    y9 = y[9];
    y10 = y[10];
    y11 = y[11];
    y12 = y[12];
    y13 = y[13];
    y14 = y[14];
    y15 = y[15];
    // preliminary sum digits
    s0 = x0 + y0;
    s1 = x1 + y1;
    s2 = x2 + y2;
    s3 = x3 + y3;
    s4 = x4 + y4;
    s5 = x5 + y5;
    s6 = x6 + y6;
    s7 = x7 + y7;
    s8 = x8 + y8;
    s9 = x9 + y9;
    s10 = x10 + y10;
    s11 = x11 + y11;
    s12 = x12 + y12;
    s13 = x13 + y13;
    s14 = x14 + y14;
    s15 = x15 + y15;
    // initial generate conditions
    g0 = s0>255;
    g1 = s1>255;
    g2 = s2>255;
    g3 = s3>255;
    g4 = s4>255;
    g5 = s5>255;
    g6 = s6>255;
    g7 = s7>255;
    g8 = s8>255;
    g9 = s9>255;
    g10 = s10>255;
    g11 = s11>255;
    g12 = s12>255;
    g13 = s13>255;
    g14 = s14>255;
    g15 = s15>255;
    // initial propagate conditions
    p0 = s0==255;
    p1 = s1==255;
    p2 = s2==255;
    p3 = s3==255;
    p4 = s4==255;
    p5 = s5==255;
    p6 = s6==255;
    p7 = s7==255;
    p8 = s8==255;
    p9 = s9==255;
    p10 = s10==255;
    p11 = s11==255;
    p12 = s12==255;
    p13 = s13==255;
    p14 = s14==255;
    p15 = s15==255;
    // carry propagation prefix tree
    // up-level 1
    g1 = g0 & p1 | g1;
    p1 = p1 & p0;
    g3 = g2 & p3 | g3;
    p3 = p3 & p2;
    g5 = g4 & p5 | g5;
    p5 = p5 & p4;
    g7 = g6 & p7 | g7;
    p7 = p7 & p6;
    g9 = g8 & p9 | g9;
    p9 = p9 & p8;
    g11 = g10 & p11 | g11;
    p11 = p11 & p10;
    g13 = g12 & p13 | g13;
    p13 = p13 & p12;
    g15 = g14 & p15 | g15;
    p15 = p15 & p14;
    // up-level 2
    g3 = g1 & p3 | g3;
    p3 = p3 & p1;
    g7 = g5 & p7 | g7;
    p7 = p7 & p5;
    g11 = g9 & p11 | g11;
    p11 = p11 & p9;
    g15 = g13 & p15 | g15;
    p15 = p15 & p13;
    // up-level 3
    g7 = g3 & p7 | g7;
    p7 = p7 & p3;
    g15 = g11 & p15 | g15;
    p15 = p15 & p11;
    // up-level 4
    g15 = g7 & p15 | g15;
    p15 = p15 & p7;
    // down-level 6
    // down-level 7
    g11 = g7 & p11 | g11;
    p11 = p11 & p7;
    // down-level 8
    g5 = g3 & p5 | g5;
    p5 = p5 & p3;
    g9 = g7 & p9 | g9;
    p9 = p9 & p7;
    g13 = g11 & p13 | g13;
    p13 = p13 & p11;
    // down-level 9
    g2 = g1 & p2 | g2;
    p2 = p2 & p1;
    g4 = g3 & p4 | g4;
    p4 = p4 & p3;
    g6 = g5 & p6 | g6;
    p6 = p6 & p5;
    g8 = g7 & p8 | g8;
    p8 = p8 & p7;
    g10 = g9 & p10 | g10;
    p10 = p10 & p9;
    g12 = g11 & p12 | g12;
    p12 = p12 & p11;
    g14 = g13 & p14 | g14;
    p14 = p14 & p13;
    // compute final sum digits
    s[0] = s0 % 256;
    s[1] = (s1+(g0?1:0)) % 256;
    s[2] = (s2+(g1?1:0)) % 256;
    s[3] = (s3+(g2?1:0)) % 256;
    s[4] = (s4+(g3?1:0)) % 256;
    s[5] = (s5+(g4?1:0)) % 256;
    s[6] = (s6+(g5?1:0)) % 256;
    s[7] = (s7+(g6?1:0)) % 256;
    s[8] = (s8+(g7?1:0)) % 256;
    s[9] = (s9+(g8?1:0)) % 256;
    s[10] = (s10+(g9?1:0)) % 256;
    s[11] = (s11+(g10?1:0)) % 256;
    s[12] = (s12+(g11?1:0)) % 256;
    s[13] = (s13+(g12?1:0)) % 256;
    s[14] = (s14+(g13?1:0)) % 256;
    s[15] = (s15+(g14?1:0)) % 256;
    s[16] = (g15?1:0);
}