CAMLexport int caml_umul_overflow(uintnat a, uintnat b, uintnat * res) { #define HALF_SIZE (sizeof(uintnat) * 4) #define HALF_MASK (((uintnat)1 << HALF_SIZE) - 1) #define LOW_HALF(x) ((x) & HALF_MASK) #define HIGH_HALF(x) ((x) >> HALF_SIZE) /* Cut in half words */ uintnat al = LOW_HALF(a); uintnat ah = HIGH_HALF(a); uintnat bl = LOW_HALF(b); uintnat bh = HIGH_HALF(b); /* Exact product is: al * bl + ah * bl << HALF_SIZE + al * bh << HALF_SIZE + ah * bh << 2*HALF_SIZE Overflow occurs if: ah * bh is not 0, i.e. ah != 0 and bh != 0 OR ah * bl has high half != 0 OR al * bh has high half != 0 OR the sum al * bl + LOW_HALF(ah * bl) << HALF_SIZE + LOW_HALF(al * bh) << HALF_SIZE overflows. This sum is equal to p = (a * b) modulo word size. */ uintnat p = a * b; uintnat p1 = al * bh; uintnat p2 = ah * bl; *res = p; if (ah == 0 && bh == 0) return 0; if (ah != 0 && bh != 0) return 1; if (HIGH_HALF(p1) != 0 || HIGH_HALF(p2) != 0) return 1; p1 <<= HALF_SIZE; p2 <<= HALF_SIZE; p1 += p2; if (p < p1 || p1 < p2) return 1; /* overflow in sums */ return 0; #undef HALF_SIZE #undef HALF_MASK #undef LOW_HALF #undef HIGH_HALF }
void dh_hw_mult::process_hw_mult() { NN_DIGIT a[2], b, c, t, u; //NN_HALF_DIGIT bHigh, bLow, cHigh, cLow; while (true) { if (reset.read() == true){ state.write(S0_WAIT); hw_mult_done.write(false); } else { switch(state.read()){ case S0_WAIT: // wait for enable signal to be asserted if (hw_mult_enable.read() == true) { state.write(S1_EXECUTE); } break; case S1_EXECUTE: //multiply the inputs // Read inputs /*b = in_data_1.read(); c = in_data_2.read();*/ // Original code from NN_DigitMult()... /*bHigh = b_high.read(); //(NN_HALF_DIGIT)HIGH_HALF (b); bLow = b_low.read(); //(NN_HALF_DIGIT)LOW_HALF (b); cHigh = c_high.read();//(NN_HALF_DIGIT)HIGH_HALF (c); cLow = c_low.read(); //(NN_HALF_DIGIT)LOW_HALF (c);*/ a[0] = a0temp.read();//(NN_DIGIT)bLow * (NN_DIGIT)cLow; t = t_temp.read(); //(NN_DIGIT)bLow * (NN_DIGIT)cHigh; u = u_temp.read(); //(NN_DIGIT)bHigh * (NN_DIGIT)cLow; a[1] = a1temp.read();//(NN_DIGIT)bHigh * (NN_DIGIT)cHigh; if ((t += u) < u) a[1] += TO_HIGH_HALF (1); //t = t + u < u u = TO_HIGH_HALF (t); if ((a[0] += u) < u) a[1]++; a[1] += HIGH_HALF (t); state.write(S2_OUTPUT); break; case S2_OUTPUT: //write to modules output ports, assert done signal // Write Outputs out_data_low.write(a[0]); out_data_high.write(a[1]); hw_mult_done.write(true); wait(); state.write(S3_FINISH); break; case S3_FINISH: //check if enable is deasserted, if so deassert done if (hw_mult_enable.read() == false) { hw_mult_done.write(false); wait(); state.write(S0_WAIT); } break; } }wait(); } }