//rlnstool version 1.0 Oct 26, 2004 //copyright 2004 Mark G. Arnold All rights reserved /* NOTICE AND DISCLAIMER No use of this software is authorized except under this NOTICE AND DISCLAIMER. Downloading, use, copying, modification, and/or distribution of this software in its original or modified form implies your acceptance of this NOTICE and DISCLAIMER. Permission to use, copy, modify and distribute this software and its documentation, for any purpose and without fee is hereby granted, provided that this permission notice appears prominently in supporting documentation and must be viewed prior to use, copying, modification or distribution. You are responsible for any modifications to the software which you make and notice that the software has been modified must be appended to this notice prior to further use, copying, modification or distribution. This software is provided AS IS without warranty of any kind, including without limitation the warranties that the software is non-infringing, merchantable, or fit for a particular purpose, including high risk activities. The entire risk as to the quality and performance of the software is born by you. Should the software prove defective in any respect, you and not the developers, nor any parties associated with the developers, assume the entire cost of any service and repair. This software may be subject to the Export Control Laws of the United States of America. It is your responsibility to determine the applicable laws and regulations and comply with them. */ #include #include #include #include #include #include "rlnstool.h" #ifndef ZSCALE #define ZSCALE 16.0 #endif #ifndef BASE #define BASE 2.0 #endif #ifndef RLNSPATH #define RLNSPATH "c:/RLNS" #endif /* for checking against CRT in Koren p. 253-254 #define MAXMODULI 3 #define MODULUS0 2 #define MODULUS1 3 #define MODULUS2 7 #define MODULUS3 1 */ #define M (MODULUS0*MODULUS1*MODULUS2*MODULUS3) #define MAXPACKBITSLOW3 7 //#define MAXPACKBITS 7 (for MAXMODULI 3) #define MAXPACKBITS 10 //also, MAXMODULI,MAXPACKBITS and M needs to be consistant with init_residue_constants #define MIN (-(MODULUS3/2 )*MODULUS2*MODULUS1*MODULUS0) #define MAX ( (MODULUS3/2+1)*MODULUS2*MODULUS1*MODULUS0-1) #define MIN_BIPART (-(MODULUS2/2 )*MODULUS1*MODULUS0) #define MAX_BIPART ( (MODULUS2/2+1)*MODULUS1*MODULUS0-1) #define MAXPACK (1<=0; i--) { printf("%d\n",i); left_bitpos.m[i] = right_bitpos.m[i] + bitwidth.m[i] - 1; if (i != 0) right_bitpos.m[i-1] = left_bitpos.m[i] + 1; } minres = zero; minres.m[0] = 1; maxres = mone; maxres.m[0] = 0; } int res2pack(residuetype r) { int i,t; t = 0; for (i=0; i= MIN; cnt--) { bin2res[cnt+M] = rcnt; res2bin[res2pack(rcnt)] = cnt; add_residue(&rcnt, rcnt, mone); } } #define BIN2RES(x) bin2res[x+( x<0 ? M : 0 )] #define RES2BIN(x) res2bin[res2pack(x)] res2restype sb_lookup_tbl; res2restype db_lookup_tbl; resLNS2resLNStype sbdb; void init_residue_lookup() { int yi, zi; residuetype yres, zres; double y, z; for (zi = MIN; zi <= MAX; zi++) { z = zi / ZSCALE; y = log(1 + pow(BASE, z))/log(BASE); printf("%f sb=%f\n",z,y); yi = floor(y*ZSCALE + 0.5); zres = BIN2RES(zi); yres = BIN2RES(yi); sb_lookup_tbl[res2pack(zres)] = yres; sbdb[res2pack(zres)].x = yres; sbdb[res2pack(zres)].xsign = 0; if (zi != 0) y = log(fabs(1-pow(BASE, z)))/log(BASE); else y = MIN/ZSCALE; printf("%f db=%f\n",z,y); yi = floor(y*ZSCALE+0.5); zres = BIN2RES(zi); yres = BIN2RES(yi); db_lookup_tbl[res2pack(zres)] = yres; sbdb[MAXPACK + res2pack(zres)].x = yres; sbdb[MAXPACK + res2pack(zres)].xsign = zi>0; } //getchar(); } //verilog generating routines int check_moduli_count = 0; void print_check_moduli_define(FILE * f, int insidemodule) { int i; fprintf(f, "\n"); fprintf(f,"`ifdef MODULI"); for (i=0; i moduli.m[0]) fprintf(f, " assign z12[%d:%d] = submod%d(z[%d:%d], z[%d:%d]);\n", left_bitpos.m[i], right_bitpos.m[i], moduli.m[i], left_bitpos.m[i], right_bitpos.m[i], left_bitpos.m[0], right_bitpos.m[0]); else if (2*moduli.m[i] > moduli.m[0]) fprintf(f, " assign z12[%d:%d] = submod%d(z[%d:%d], mod%d(z[%d:%d]));\n", left_bitpos.m[i], right_bitpos.m[i], moduli.m[i], left_bitpos.m[i], right_bitpos.m[i], moduli.m[i], left_bitpos.m[0], right_bitpos.m[0]); else fprintf(f,"***error: ratio of moduli > 4***\n"); } fprintf(f, " assign t01 = lookup_t01(z[%d:%d]);\n", left_bitpos.m[0], right_bitpos.m[1]); fprintf(f, " assign z2 = submod%d(z[%d:%d], t01);\n", moduli.m[2], left_bitpos.m[2], right_bitpos.m[2]); fprintf(f, " assign t02 = lookup_t02({z[%d:%d],z2});\n", left_bitpos.m[0], right_bitpos.m[0]); fprintf(f, " assign t12 = lookup_t12(z12);\n"); for (i=0; i=0; i--) { for (s=0; s=0; i--) { for (s=0; s%d)?crt-%d:crt);\n",'"','%','"',MAX,M); fprintf(f, " if (crt>%d)\n",MAX); fprintf(f, " begin\n"); fprintf(f, " crt = %d-crt;\n",M); fprintf(f, " eps = %lf;\n",1.0/pow(BASE, 1.0/ZSCALE)); fprintf(f, " end\n"); fprintf(f, " else\n"); fprintf(f, " eps = %lf;\n",pow(BASE, 1.0/ZSCALE)); fprintf(f, " poweps = 1.0;\n"); fprintf(f, " for (i=1; i<=crt; i=i+1)\n"); fprintf(f, " poweps = poweps * eps;\n"); fprintf(f, " if (x[%d])\n",MAXPACKBITS); fprintf(f, " poweps = -1.0 * poweps;\n"); fprintf(f, " $write(%c=%c,poweps,%c %c);\n",'"', '"', '"', '"'); fprintf(f, " end\n"); fprintf(f, "endtask\n"); fprintf(f, "\n"); fclose(f); } void print_convert_residueLNS() { int i,crt; FILE * f; f = fopen(("cvt2rlns.v"),"w"); fprintf(f,"// moduli ["); for (i=0; i%d)\n",MAX); fprintf(f, " begin\n"); fprintf(f, " crt = %d-crt;\n",M); fprintf(f, " eps = %lf;\n",1.0/pow(BASE, 1.0/ZSCALE)); fprintf(f, " end\n"); fprintf(f, " else\n"); fprintf(f, " eps = %lf;\n",pow(BASE, 1.0/ZSCALE)); fprintf(f, " poweps = 1.0;\n"); fprintf(f, " for (i=1; i<=crt; i=i+1)\n"); fprintf(f, " poweps = poweps * eps;\n"); fprintf(f, " if (x[%d])\n",MAXPACKBITS); fprintf(f, " poweps = -1.0 * poweps;\n"); fprintf(f, " residueLNS2real = poweps;\n"); fprintf(f, " end\n"); fprintf(f, "endfunction\n"); fprintf(f, "\n"); fclose(f); } void print_print_residueLNS_1hot() { int i, onehotbits, bitpos, crt; FILE * f; f = fopen(("pri1rlns.v"),"w"); fprintf(f,"// onehot moduli ["); for (i=0; i%d)?crt-%d:crt);\n",'"','%','"',MAX,M); fprintf(f, " if (crt>%d)\n",MAX); fprintf(f, " begin\n"); fprintf(f, " crt = %d-crt;\n",M); fprintf(f, " eps = %lf;\n",1.0/pow(BASE, 1.0/ZSCALE)); fprintf(f, " end\n"); fprintf(f, " else\n"); fprintf(f, " eps = %lf;\n",pow(BASE, 1.0/ZSCALE)); fprintf(f, " poweps = 1.0;\n"); fprintf(f, " for (i=1; i<=crt; i=i+1)\n"); fprintf(f, " poweps = poweps * eps;\n"); fprintf(f, " if (x[%d])\n", onehotbits); fprintf(f, " poweps = -1.0 * poweps;\n"); fprintf(f, " $write(%c=%c,poweps,%c %c);\n",'"', '"', '"', '"'); fprintf(f, " end\n"); fprintf(f, "endtask\n"); fprintf(f, "\n"); fclose(f); } void print_convert_residueLNS_1hot() { int i, onehotbits, bitpos, crt; FILE * f; f = fopen(("cvt1rlns.v"),"w"); fprintf(f,"// onehot moduli ["); for (i=0; i%d)\n",MAX); fprintf(f, " begin\n"); fprintf(f, " crt = %d-crt;\n",M); fprintf(f, " eps = %lf;\n",1.0/pow(BASE, 1.0/ZSCALE)); fprintf(f, " end\n"); fprintf(f, " else\n"); fprintf(f, " eps = %lf;\n",pow(BASE, 1.0/ZSCALE)); fprintf(f, " poweps = 1.0;\n"); fprintf(f, " for (i=1; i<=crt; i=i+1)\n"); fprintf(f, " poweps = poweps * eps;\n"); fprintf(f, " if (x[%d])\n", onehotbits); fprintf(f, " poweps = -1.0 * poweps;\n"); fprintf(f, " if (count != 1)\n"); fprintf(f, " poweps = 'bx;\n"); fprintf(f, " residueLNS1hot2real = poweps;\n"); fprintf(f, " end\n"); fprintf(f, "endfunction\n"); fprintf(f, "\n"); fclose(f); } void print_naive_sbdb() { int i, z; FILE * f; //f = fopen(("resLNS.v"),"w"); f = fopen(("nsd2rlns.v"),"w"); fprintf(f,"// moduli ["); for (i=0; i> (MAXPACKBITS)); fprint_residue(f, BIN2RES(res2bin[((1 << MAXPACKBITS)-1) & z])); fprintf(f, " --> %d,",sbdb[z].xsign); fprint_residue(f, sbdb[z].x); fprintf(f, "\n"); } fprintf(f, " endcase\n"); fprintf(f, " end\n"); fprintf(f, "endmodule\n"); fprintf(f, "\n"); fclose(f); } int sbdblow_pos[2*MAXPACKLOW3]; int sbdblow_neg[2*MAXPACKLOW3]; int base_extend[2*MAXPACKLOW3]; int sbdblowpack_pos[MAXPACKLOW3]; int sbdblowpack_neg[MAXPACKLOW3]; int myM = MODULUS0*MODULUS1*MODULUS2; void init_sbdb_lowbits() { int result; int i, z, zi, mask, zsign, zaddr,high_mrc; residuetype zr,zrn; int zn, zaddr2n, zaddr2, testpos,testneg; printf("%d",2*MAXPACKLOW3); for (z = 0; z< 2*MAXPACKLOW3; z++) sbdblow_pos[z] = -1; for (z = 0; z< 2*MAXPACKLOW3; z++) sbdblow_neg[z] = -1; for (z = 0; z< 2*MAXPACK; z++) { zi = res2bin[((1 << MAXPACKBITS)-1) & z]; if ((zi < myM) && (( (z& ((1< 0)) ) sbdblow_pos[z>>bitwidth.m[3]] = res2pack(sbdb[z].x); } for (z = 0; z< 2*MAXPACK; z++) { zi = res2bin[((1 << MAXPACKBITS)-1) & z]; if ((zi >= -myM)&&(zi < 0)) sbdblow_neg[z>>bitwidth.m[3]] = res2pack(BIN2RES(RES2BIN(sbdb[z].x)-zi)); } for (z = 0; z< MAXPACKLOW3; z++) { sbdblowpack_pos[z] = sbdblow_pos[z<<1]; sbdblowpack_neg[z] = sbdblow_neg[z<<1]; } if (0) for (zi = -myM; zi < myM; zi++) { zr = BIN2RES(zi); z = res2pack(zr); zrn = BIN2RES(-zi); zn = res2pack(zrn); //if (zr.m[2]!=0) { zaddr = z >> bitwidth.m[3]; zaddr2 = zaddr >> 1; zaddr2n = zn >> (bitwidth.m[3]+1); if (zaddr & 1) { testneg = sbdblowpack_pos[zaddr2n]; testpos = sbdblowpack_neg[zaddr2n]; } else { testpos = sbdblowpack_pos[zaddr2]; testneg = sbdblowpack_neg[zaddr2]; } /* if ((testpos == sbdblow_pos[zaddr])&& (testneg == sbdblow_neg[zaddr])) printf(" ok %d",zi); else { printf("bad %d test p=%d n=%d true p=%d n=%d\n", zi,testpos,testneg,sbdblow_pos[zaddr],sbdblow_neg[zaddr]); print_residue(zr); print_residue(zrn); } getchar(); */ } } for (z = 0; z< 2*MAXPACKLOW3; z++) base_extend[z] = -1; for (z = 0; z< 2*MAXPACK; z++) { zi = res2bin[((1 << MAXPACKBITS)-1) & z]; if ((zi < myM) && (( (z& ((1< 0)) ) base_extend [z>>bitwidth.m[3]] = zi%moduli.m[3]; } } void print_mulinv_function(FILE * f, int myM, int modu) { int modu_bits, i; modu_bits = (int) ceil(log(modu)/log(2.0)); fprintf(f," function [%d:0] mulinv%d_%d;\n",modu_bits-1,myM,modu); fprintf(f," input [%d:0] x;\n",modu_bits-1); fprintf(f," begin\n"); fprintf(f," case(x)\n"); for (i=0; i=0; i--) { //leftbitpos = bitpos + moduli.m[i] - 1; //numpackbits = (int) ceil(log(moduli.m[i])/log(2.0)); for (k=1; k=0; i--) { for (j=0; j 0) & (high_mrc <=moduli.m[3]/2) ) select = 2; else select = 3; fprintf(f," %d: mulinv1h%d_%dsel = %d; //%d\n",1<>%d)\n",modu_bits+1); for (i=0; i>%d)\n",modu_bits+1); for (i=0; i=0; i--) { leftbitpos = bitpos + moduli.m[i] - 1; fprintf(f, " s[%d:%d] = add1hmod%d(a[%d:%d], b[%d:%d]);\n", leftbitpos, bitpos, moduli.m[i], leftbitpos, bitpos, leftbitpos, bitpos); bitpos += moduli.m[i]; } fprintf(f, " s[%d] = a[%d] ^ b[%d]; //sign bit\n",onehotbits, onehotbits, onehotbits); fprintf(f, " end\n"); fprintf(f, "endmodule\n"); fprintf(f, "\n"); fclose(f); } void print_div_1hotter_residueLNS() { int i, onehotbits, bitpos, leftbitpos; FILE * f; f = fopen(("div1rlns.v"),"w"); fprintf(f,"// onehot moduli ["); for (i=0; i=0; i--) { leftbitpos = bitpos + moduli.m[i] - 1; fprintf(f, " s[%d:%d] = sub1hmod%d(a[%d:%d], b[%d:%d]);\n", leftbitpos, bitpos, moduli.m[i], leftbitpos, bitpos, leftbitpos, bitpos); bitpos += moduli.m[i]; } fprintf(f, " s[%d] = a[%d] ^ b[%d]; //sign bit\n",onehotbits, onehotbits, onehotbits); fprintf(f, " end\n"); fprintf(f, "endmodule\n"); fprintf(f, "\n"); fclose(f); } void print_check_relerr(FILE * f, char op) { fprintf(f,"\n"); fprintf(f, " `ifdef CHECK_RELERR\n"); fprintf(f, "\n"); fprintf(f, " `include %ccvt2rlns.v%c\n",'"','"'); fprintf(f, " real reala, realb, reals, relerr;\n"); fprintf(f, " reg [%d:0] olds;\n",MAXPACKBITS); fprintf(f, "\n"); fprintf(f, " always @(s)\n"); fprintf(f, " begin\n"); fprintf(f, " olds = 'bz;\n"); fprintf(f, " while (olds !== s)\n"); fprintf(f, " begin\n"); fprintf(f, " #0; olds = s;\n"); fprintf(f, " end\n"); fprintf(f, " reala = residueLNS2real(a);\n"); fprintf(f, " realb = residueLNS2real(b);\n"); fprintf(f, " reals = residueLNS2real(s);\n"); fprintf(f, " relerr = (reala %c realb-reals)/(reala %c realb);\n",op,op); fprintf(f, " if (relerr < 0.0)\n"); fprintf(f, " relerr = -1.0 * relerr;\n"); fprintf(f, " if (relerr > `CHECK_RELERR)\n"); fprintf(f, " begin\n"); fprintf(f, " $write(%ca=%c,reala);\n",'"','"'); fprintf(f, " $write(%c (%ch) %c,a);\n",'"','%','"'); fprintf(f, " $write(%c b=%c,realb);\n",'"','"'); fprintf(f, " $write(%c (%ch) %c,b);\n",'"','%','"'); fprintf(f, " $write(%c a%cb=%c,reala %c realb);\n",'"',op,'"',op); fprintf(f, " $write(%c vs. s=%c,reals);\n",'"','"'); fprintf(f, " $write(%c (%ch) %c,s);\n",'"','%','"'); fprintf(f, " $write(%c relerr=%c,relerr);\n",'"','"'); fprintf(f, " $display(%c time= %cd%c,$time);\n",'"','%','"'); fprintf(f, " end\n"); fprintf(f, " end\n"); fprintf(f, " `endif\n"); fprintf(f, "\n"); } void print_mul_residueLNS() { int i; FILE * f; f = fopen(("mul2rlns.v"),"w"); fprintf(f,"// moduli ["); for (i=0; i>%d);\n",modu_bits-1,modu_bits); fprintf(f, " wire [%d:0] diff = submod%d(z[%d:0],baseext);\n",modu_bits-1,moduli.m[3],modu_bits-1); fprintf(f, " wire [1:0] select = mulinv%d_%dsel(diff);\n",myM,moduli.m[3]); fprintf(f, " assign {sbdb_pos,sbdb_neg} = sbdb_posneg(znew,z[%d]);\n", left_bitpos.m[MAXMODULI-1]+1); //????????????????????? fprintf(f, " assign sbdb_neg_plus_a[%d] = sbdb_neg[%d]^a[%d];\n",MAXPACKBITS,MAXPACKBITS,MAXPACKBITS); for (i=0; i=0; i--) { leftbitpos = bitpos + moduli.m[i] - 1; fprintf(f, " assign z[%d:%d] = sub1hmod%d(a[%d:%d], b[%d:%d]);\n", leftbitpos, bitpos, moduli.m[i], leftbitpos, bitpos, leftbitpos, bitpos); bitpos += moduli.m[i]; } fprintf(f, " assign negz[%d] = z[%d];\n",onehotbits,onehotbits); bitpos = 0; for (i=MAXMODULI-1; i >=0; i--) { leftbitpos = bitpos + moduli.m[i] - 1; fprintf(f, " assign negz[%d:%d] = sub1hmod%d(b[%d:%d], a[%d:%d]);\n", leftbitpos, bitpos, moduli.m[i], leftbitpos, bitpos, leftbitpos, bitpos); bitpos += moduli.m[i]; } fprintf(f, " wire oddz = 0"); for (i=1; i>%d);\n",moduli.m[3]-1,moduli.m[3]); fprintf(f, " wire [%d:0] diff = sub1hmod%d(z[%d:0],baseext);\n",moduli.m[3]-1,moduli.m[3],moduli.m[3]-1); fprintf(f, " wire [1:0] select = mulinv1h%d_%dsel(diff);\n",myM,moduli.m[3]); fprintf(f, " assign {sbdb_pos_pack,sbdb_neg_pack} = sbdb_posneg(rlns1h2pack(znew),oddz);\n"); fprintf(f, " assign sbdb_pos = rlnspack21h(sbdb_pos_pack);\n"); fprintf(f, " assign sbdb_neg = rlnspack21h(sbdb_neg_pack);\n"); //????????????????????? fprintf(f, " assign sbdb_neg_plus_a[%d] = sbdb_neg[%d]^a[%d];\n",onehotbits,onehotbits,onehotbits); bitpos = 0; for (i=MAXMODULI-1; i >=0; i--) { leftbitpos = bitpos + moduli.m[i] - 1; fprintf(f, " assign sbdb_neg_plus_a[%d:%d] = add1hmod%d(sbdb_neg[%d:%d], a[%d:%d]);\n", leftbitpos, bitpos, moduli.m[i], leftbitpos, bitpos, leftbitpos, bitpos); bitpos += moduli.m[i]; } fprintf(f, " assign sbdb_pos_plus_b[%d] = sbdb_pos[%d]^b[%d];\n",onehotbits,onehotbits,onehotbits); bitpos = 0; for (i=MAXMODULI-1; i >=0; i--) { leftbitpos = bitpos + moduli.m[i] - 1; fprintf(f, " assign sbdb_pos_plus_b[%d:%d] = add1hmod%d(sbdb_pos[%d:%d], b[%d:%d]);\n", leftbitpos, bitpos, moduli.m[i], leftbitpos, bitpos, leftbitpos, bitpos); bitpos += moduli.m[i]; } fprintf(f, " always @(a or b or select or sbdb_pos_plus_b or sbdb_neg_plus_a or z)\n"); fprintf(f, " begin\n"); fprintf(f, " case(select)\n"); fprintf(f, " 0: s = (z[%d]<<%d)^sbdb_pos_plus_b;//bugfix\n",onehotbits,onehotbits); fprintf(f, " 1: s = (z[%d]<<%d)^sbdb_neg_plus_a;\n",onehotbits,onehotbits); fprintf(f, " 2: s = a; //z;\n"); fprintf(f, " 3: s = b; //0;\n"); fprintf(f, " endcase\n"); fprintf(f, " end\n"); fprintf(f, "endmodule\n"); fprintf(f, "\n"); fclose(f); } unsigned long residue21hot(residuetype x) { unsigned long s; int i; s = 0; for (i = 0; i< MAXMODULI; i++) { s = s << moduli.m[i]; s |= 1 << x.m[i]; //printf(" %d %d %08lx\n",x.m[i], moduli.m[i], s); //getchar(); } return(s); } void print_naive_sbdb_1hot() { int i, z, zi, mask, onehotbits; unsigned long zsign, zsignonehot; FILE * f; f = fopen(("nsd1rlns.v"),"w"); fprintf(f,"// moduli ["); for (i=0; i=0; i--) { fprintf(f,"sbdb[%d] = sbdb[%d] | ", sbdb[z].x.m[i]+bitpos, sbdb[z].x.m[i]+bitpos); for (j=0; j