TaMaDiDecoder::TaMaDiDecoder(Target* target, int n): Operator(target) { srcFileName="TaMaDiDecoder"; ostringstream name; int outWires = intlog2(n-1); name <<"TaMaDiDecoder_n"<<n<<"_output"<<outWires<<"_uid"<<getNewUId(); setName(name.str()); setCopyrightString("Bogdan Pasca (2011)"); /* Set up the I/O signals of of the entity */ int inWires = intlog2(n-1); addInput ("X",inWires,true); addOutput ("R",n,1,true); vhdl << tab << "with X select" << endl; vhdl << tab << "R <= "<<endl; for (int i=0;i<n;i++){ vhdl << tab << tab <<"\""; for (int k=0;k<i;k++) vhdl << "0"; vhdl << "1"; for (int k=i+1;k<n;k++) vhdl << "0"; vhdl <<"\""; vhdl << " when \"" << unsignedBinary( n-1-i, inWires) <<"\","<<endl; } vhdl << tab << tab << zg(n) <<" when others;" << endl; }
FPge_expr::FPge_expr(Target* _target, int wE, int wF) : Operator(_target) { ostringstream name; name<<"FPge_expr_" <<wE<<"_"<<wF; setName(name.str()); setCopyrightString("Fabrizio Ferrandi (2011-2017)"); /* Set up the IO signals */ addFPInput ("X", wE,wF); addFPInput ("Y", wE,wF); addOutput ("R", 1); /* VHDL code description */ manageCriticalPath(_target->localWireDelay() + _target->lutDelay()); vhdl << tab << declare("nY",wE+wF+3) << " <= Y"<< range(wE+wF+2,wE+wF+1) << " & not(Y"<< of(wE+wF) << ") & Y" << range(wE+wF-1,0) << ";" << endl; FPAdderSinglePath * value_difference = new FPAdderSinglePath(_target, wE, wF, wE, wF, wE, wF); value_difference->changeName(getName()+"value_difference"); oplist.push_back(value_difference); inPortMap (value_difference, "X", "X"); inPortMap (value_difference, "Y", "nY"); outPortMap (value_difference, "R","valueDiff"); vhdl << instance(value_difference, "value_difference"); syncCycleFromSignal("valueDiff"); setCriticalPath(value_difference->getOutputDelay("R")); manageCriticalPath(_target->localWireDelay() + _target->lutDelay()); vhdl << tab << "R(0) <= '1' when (valueDiff" << of(wE+wF) << "='0' or (valueDiff" << range(wE+wF+2,wE+wF+1) << " = \"00\")) else '0';" << endl; }
LNSMul::LNSMul(Target * target, int wE, int wF) : Operator(target), wE(wE), wF(wF) { ostringstream name; /* The name has the format: LNSMul_wE_wF where: wE = width of the integral part of the exponent wF = width of the fractional part of the exponent */ name << "LNSMul_" << wE << "_" << wF; setName(name.str()); setCopyrightString("Jérémie Detrey, Florent de Dinechin (2003-2004), Sylvain Collange (2008)"); addInput ("nA", wE + wF + 3); addInput ("nB", wE + wF + 3); addOutput("nR", wE + wF + 3); addConstant("wE", "positive", wE); addConstant("wF", "positive", wF); //vhdl << tab << declare("eRn", wE+wF+1) << " <= (nA(wE+wF-1) & nA(wE+wF-1 downto 0)) + (nB(wE+wF-1) & nB(wE+wF-1 downto 0));\n"; IntAdder *my_adder = new IntAdder(target, wE+wF+1); oplist.push_back(my_adder); vhdl << tab << declare("X", wE+wF+1) << "<= nA(wE+wF-1) & nA(wE+wF-1 downto 0);\n"; vhdl << tab << declare("Y", wE+wF+1) << "<= nB(wE+wF-1) & nB(wE+wF-1 downto 0);\n"; inPortMap (my_adder, "X", "X"); inPortMap (my_adder, "Y", "Y"); inPortMapCst(my_adder, "Cin", "'0'"); outPortMap (my_adder, "R","eRn"); vhdl << instance(my_adder, "my_add"); vhdl << tab << declare("sRn") << " <= nA(wE+wF) xor nB(wE+wF);\n"; vhdl << tab << declare("xRn", 2) << " <= \"00\" when eRn(wE+wF downto wE+wF-1) = \"10\" else\n" << tab << " \"10\" when eRn(wE+wF downto wE+wF-1) = \"01\" else\n" << tab << " \"01\";\n"; vhdl << tab << declare("nRn", wE+wF+3) << " <= xRn & sRn & eRn(wE+wF-1 downto 0);\n"; vhdl << tab << declare("xA", 2) << " <= nA(wE+wF+2 downto wE+wF+1);\n"; vhdl << tab << declare("xB", 2) << " <= nB(wE+wF+2 downto wE+wF+1);\n"; vhdl << tab << declare("xAB", 4) << " <= xA & xB when xA >= xB else\n" << tab << " xB & xA;\n"; vhdl << tab << "with xAB select\n" << tab << tab << "nR(wE+wF+2 downto wE+wF+1) <= xRn when \"0101\",\n" << tab << " \"00\" when \"0000\" | \"0100\",\n" << tab << " \"10\" when \"1001\" | \"1010\",\n" << tab << " \"11\" when others;\n" << tab << "\n" << tab << "nR(wE+wF downto 0) <= nRn(wE+wF downto 0);\n"; }
TaMaDiPriorityEncoder::TaMaDiPriorityEncoder(Target* target, int n): Operator(target) { srcFileName="TaMaDiPriorityEncoder"; ostringstream name; int outWires = intlog2(n-1); name <<"TaMaDiPriorityEncoder_n"<<n<<"_output"<<outWires<<"_uid"<<getNewUId(); setName(name.str()); setCopyrightString("Bogdan Pasca (2011)"); /* Set up the I/O signals of of the entity */ addInput ("X",n,true); addOutput ("R",outWires,1,true); // vhdl << tab << "with X select" << endl; // vhdl << tab << "R <= "<<endl; // for (int i=0;i<n;i++){ // vhdl << tab << tab << "\""<< unsignedBinary(n-1-i,outWires) <<"\" when \""; // for (int k=0;k<i;k++) // vhdl << "0"; // vhdl << "1"; // for (int k=i+1;k<n;k++) // vhdl << "X"; // vhdl <<"\","<<endl; // } // vhdl << tab << tab << tab << zg(outWires) <<" when others;" << endl; vhdl << tab << "R <= "<<endl; for (int i=0;i<n;i++){ vhdl << tab << tab << "\""<< unsignedBinary(n-1-i,outWires) <<"\" when "; vhdl << "X("<<n-i-1<<")='1' else" << endl; } ostringstream dcare; dcare << "\""; for (int i=0; i<outWires; i++) dcare << "X"; dcare << "\""; vhdl << tab << tab << tab << dcare.str() <<";" << endl; }
FixAtan2ByCORDIC::FixAtan2ByCORDIC(Target* target_, int wIn_, int wOut_, map<string, double> inputDelays_) : FixAtan2(target_, wIn_, wOut_, inputDelays_) { int stage; srcFileName="FixAtan2ByCORDIC"; setCopyrightString ( "Matei Istoan, Florent de Dinechin (2012-...)" ); useNumericStd_Unsigned(); ostringstream name; name << "FixAtan2ByCORDIC_" << wIn_ << "_" << wOut_ << "_uid" << getNewUId(); setNameWithFreq( name.str() ); mpfr_t zatan; mpfr_init2(zatan, 10*wOut); computeGuardBits(); //Defining the various parameters according to method ///////////// VHDL GENERATION ///////////////////////////////////////////////////////////////////////////// // // First range reduction // ///////////////////////////////////////////////////////////////////////////// buildQuadrantRangeReduction(); // No scaling RR: just a copy vhdl << tab << declare("XRS", wIn-1) << " <= XR;" << endl; vhdl << tab << declare("YRS", wIn-1) << " <= YR;" << endl; int sizeZ=wOut-2+gA; // w-2 because two bits come from arg red //////////////////////////////////////////////////////////////////////////// // // CORDIC iterations // //////////////////////////////////////////////////////////////////////////// // Fixed-point considerations: // Y -> 0 and X -> K.sqrt(x1^2+y1^2) // Max value attained by X is sqrt(2)*K which is smaller than 2 int zMSB=-1; // -1 because these two bits have weight 0 and -1, but we must keep the sign int zLSB = zMSB-sizeZ+1; int sizeX = wIn+gXY; int sizeY = sizeX; vhdl << tab << declare("X1", sizeX) << " <= '0' & XRS & " << zg(sizeX-(wIn-1)-1) << ";" <<endl; vhdl << tab << declare("Y1", sizeY) << " <= '0' & YRS & " << zg(sizeY-(wIn-1)-1) << ";" <<endl; stage=1; manageCriticalPath( getTarget()->adderDelay(sizeX)); vhdl << tab << "--- Iteration " << stage << " : sign is known positive ---" << endl; vhdl << tab << declare(join("YShift", stage), sizeX) << " <= " << rangeAssign(sizeX-1, sizeX-stage, "'0'") << " & Y" << stage << range(sizeX-1, stage) << ";" << endl; vhdl << tab << declare(join("X", stage+1), sizeX) << " <= " << join("X", stage) << " + " << join("YShift", stage) << " ;" << endl; vhdl << tab << declare(join("XShift", stage), sizeY) << " <= " << zg(stage) << " & X" << stage << range(sizeY-1, stage) << ";" <<endl; vhdl << tab << declare(join("Y", stage+1), sizeY) << " <= " << join("Y", stage) << " - " << join("XShift", stage) << " ;" << endl; //create the constant signal for the arctan mpfr_set_d(zatan, 1.0, GMP_RNDN); mpfr_div_2si(zatan, zatan, stage, GMP_RNDN); mpfr_atan(zatan, zatan, GMP_RNDN); mpfr_div(zatan, zatan, constPi, GMP_RNDN); mpfr_t roundbit; mpfr_init2(roundbit, 30); // should be enough for anybody mpfr_set_d(roundbit, 1.0, GMP_RNDN); mpfr_div_2si(roundbit, roundbit, wOut, GMP_RNDN); // roundbit is in position 2^-wOut REPORT(DEBUG, "stage=" << stage << " atancst=" << printMPFR(zatan)); mpfr_add(zatan, zatan, roundbit, GMP_RNDN); vhdl << tab << declare("Z2", sizeZ) << " <= " << unsignedFixPointNumber(zatan, zMSB, zLSB) << "; -- initial atan, plus round bit" <<endl; for(stage=2; stage<=maxIterations; stage++, sizeY--){ // Invariant: sizeX-sizeY = stage-2 vhdl << tab << "--- Iteration " << stage << " ---" << endl; manageCriticalPath( getTarget()->localWireDelay(sizeX+1) + getTarget()->adderDelay(max(sizeX,sizeZ)) ); vhdl << tab << declare(join("sgnY", stage)) << " <= " << join("Y", stage) << of(sizeY-1) << ";" << endl; if(-2*stage+1 >= -wIn+1-gXY) { vhdl << tab << declare(join("YShift", stage), sizeX) << " <= " << rangeAssign(sizeX-1, sizeX -(sizeX-sizeY+stage), join("sgnY", stage)) << " & Y" << stage << range(sizeY-1, stage) << ";" << endl; vhdl << tab << declare(join("X", stage+1), sizeX) << " <= " << join("X", stage) << " - " << join("YShift", stage) << " when " << join("sgnY", stage) << "=\'1\' else " << join("X", stage) << " + " << join("YShift", stage) << " ;" << endl; } else { // autant pisser dans un violon vhdl << tab << declare(join("X", stage+1), sizeX) << " <= " << join("X", stage) << " ;" << endl; } vhdl << tab << declare(join("XShift", stage), sizeY) << " <= " << zg(2) << " & X" << stage << range(sizeX-1, sizeX - sizeY + 2) << ";" <<endl; vhdl << tab << declare(join("YY", stage+1), sizeY) << " <= " << join("Y", stage) << " + " << join("XShift", stage) << " when " << join("sgnY", stage) << "=\'1\' else " << join("Y", stage) << " - " << join("XShift", stage) << " ;" << endl; vhdl << tab << declare(join("Y", stage+1), sizeY-1) << " <= " << join("YY", stage+1) << range(sizeY-2, 0) << ";" <<endl; //create the constant signal for the arctan mpfr_set_d(zatan, 1.0, GMP_RNDN); mpfr_div_2si(zatan, zatan, stage, GMP_RNDN); mpfr_atan(zatan, zatan, GMP_RNDN); mpfr_div(zatan, zatan, constPi, GMP_RNDN); REPORT(DEBUG, "stage=" << stage << " atancst=" << printMPFR(zatan)); // rounding here in unsignedFixPointNumber() vhdl << tab << declare(join("atan2PowStage", stage), sizeZ) << " <= " << unsignedFixPointNumber(zatan, zMSB, zLSB) << ";" <<endl; vhdl << tab << declare(join("Z", stage+1), sizeZ) << " <= " << join("Z", stage) << " + " << join("atan2PowStage", stage) << " when " << join("sgnY", stage) << "=\'0\' else " << join("Z", stage) << " - " << join("atan2PowStage", stage) << " ;" << endl; } //end for loop // Give the time to finish the last rotation // manageCriticalPath( getTarget()->localWireDelay(w+1) + getTarget()->adderDelay(w+1) // actual CP delay // - (getTarget()->localWireDelay(sizeZ+1) + getTarget()->adderDelay(sizeZ+1))); // CP delay that was already added manageCriticalPath( getTarget()->localWireDelay(wOut+1) + getTarget()->adderDelay(2) ); vhdl << tab << declare("finalZ", wOut) << " <= Z" << stage << of(sizeZ-1) << " & Z" << stage << range(sizeZ-1, sizeZ-wOut+1) << "; -- sign-extended and rounded" << endl; buildQuadrantReconstruction(); };
void FixComplexKCM::init() { if(lsb_in>msb_in) { throw string("FixComplexKCM: Error, lsbIn>msbIn"); } // definition of the source file name, used for info and error reporting // using REPORT srcFileName="FixComplexKCM"; // definition of the name of the operator ostringstream name; name << "FixComplexKCM_" << vhdlize(msb_in) <<"_" << vhdlize(lsb_in) << "_" << vhdlize(lsb_out) << "_" << vhdlize(constant_re) << "_" << vhdlize(constant_im) << "_" << ((signedInput) ? "" : "un") << "signed" ; setName(name.str()); // Copyright setCopyrightString("3IF 2015 dev team (2015)"); input_width = 1 + msb_in - lsb_in; // declaring inputs addInput ("ReIN" , input_width); addInput ("ImIN" , input_width); //Computing constants for testBench and in order to know constant width sollya_obj_t nodeIm, nodeRe; nodeRe = sollya_lib_parse_string(constant_re.c_str()); if(sollya_lib_obj_is_error(nodeRe)) { ostringstream error; error << srcFileName <<" : Unable to parse string \"" << constant_re << "\" as a numeric constant" << endl; throw error.str(); } nodeIm = sollya_lib_parse_string(constant_im.c_str()); if(sollya_lib_obj_is_error(nodeIm)) { ostringstream error; error << srcFileName <<" : Unable to parse string \"" << constant_im << "\" as a numeric constant" << endl; throw error.str(); } mpfr_inits2(10000, mpfr_constant_re, mpfr_constant_im, NULL); sollya_lib_get_constant(mpfr_constant_re, nodeRe); sollya_lib_get_constant(mpfr_constant_im, nodeIm); constantReNeg = (mpfr_sgn(mpfr_constant_re) < 0); constantImNeg = (mpfr_sgn(mpfr_constant_im) < 0); mpfr_t log2C; mpfr_init2(log2C, 100); //Constant real part width mpfr_log2(log2C, mpfr_constant_re, GMP_RNDN); constantReMsb = mpfr_get_si(log2C, GMP_RNDU); //Constant imaginary part width mpfr_log2(log2C, mpfr_constant_im, GMP_RNDN); constantImMsb = mpfr_get_si(log2C, GMP_RNDU); //Free mpfr_clear(log2C); int constantMaxMSB = max(constantReMsb, constantImMsb); //Do we need an extra sign bit ? bool extraSignBitRe = !signedInput && (constantReNeg || !constantImNeg); bool extraSignBitIm = !signedInput && (constantReNeg || constantImNeg); int msbout_re, msbout_im; msbout_re = msbout_im = msb_in + constantMaxMSB +1; if(extraSignBitRe) { msbout_re++; } if(extraSignBitIm) { msbout_im++; } outputre_width = msbout_re - lsb_out + 1; outputim_width = msbout_im - lsb_out + 1; if(outputre_width < 0 || outputim_width < 0) { THROWERROR("Computed msb will be lower than asked lsb." " Result would always be zero "); } }
FPSumOf3Squares::FPSumOf3Squares(Target* target, int wE, int wF, int optimize) : Operator(target), wE(wE), wF(wF) { setCopyrightString("F. de Dinechin, Bogdan Pasca (2011)"); srcFileName="FPSumOf3Squares"; ostringstream o; o << "FPSumOf3Squares_" << wE << "_" << wF; if(!optimize) o << "_FP"; setName(o.str()); addFPInput("X", wE, wF); addFPInput("Y", wE, wF); addFPInput("Z", wE, wF); addFPOutput("R", wE, wF, 2); // This 2 means: we will allow two possible inputs (faithful rounding) if(!optimize) { //////////////////////////////////////////////////////////////////: // A version that assembles FP operators // //////////////////////////////////////////////////////////////////: FPMult* mult = new FPMult(target, wE, wF, wE, wF, wE, wF, 1); oplist.push_back(mult); FPAddSinglePath* add = new FPAddSinglePath(target, wE, wF, wE, wF, wE, wF); oplist.push_back(add); inPortMap (mult, "X", "X"); inPortMap (mult, "Y", "X"); outPortMap(mult, "R", "X2"); vhdl << instance(mult, "multx"); inPortMap (mult, "X", "Y"); inPortMap (mult, "Y", "Y"); outPortMap(mult, "R", "Y2"); vhdl << instance(mult, "multy"); inPortMap (mult, "X", "Z"); inPortMap (mult, "Y", "Z"); outPortMap(mult, "R", "Z2"); vhdl << instance(mult, "multz"); syncCycleFromSignal("Z2", false); nextCycle(); inPortMap (add, "X", "X2"); inPortMap (add, "Y", "Y2"); outPortMap(add, "R", "X2PY2"); vhdl << instance(add, "add1"); syncCycleFromSignal("X2PY2", false); nextCycle(); inPortMap (add, "X", "X2PY2"); inPortMap (add, "Y", "Z2"); outPortMap(add, "R", "X2PY2PZ2"); vhdl << instance(add, "add2"); syncCycleFromSignal("X2PY2PZ2", false); setCriticalPath(add->getOutputDelay("R")); vhdl << tab << "R <= X2PY2PZ2;"<<endl; outDelayMap["R"]=getCriticalPath(); } else { ////////////////// here comes the FloPoCo version //////////////////////////: // Error analysis // 3 ulps(wF+g) in the multiplier truncation // Again 2 ulps(wF+g) in the shifter output truncation // Normalisation truncation: either 0 (total 5), or 1 ulp(wF+g) but dividing the previous by 2 (total 3.5) // Total max 5 ulps, we're safe with 3 guard bits // guard bits for a faithful result int g=3; // The exponent datapath // setCriticalPath( getMaxInputDelays(inputDelays) + target->localWireDelay()); setCriticalPath(0); manageCriticalPath( target->adderDelay(wE+1) // subtractions + target->localWireDelay(wE) // fanout of XltY etc + target->lutDelay() // & and mux ); //--------------------------------------------------------------------- // extract the three biased exponents. vhdl << tab << declare("EX", wE) << " <= X" << range(wE+wF-1, wF) << ";" << endl; vhdl << tab << declare("EY", wE) << " <= Y" << range(wE+wF-1, wF) << ";" << endl; vhdl << tab << declare("EZ", wE) << " <= Z" << range(wE+wF-1, wF) << ";" << endl; // determine the max of the exponents vhdl << tab << declare("DEXY", wE+1) << " <= ('0' & EX) - ('0' & EY);" << endl; vhdl << tab << declare("DEYZ", wE+1) << " <= ('0' & EY) - ('0' & EZ);" << endl; vhdl << tab << declare("DEXZ", wE+1) << " <= ('0' & EX) - ('0' & EZ);" << endl; vhdl << tab << declare("XltY") << " <= DEXY("<< wE<<");" << endl; vhdl << tab << declare("YltZ") << " <= DEYZ("<< wE<<");" << endl; vhdl << tab << declare("XltZ") << " <= DEXZ("<< wE<<");" << endl; // rename the exponents to A,B,C with A>=(B,C) vhdl << tab << declare("EA", wE) << " <= " << endl << tab << tab << "EZ when (XltZ='1') and (YltZ='1') else " << endl << tab << tab << "EY when (XltY='1') and (YltZ='0') else " << endl << tab << tab << "EX; " << endl; vhdl << tab << declare("EB", wE) << " <= " << endl << tab << tab << "EX when (XltZ='1') and (YltZ='1') else " << endl << tab << tab << "EZ when (XltY='1') and (YltZ='0') else " << endl << tab << tab << "EY; " << endl; vhdl << tab << declare("EC", wE) << " <= " << endl << tab << tab << "EY when (XltZ='1') and (YltZ='1') else " << endl << tab << tab << "EX when (XltY='1') and (YltZ='0') else " << endl << tab << tab << "EZ; " << endl; //--------------------------------------------------------------------- // Now recompute our two shift values -- they were already computed at cycle 0 but it is cheaper this way, otherwise we have to register, negate and mux them. manageCriticalPath( target->adderDelay(wE-1) ); vhdl << tab << declare("fullShiftValB", wE) << " <= (EA" << range(wE-2,0) << " - EB" << range(wE-2,0) << ") & '0' ; -- positive result, no overflow " << endl; vhdl << tab << declare("fullShiftValC", wE) << " <= (EA" << range(wE-2,0) << " - EC" << range(wE-2,0) << ") & '0' ; -- positive result, no overflow " << endl; double cpfullShiftValC = getCriticalPath(); //--------------------------------------------------------------------- Shifter* rightShifterDummy = new Shifter(target,wF+g+2, wF+g+2, Shifter::Right); int sizeRightShift = rightShifterDummy->getShiftInWidth(); //-- Manage the shift value of the mantissa of B -------- manageCriticalPath( target->localWireDelay() + target->lutDelay()); vhdl<<tab<<declare("shiftedOutB") << " <= "; if (wE>sizeRightShift){ for (int i=wE-1;i>=sizeRightShift;i--) { vhdl<< "fullShiftValB("<<i<<")"; if (i>sizeRightShift) vhdl<< " or "; } vhdl<<";"<<endl; } else vhdl<<tab<<"'0';"<<endl; if (wE>sizeRightShift) { manageCriticalPath( target->localWireDelay() + target->lutDelay()); vhdl<<tab<<declare("shiftValB",sizeRightShift) << " <= fullShiftValB("<< sizeRightShift-1<<" downto 0)" << " when shiftedOutB='0'"<<endl <<tab << tab << " else CONV_STD_LOGIC_VECTOR("<<wF+g+1<<","<<sizeRightShift<<") ;" << endl; }else if (wE==sizeRightShift) { vhdl<<tab<<declare("shiftValB",sizeRightShift) << " <= fullShiftValB;" << endl ; }else { // wE< sizeRightShift vhdl<<tab<<declare("shiftValB",sizeRightShift) << " <= CONV_STD_LOGIC_VECTOR(0,"<<sizeRightShift-wE <<") & fullShiftValB;" << endl; } double cpshiftValB = getCriticalPath(); //-- Manage the shift value of the mantissa of C -------- manageCriticalPath( target->localWireDelay() + target->lutDelay()); //FIXME possible fixme needed when or does not fit on lut vhdl<<tab<<declare("shiftedOutC") << " <= "; if (wE>sizeRightShift){ for (int i=wE-1;i>=sizeRightShift;i--) { vhdl<< "fullShiftValC("<<i<<")"; if (i>sizeRightShift) vhdl<< " or "; } vhdl<<";"<<endl; } else vhdl<<tab<<"'0';"<<endl; setCycleFromSignal("fullShiftValC",cpfullShiftValC); if (wE>sizeRightShift) { manageCriticalPath( target->localWireDelay() + target->lutDelay());//the mux delay vhdl<<tab<<declare("shiftValC",sizeRightShift) << " <= fullShiftValC("<< sizeRightShift-1<<" downto 0)" << " when shiftedOutC='0'"<<endl <<tab << tab << " else CONV_STD_LOGIC_VECTOR("<<wF+g+1<<","<<sizeRightShift<<") ;" << endl; } else if (wE==sizeRightShift) { vhdl<<tab<<declare("shiftValC",sizeRightShift) << " <= fullShiftValC;" << endl ; } else { // wE< sizeRightShift vhdl<<tab<<declare("shiftValC",sizeRightShift) << " <= CONV_STD_LOGIC_VECTOR(0,"<<sizeRightShift-wE <<") & fullShiftValC;" << endl; } // Back to cycle 0 for the significand datapath setCycle(0); //FIXME add inDelayMap for use within hierarchies of components // Square the significands #define USE_SQUARER 1 #if USE_SQUARER IntSquarer* mult = new IntSquarer(target, 1+ wF); #else IntMultiplier* mult = new IntMultiplier(target, 1+ wF, 1+ wF); #endif oplist.push_back(mult); vhdl << tab << declare("mX", wF+1) << " <= '1' & X" << range(wF-1, 0) << "; " << endl; inPortMap (mult, "X", "mX"); #if !USE_SQUARER inPortMap (mult, "Y", "mX"); #endif outPortMap(mult, "R", "mX2"); vhdl << instance(mult, "multx"); vhdl << tab << declare("mY", wF+1) << " <= '1' & Y" << range(wF-1, 0) << "; " << endl; inPortMap (mult, "X", "mY"); #if !USE_SQUARER inPortMap (mult, "Y", "mY"); #endif outPortMap(mult, "R", "mY2"); vhdl << instance(mult, "multy"); vhdl << tab << declare("mZ", wF+1) << " <= '1' & Z" << range(wF-1, 0) << "; " << endl; inPortMap (mult, "X", "mZ"); #if !USE_SQUARER inPortMap (mult, "Y", "mZ"); #endif outPortMap(mult, "R", "mZ2"); vhdl << instance(mult, "multz"); syncCycleFromSignal("mZ2", false); setCriticalPath(mult->getOutputDelay("R")); // truncate the three results to wF+g+2 int prodsize = 2+2*wF; vhdl << tab << declare("X2t", wF+g+2) << " <= mX2" << range(prodsize-1, prodsize - wF-g-2) << "; " << endl; vhdl << tab << declare("Y2t", wF+g+2) << " <= mY2" << range(prodsize-1, prodsize - wF-g-2) << "; " << endl; vhdl << tab << declare("Z2t", wF+g+2) << " <= mZ2" << range(prodsize-1, prodsize - wF-g-2) << "; " << endl; // Now we have our three FP squares, we rename them to A,B,C with A>=(B,C) // only 3 3-muxes manageCriticalPath(target->localWireDelay(wF) + target->lutDelay()); vhdl << tab << declare("MA", wF+g+2) << " <= " << endl << tab << tab << "Z2t when (XltZ='1') and (YltZ='1') else " << endl << tab << tab << "Y2t when (XltY='1') and (YltZ='0') else " << endl << tab << tab << "X2t; " << endl; vhdl << tab << declare("MB", wF+g+2) << " <= " << endl << tab << tab << "X2t when (XltZ='1') and (YltZ='1') else " << endl << tab << tab << "Z2t when (XltY='1') and (YltZ='0') else " << endl << tab << tab << "Y2t; " << endl; vhdl << tab << declare("MC", wF+g+2) << " <= " << endl << tab << tab << "Y2t when (XltZ='1') and (YltZ='1') else " << endl << tab << tab << "X2t when (XltY='1') and (YltZ='0') else " << endl << tab << tab << "Z2t; " << endl; //Synchronize exponent and significand datapath syncCycleFromSignal("shiftValB", cpshiftValB, false); // B and C right shifters are the same Shifter* rightShifter = new Shifter(target,wF+g+2, wF+g+2, Shifter::Right, inDelayMap("X",target->localWireDelay()+getCriticalPath())); oplist.push_back(rightShifter); inPortMap (rightShifter, "X", "MB"); inPortMap (rightShifter, "S", "shiftValB"); outPortMap (rightShifter, "R","shiftedB"); vhdl << instance(rightShifter, "ShifterForB"); inPortMap (rightShifter, "X", "MC"); inPortMap (rightShifter, "S", "shiftValC"); outPortMap (rightShifter, "R","shiftedC"); vhdl << instance(rightShifter, "ShifterForC"); // superbly ignore the bits that are shifted out syncCycleFromSignal("shiftedB", false); setCriticalPath( rightShifter->getOutputDelay("R")); int shiftedB_size = getSignalByName("shiftedB")->width(); vhdl << tab << declare("alignedB", wF+g+2) << " <= shiftedB" << range(shiftedB_size-1, shiftedB_size -(wF+g+2)) << "; " << endl; vhdl << tab << declare("alignedC", wF+g+2) << " <= shiftedC" << range(shiftedB_size-1, shiftedB_size -(wF+g+2)) << "; " << endl; vhdl << tab << declare("paddedA", wF+g+4) << " <= \"00\" & MA; " << endl; vhdl << tab << declare("paddedB", wF+g+4) << " <= \"00\" & alignedB; " << endl; vhdl << tab << declare("paddedC", wF+g+4) << " <= \"00\" & alignedC; " << endl; IntMultiAdder* adder = new IntMultiAdder(target,wF+g+4, 3, inDelayMap("X0", target->localWireDelay() + getCriticalPath() )); oplist.push_back(adder); inPortMap (adder, "X0", "paddedA"); inPortMap (adder, "X1", "paddedB"); inPortMap (adder, "X2", "paddedC"); inPortMapCst(adder, "Cin", "'0'"); // a 1 would compensate the two truncations in the worst case -- to explore outPortMap (adder, "R","sum"); vhdl << instance(adder, "adder1"); syncCycleFromSignal("sum", false); setCriticalPath(adder->getOutputDelay("R")); manageCriticalPath(target->localWireDelay() + target->lutDelay()); // Possible 3-bit normalisation, with a truncation vhdl << tab << declare("finalFraction", wF+g) << " <= " << endl << tab << tab << "sum" << range(wF+g+2,3) << " when sum(" << wF+g+3 << ")='1' else " << endl << tab << tab << "sum" << range(wF+g+1, 2) << " when (sum" << range(wF+g+3, wF+g+2) << "=\"01\") else " << endl << tab << tab << "sum" << range(wF+g, 1) << " when (sum" << range(wF+g+3, wF+g+1) << "=\"001\") else " << endl << tab << tab << "sum" << range(wF+g-1, 0) << "; " << endl; // Exponent datapath. We have to compute 2*EA - bias + an update corresponding to the normalisatiobn // since (1.m)*(1.m) = xx.xxxxxx sum is xxxx.xxxxxx // All the following ignores overflows, infinities, zeroes, etc for the sake of simplicity. manageCriticalPath(target->localWireDelay() + target->lutDelay()); int bias = (1<<(wE-1))-1; vhdl << tab << declare("exponentUpdate", wE+1) << " <= " << endl << tab << tab << "CONV_STD_LOGIC_VECTOR(" << bias-3 << ", "<< wE+1 <<") when sum(" << wF+g+3 << ")='1' else " << endl << tab << tab << "CONV_STD_LOGIC_VECTOR(" << bias-2 << ", "<< wE+1 <<") when (sum" << range(wF+g+3, wF+g+2) << "=\"01\") else " << endl << tab << tab << "CONV_STD_LOGIC_VECTOR(" << bias-1 << ", "<< wE+1 <<") when (sum" << range(wF+g+3, wF+g+1) << "=\"001\") else " << endl << tab << tab << "CONV_STD_LOGIC_VECTOR(" << bias << ", "<< wE+1 <<") ; " << endl; manageCriticalPath( target->localWireDelay() + target->adderDelay(wE+1)); vhdl << tab << declare("finalExp", wE+1) << " <= (EA & '0') - exponentUpdate ; " << endl; IntAdder *roundingAdder = new IntAdder(target, wE +1 + wF); oplist.push_back(roundingAdder); vhdl << tab << declare("roundingOp",wE+1 + wF) << "<= finalExp & finalFraction"<<range(wF+g-1,g)<<";"<<endl; inPortMap ( roundingAdder, "X", "roundingOp"); inPortMapCst ( roundingAdder, "Y", zg(wE+1+wF)); inPortMapCst ( roundingAdder, "Cin", "'1'"); outPortMap ( roundingAdder, "R", "expFrac"); vhdl << tab << instance( roundingAdder, "RoundingAdder"); syncCycleFromSignal("expFrac"); setCriticalPath( roundingAdder->getOutputDelay("R")); //TODO vhdl << tab << declare("rExc",2) << " <= \"01\" when expFrac"<<of(wE+wF)<<"='0' else \"10\";"<<endl; vhdl << tab << "R <= rExc & '0' & expFrac"<<range(wE+1 + wF-2,0)<<";"<<endl; } }