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; }
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(); };
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; } }