import "primitives/std.lib"; import "primitives/math.futil"; component main() -> () { cells { @external(1) x = std_mem_d2(32, 1, 10, 1, 4); @external(1) x1 = std_mem_d2(32, 1, 10, 1, 4); softmax_1x10_ = softmax_1x10(); } wires { } control { seq { invoke softmax_1x10_(x0_0_read_data=x.read_data, x10_0_done=x1.done, x10_0_read_data=x1.read_data)(x0_0_addr0=x.addr0, x0_0_addr1=x.addr1, x10_0_write_data=x1.write_data, x10_0_write_en=x1.write_en, x10_0_addr0=x1.addr0, x10_0_addr1=x1.addr1); } } } component softmax_1x10(x0_0_read_data: 32, x0_0_done: 1, x10_0_read_data: 32, x10_0_done: 1) -> (x0_0_write_data: 32, x0_0_write_en: 1, x0_0_addr0: 1, x0_0_addr1: 4, x10_0_write_data: 32, x10_0_write_en: 1, x10_0_addr0: 1, x10_0_addr1: 4) { cells { __exp_sum_0 = std_reg(32); __i0 = std_reg(1); __i1 = std_reg(1); __j0 = std_reg(4); __j1 = std_reg(4); __k0 = std_reg(4); __max_0 = std_reg(32); __t0_0 = std_reg(32); __t1_0 = std_reg(32); __t2_0 = std_reg(32); __t3_0 = std_reg(32); add0 = std_add(4); add1 = std_add(1); add2 = std_fp_sadd(32,16,16); add3 = std_add(4); add4 = std_add(4); add5 = std_add(1); bin_read0_0 = std_reg(32); const0 = std_const(1,0); const1 = std_const(4,0); const10 = std_const(4,0); const11 = std_const(4,9); const12 = std_const(4,1); const13 = std_const(4,0); const14 = std_const(4,9); const15 = std_const(4,1); const16 = std_const(1,1); const2 = std_const(1,0); const3 = std_const(1,0); const4 = std_const(4,0); const5 = std_const(4,9); const6 = std_const(4,1); const7 = std_const(1,1); const8 = std_const(1,0); const9 = std_const(1,0); div_pipe0 = std_fp_sdiv_pipe(32,16,16); exp0 = exp(); exp1 = exp(); fp_const0 = std_const(32,0); gt0 = std_fp_sgt(32,16,16); le0 = std_le(1); le1 = std_le(4); le2 = std_le(1); le3 = std_le(4); le4 = std_le(4); sub0 = std_fp_ssub(32,16,16); sub1 = std_fp_ssub(32,16,16); x_read0_0 = std_reg(32); x_read1_0 = std_reg(32); x_read2_0 = std_reg(32); x_read3_0 = std_reg(32); } wires { group cond0<"static"=0> { cond0[done] = 1'd1; le0.left = __i0.out; le0.right = const3.out; } group cond1<"static"=0> { cond1[done] = 1'd1; le1.left = __j0.out; le1.right = const5.out; } group cond2<"static"=0> { cond2[done] = 1'd1; gt0.left = x_read0_0.out; gt0.right = __max_0.out; } group cond3<"static"=0> { cond3[done] = 1'd1; le2.left = __i1.out; le2.right = const9.out; } group cond4<"static"=0> { cond4[done] = 1'd1; le3.left = __j1.out; le3.right = const11.out; } group cond5<"static"=0> { cond5[done] = 1'd1; le4.left = __k0.out; le4.right = const14.out; } group let0<"static"=1> { __i0.in = const2.out; __i0.write_en = 1'd1; let0[done] = __i0.done; } group let1<"static"=1> { __j0.in = const4.out; __j0.write_en = 1'd1; let1[done] = __j0.done; } group let10 { bin_read0_0.in = div_pipe0.out_quotient; bin_read0_0.write_en = div_pipe0.done; let10[done] = bin_read0_0.done; div_pipe0.left = __t3_0.out; div_pipe0.right = __exp_sum_0.out; div_pipe0.go = !div_pipe0.done ? 1'd1; } group let2<"static"=1> { __i1.in = const8.out; __i1.write_en = 1'd1; let2[done] = __i1.done; } group let3<"static"=1> { __exp_sum_0.in = fp_const0.out; __exp_sum_0.write_en = 1'd1; let3[done] = __exp_sum_0.done; } group let4<"static"=1> { __j1.in = const10.out; __j1.write_en = 1'd1; let4[done] = __j1.done; } group let5<"static"=1> { __t0_0.in = sub0.out; __t0_0.write_en = 1'd1; let5[done] = __t0_0.done; sub0.left = x_read2_0.out; sub0.right = __max_0.out; } group let6 { __t1_0.in = exp0.out; __t1_0.write_en = 1'd1; let6[done] = __t1_0.done; } group let7<"static"=1> { __k0.in = const13.out; __k0.write_en = 1'd1; let7[done] = __k0.done; } group let8<"static"=1> { __t2_0.in = sub1.out; __t2_0.write_en = 1'd1; let8[done] = __t2_0.done; sub1.left = x_read3_0.out; sub1.right = __max_0.out; } group let9 { __t3_0.in = exp1.out; __t3_0.write_en = 1'd1; let9[done] = __t3_0.done; } group upd0<"static"=1> { __max_0.write_en = 1'd1; x0_0_addr1 = const1.out; x0_0_addr0 = const0.out; __max_0.in = 1'd1 ? x0_0_read_data; upd0[done] = __max_0.done ? 1'd1; } group upd1<"static"=1> { x_read0_0.write_en = 1'd1; x0_0_addr1 = __j0.out; x0_0_addr0 = __i0.out; x_read0_0.in = 1'd1 ? x0_0_read_data; upd1[done] = x_read0_0.done ? 1'd1; } group upd10<"static"=1> { x10_0_addr1 = __k0.out; x10_0_addr0 = __i1.out; x10_0_write_en = 1'd1; x10_0_write_data = 1'd1 ? bin_read0_0.out; upd10[done] = x10_0_done ? 1'd1; } group upd11<"static"=1> { __k0.write_en = 1'd1; add4.left = __k0.out; add4.right = const15.out; __k0.in = 1'd1 ? add4.out; upd11[done] = __k0.done ? 1'd1; } group upd12<"static"=1> { __i1.write_en = 1'd1; add5.left = __i1.out; add5.right = const16.out; __i1.in = 1'd1 ? add5.out; upd12[done] = __i1.done ? 1'd1; } group upd2<"static"=1> { x_read1_0.write_en = 1'd1; x0_0_addr1 = __j0.out; x0_0_addr0 = __i0.out; x_read1_0.in = 1'd1 ? x0_0_read_data; upd2[done] = x_read1_0.done ? 1'd1; } group upd3<"static"=1> { __max_0.write_en = 1'd1; __max_0.in = 1'd1 ? x_read1_0.out; upd3[done] = __max_0.done ? 1'd1; } group upd4<"static"=1> { __j0.write_en = 1'd1; add0.left = __j0.out; add0.right = const6.out; __j0.in = 1'd1 ? add0.out; upd4[done] = __j0.done ? 1'd1; } group upd5<"static"=1> { __i0.write_en = 1'd1; add1.left = __i0.out; add1.right = const7.out; __i0.in = 1'd1 ? add1.out; upd5[done] = __i0.done ? 1'd1; } group upd6<"static"=1> { x_read2_0.write_en = 1'd1; x0_0_addr1 = __j1.out; x0_0_addr0 = __i1.out; x_read2_0.in = 1'd1 ? x0_0_read_data; upd6[done] = x_read2_0.done ? 1'd1; } group upd7<"static"=1> { __exp_sum_0.write_en = 1'd1; add2.left = __exp_sum_0.out; add2.right = __t1_0.out; __exp_sum_0.in = 1'd1 ? add2.out; upd7[done] = __exp_sum_0.done ? 1'd1; } group upd8<"static"=1> { __j1.write_en = 1'd1; add3.left = __j1.out; add3.right = const12.out; __j1.in = 1'd1 ? add3.out; upd8[done] = __j1.done ? 1'd1; } group upd9<"static"=1> { x_read3_0.write_en = 1'd1; x0_0_addr1 = __k0.out; x0_0_addr0 = __i1.out; x_read3_0.in = 1'd1 ? x0_0_read_data; upd9[done] = x_read3_0.done ? 1'd1; } } control { seq { upd0; let0; @bound(1) while le0.out with cond0 { seq { let1; @bound(10) while le1.out with cond1 { seq { upd1; if gt0.out with cond2 { seq { upd2; upd3; } } upd4; } } upd5; } } let2; @bound(1) while le2.out with cond3 { seq { par { let3; seq { let4; @bound(10) while le3.out with cond4 { seq { upd6; let5; invoke exp0(x=__t0_0.out)(); let6; upd7; upd8; } } } } let7; @bound(10) while le4.out with cond5 { seq { upd9; let8; invoke exp1(x=__t2_0.out)(); let9; let10; upd10; upd11; } } upd12; } } } } } component exp(x: 32) -> (out: 32) { cells { exponent_value = std_reg(32); int_x = std_reg(32); frac_x = std_reg(32); m = std_reg(32); and0 = std_and(32); and1 = std_and(32); rsh = std_rsh(32); lt = std_slt(32); c2 = std_const(32, 2); c3 = std_const(32, 3); c4 = std_const(32, 4); c5 = std_const(32, 5); c6 = std_const(32, 6); c7 = std_const(32, 7); c8 = std_const(32, 8); one = std_const(32, 65536); e = std_const(32, 178145); negative_one = std_const(32, 4294901760); product2 = std_reg(32); product3 = std_reg(32); product4 = std_reg(32); product5 = std_reg(32); product6 = std_reg(32); product7 = std_reg(32); product8 = std_reg(32); p2 = std_reg(32); p3 = std_reg(32); p4 = std_reg(32); p5 = std_reg(32); p6 = std_reg(32); p7 = std_reg(32); p8 = std_reg(32); sum1 = std_reg(32); sum2 = std_reg(32); sum3 = std_reg(32); sum4 = std_reg(32); add1 = std_fp_sadd(32, 16, 16); add2 = std_fp_sadd(32, 16, 16); add3 = std_fp_sadd(32, 16, 16); add4 = std_fp_sadd(32, 16, 16); mult_pipe1 = std_fp_smult_pipe(32, 16, 16); mult_pipe2 = std_fp_smult_pipe(32, 16, 16); mult_pipe3 = std_fp_smult_pipe(32, 16, 16); mult_pipe4 = std_fp_smult_pipe(32, 16, 16); mult_pipe5 = std_fp_smult_pipe(32, 16, 16); mult_pipe6 = std_fp_smult_pipe(32, 16, 16); mult_pipe7 = std_fp_smult_pipe(32, 16, 16); mult_pipe8 = std_fp_smult_pipe(32, 16, 16); div_pipe = std_fp_sdiv_pipe(32, 16, 16); reciprocal_factorial2 = std_const(32, 32768); reciprocal_factorial3 = std_const(32, 10923); reciprocal_factorial4 = std_const(32, 2731); reciprocal_factorial5 = std_const(32, 546); reciprocal_factorial6 = std_const(32, 91); reciprocal_factorial7 = std_const(32, 13); reciprocal_factorial8 = std_const(32, 2); pow1 = fp_pow(); pow2 = fp_pow(); pow3 = fp_pow(); pow4 = fp_pow(); pow5 = fp_pow(); pow6 = fp_pow(); pow7 = fp_pow(); pow8 = fp_pow(); } wires { group init<"static"=1> { exponent_value.write_en = 1'd1; exponent_value.in = x; init[done] = exponent_value.done; } group split_bits { and0.left = exponent_value.out; and0.right = 32'd4294901760; rsh.left = and0.out; rsh.right = 32'd16; and1.left = exponent_value.out; and1.right = 32'd65535; int_x.write_en = 1'd1; frac_x.write_en = 1'd1; int_x.in = rsh.out; frac_x.in = and1.out; split_bits[done] = int_x.done & frac_x.done ? 1'd1; } group negate { mult_pipe1.left = exponent_value.out; mult_pipe1.right = negative_one.out; mult_pipe1.go = !mult_pipe1.done ? 1'd1; exponent_value.write_en = mult_pipe1.done; exponent_value.in = mult_pipe1.out; negate[done] = exponent_value.done; } group is_negative<"static"=0> { lt.left = x; lt.right = 32'd0; is_negative[done] = 1'd1; } group reciprocal { div_pipe.left = one.out; div_pipe.right = m.out; div_pipe.go = !div_pipe.done ? 1'd1; m.write_en = div_pipe.done; m.in = div_pipe.out_quotient; reciprocal[done] = m.done; } group consume_pow2<"static"=1> { p2.write_en = 1'd1; p2.in = pow2.out; consume_pow2[done] = p2.done ? 1'd1; } group consume_pow3<"static"=1> { p3.write_en = 1'd1; p3.in = pow3.out; consume_pow3[done] = p3.done ? 1'd1; } group consume_pow4<"static"=1> { p4.write_en = 1'd1; p4.in = pow4.out; consume_pow4[done] = p4.done ? 1'd1; } group consume_pow5<"static"=1> { p5.write_en = 1'd1; p5.in = pow5.out; consume_pow5[done] = p5.done ? 1'd1; } group consume_pow6<"static"=1> { p6.write_en = 1'd1; p6.in = pow6.out; consume_pow6[done] = p6.done ? 1'd1; } group consume_pow7<"static"=1> { p7.write_en = 1'd1; p7.in = pow7.out; consume_pow7[done] = p7.done ? 1'd1; } group consume_pow8<"static"=1> { p8.write_en = 1'd1; p8.in = pow8.out; consume_pow8[done] = p8.done ? 1'd1; } group mult_by_reciprocal_factorial2 { mult_pipe2.left = p2.out; mult_pipe2.right = reciprocal_factorial2.out; mult_pipe2.go = !mult_pipe2.done ? 1'd1; product2.write_en = mult_pipe2.done; product2.in = mult_pipe2.out; mult_by_reciprocal_factorial2[done] = product2.done; } group mult_by_reciprocal_factorial3 { mult_pipe3.left = p3.out; mult_pipe3.right = reciprocal_factorial3.out; mult_pipe3.go = !mult_pipe3.done ? 1'd1; product3.write_en = mult_pipe3.done; product3.in = mult_pipe3.out; mult_by_reciprocal_factorial3[done] = product3.done; } group mult_by_reciprocal_factorial4 { mult_pipe4.left = p4.out; mult_pipe4.right = reciprocal_factorial4.out; mult_pipe4.go = !mult_pipe4.done ? 1'd1; product4.write_en = mult_pipe4.done; product4.in = mult_pipe4.out; mult_by_reciprocal_factorial4[done] = product4.done; } group mult_by_reciprocal_factorial5 { mult_pipe5.left = p5.out; mult_pipe5.right = reciprocal_factorial5.out; mult_pipe5.go = !mult_pipe5.done ? 1'd1; product5.write_en = mult_pipe5.done; product5.in = mult_pipe5.out; mult_by_reciprocal_factorial5[done] = product5.done; } group mult_by_reciprocal_factorial6 { mult_pipe6.left = p6.out; mult_pipe6.right = reciprocal_factorial6.out; mult_pipe6.go = !mult_pipe6.done ? 1'd1; product6.write_en = mult_pipe6.done; product6.in = mult_pipe6.out; mult_by_reciprocal_factorial6[done] = product6.done; } group mult_by_reciprocal_factorial7 { mult_pipe7.left = p7.out; mult_pipe7.right = reciprocal_factorial7.out; mult_pipe7.go = !mult_pipe7.done ? 1'd1; product7.write_en = mult_pipe7.done; product7.in = mult_pipe7.out; mult_by_reciprocal_factorial7[done] = product7.done; } group mult_by_reciprocal_factorial8 { mult_pipe8.left = p8.out; mult_pipe8.right = reciprocal_factorial8.out; mult_pipe8.go = !mult_pipe8.done ? 1'd1; product8.write_en = mult_pipe8.done; product8.in = mult_pipe8.out; mult_by_reciprocal_factorial8[done] = product8.done; } group sum_round1_1<"static"=1> { add1.left = frac_x.out; add1.right = product2.out; sum1.write_en = 1'd1; sum1.in = add1.out; sum_round1_1[done] = sum1.done; } group sum_round1_2<"static"=1> { add2.left = product3.out; add2.right = product4.out; sum2.write_en = 1'd1; sum2.in = add2.out; sum_round1_2[done] = sum2.done; } group sum_round1_3<"static"=1> { add3.left = product5.out; add3.right = product6.out; sum3.write_en = 1'd1; sum3.in = add3.out; sum_round1_3[done] = sum3.done; } group sum_round1_4<"static"=1> { add4.left = product7.out; add4.right = product8.out; sum4.write_en = 1'd1; sum4.in = add4.out; sum_round1_4[done] = sum4.done; } group sum_round2_1<"static"=1> { add1.left = sum1.out; add1.right = sum2.out; sum1.write_en = 1'd1; sum1.in = add1.out; sum_round2_1[done] = sum1.done; } group sum_round2_2<"static"=1> { add2.left = sum3.out; add2.right = sum4.out; sum2.write_en = 1'd1; sum2.in = add2.out; sum_round2_2[done] = sum2.done; } group sum_round3_1<"static"=1> { add1.left = sum1.out; add1.right = sum2.out; sum1.write_en = 1'd1; sum1.in = add1.out; sum_round3_1[done] = sum1.done; } group add_degree_zero<"static"=1> { add1.left = sum1.out; add1.right = one.out; sum1.write_en = 1'd1; sum1.in = add1.out; add_degree_zero[done] = sum1.done; } group final_multiply { mult_pipe1.left = pow1.out; mult_pipe1.right = sum1.out; mult_pipe1.go = !mult_pipe1.done ? 1'd1; m.write_en = mult_pipe1.done; m.in = mult_pipe1.out; final_multiply[done] = m.done; } out = m.out; } control { seq { init; if lt.out with is_negative { negate; } split_bits; par { invoke pow1(base=e.out, integer_exp=int_x.out)(); invoke pow2(base=frac_x.out, integer_exp=c2.out)(); invoke pow3(base=frac_x.out, integer_exp=c3.out)(); invoke pow4(base=frac_x.out, integer_exp=c4.out)(); invoke pow5(base=frac_x.out, integer_exp=c5.out)(); invoke pow6(base=frac_x.out, integer_exp=c6.out)(); invoke pow7(base=frac_x.out, integer_exp=c7.out)(); invoke pow8(base=frac_x.out, integer_exp=c8.out)(); } par { consume_pow2; consume_pow3; consume_pow4; consume_pow5; consume_pow6; consume_pow7; consume_pow8; } par { mult_by_reciprocal_factorial2; mult_by_reciprocal_factorial3; mult_by_reciprocal_factorial4; mult_by_reciprocal_factorial5; mult_by_reciprocal_factorial6; mult_by_reciprocal_factorial7; mult_by_reciprocal_factorial8; } par { sum_round1_1; sum_round1_2; sum_round1_3; sum_round1_4; } par { sum_round2_1; sum_round2_2; } par { sum_round3_1; } add_degree_zero; final_multiply; if lt.out with is_negative { reciprocal; } } } } component fp_pow(base: 32, integer_exp: 32) -> (out: 32) { cells { pow = std_reg(32); count = std_reg(32); mul = std_fp_smult_pipe(32, 16, 16); lt = std_slt(32); incr = std_sadd(32); } wires { group init { pow.in = 32'd65536; pow.write_en = 1'd1; count.in = 32'd0; count.write_en = 1'd1; init[done] = pow.done & count.done ? 1'd1; } group execute_mul { mul.left = base; mul.right = pow.out; mul.go = !mul.done ? 1'd1; pow.write_en = mul.done; pow.in = mul.out; execute_mul[done] = pow.done; } group incr_count { incr.left = 32'd1; incr.right = count.out; count.in = incr.out; count.write_en = 1'd1; incr_count[done] = count.done; } group cond { lt.left = count.out; lt.right = integer_exp; cond[done] = 1'd1; } out = pow.out; } control { seq { init; while lt.out with cond { par { execute_mul; incr_count; } } } } }