string Operator::use(string name) throw(std::string) { ostringstream e; e << "ERROR in use(), "; // just in case if(isSequential()) { Signal *s; try { s=getSignalByName(name); } catch (string e2) { e << endl << tab << e2; throw e.str(); } if(s->getCycle() < 0) { e << "signal " << name<< " doesn't have (yet?) a valid cycle"; throw e.str(); } if(s->getCycle() > currentCycle_) { ostringstream e; e << "active cycle of signal " << name<< " is later than current cycle, cannot delay it"; throw e.str(); } // update the lifeSpan of s s->updateLifeSpan( currentCycle_ - s->getCycle() ); return s->delayedName( currentCycle_ - s->getCycle() ); } else return name; }
void Operator::syncCycleFromSignal(string name, bool report) throw(std::string) { ostringstream e; e << "ERROR in syncCycleFromSignal, "; // just in case if(isSequential()) { Signal* s; try { s=getSignalByName(name); } catch (string e2) { e << endl << tab << e2; throw e.str(); } if( s->getCycle() < 0 ) { ostringstream o; o << "signal " << name << " doesn't have (yet?) a valid cycle"; throw o.str(); } // advance cycle if needed if (s->getCycle()>currentCycle_) currentCycle_ = s->getCycle(); if(report) vhdl << tab << "----------------Synchro barrier, entering cycle " << currentCycle_ << "----------------" << endl ; // automatically update pipeline depth of the operator if (currentCycle_ > pipelineDepth_) pipelineDepth_ = currentCycle_; } }
int Operator::setClk(std::string name) { rmClk(); if ( Signal *s = getSignalByName(name) ) { s->setClk(1); return 1; } return 0; }
/* should be only one Clk */ int Operator::rmClk() { int cnt = 0; std::string clk = getClkName(); while ( clk.compare("") !=0 ) { cnt++; getSignalByName(clk)->setClk(0); clk = getClkName(); } return cnt; }
void Operator::inPortMap(Operator* op, string componentPortName, string actualSignalName) throw(std::string) { Signal* formal; ostringstream e; string name; e << "ERROR in inPortMap(), "; // just in case if(isSequential()) { Signal *s; try { s=getSignalByName(actualSignalName); } catch (string e2) { e << endl << tab << e2; throw e.str(); } if(s->getCycle() < 0) { ostringstream e; e << "signal " << actualSignalName<< " doesn't have (yet?) a valid cycle"; throw e.str(); } if(s->getCycle() > currentCycle_) { ostringstream e; e << "active cycle of signal " << actualSignalName<< " is later than current cycle, cannot delay it"; throw e.str(); } // update the lifeSpan of s s->updateLifeSpan( currentCycle_ - s->getCycle() ); name = s->delayedName( currentCycle_ - s->getCycle() ); } else name = actualSignalName; try { formal=op->getSignalByName(componentPortName); } catch (string e2) { e << endl << tab << e2; throw e.str(); } if (formal->type()!=Signal::in){ e << "signal " << componentPortName << " of component " << op->getName() << " doesn't seem to be an input port"; throw e.str(); } // add the mapping to the mapping list of Op op->portMap_[componentPortName] = name; }
FixComplexKCM::FixComplexKCM( Target* target, bool signedInput, int msb_in, int lsb_in, int lsb_out, string constant_re, string constant_im ): Operator(target), signedInput(signedInput), msb_in(msb_in), lsb_in(lsb_in), lsb_out(lsb_out), constant_re(constant_re), constant_im(constant_im) { init(); //For final rounding precision int guard_bits = 1; double targetUlpError = 1.0; // declaring output addOutput("ReOut", outputre_width); addOutput("ImOut", outputim_width); if(mpfr_zero_p(mpfr_constant_im) != 0 && mpfr_zero_p(mpfr_constant_re) != 0) { vhdl << tab << "ReOut" << " <= " << zg(outputre_width, 0) << ";" << endl; vhdl << tab << "ImOut" << " <= " << zg(outputim_width, 0) << ";" << endl; } else { int kcmImGuardBits = FixRealKCM::neededGuardBits( target, input_width, targetUlpError, constant_im, lsb_in, lsb_out - guard_bits ); int kcmMImGuardBits = FixRealKCM::neededGuardBits( target, input_width, targetUlpError, "-1*" + constant_im, lsb_in, lsb_out - guard_bits ); int kcmReGuardBits = FixRealKCM::neededGuardBits( target, input_width, targetUlpError, constant_re, lsb_in, lsb_out - guard_bits ); // basic message REPORT(INFO,"Declaration of FixComplexKCM\n"); int guardBits_re = max(kcmReGuardBits, kcmMImGuardBits); int guardBits_im = max(kcmReGuardBits, kcmImGuardBits); BitHeap* bitheapRe = new BitHeap( this, guardBits_re + outputre_width + guard_bits ); BitHeap* bitheapIm = new BitHeap( this, guardBits_im + outputim_width + guard_bits ); //Add 1/2 ulp bitheapIm->addConstantOneBit(0); bitheapRe->addConstantOneBit(0); //---- Real part computation ------------------------------------------ new FixRealKCM( this, target, getSignalByName("ReIN"), signedInput, msb_in, lsb_in, lsb_out - guard_bits, constant_re, bitheapRe, lsb_out - guardBits_re - guard_bits ); new FixRealKCM( this, target, getSignalByName("ImIN"), signedInput, msb_in, lsb_in, lsb_out - guard_bits, "-1 * " + constant_im, bitheapRe, lsb_out - guard_bits - guardBits_re ); //--- Imaginary part computation -------------------------------------- new FixRealKCM( this, target, getSignalByName("ImIN"), signedInput, msb_in, lsb_in, lsb_out - guard_bits, constant_re, bitheapIm, lsb_out - guard_bits - guardBits_im ); new FixRealKCM( this, target, getSignalByName("ReIN"), signedInput, msb_in, lsb_in, lsb_out - guard_bits, constant_im, bitheapIm, lsb_out - guard_bits - guardBits_im ); //BitHeap management bitheapIm->generateCompressorVHDL(); bitheapRe->generateCompressorVHDL(); vhdl << "ImOut" << " <= " << bitheapIm->getSumName( outputim_width+guardBits_im+guard_bits -1, guardBits_im+guard_bits ) << ";" << endl; vhdl << "ReOut" << " <= " << bitheapRe->getSumName( outputre_width + guardBits_re + guard_bits - 1, guardBits_re+guard_bits ) << ";" << endl; } };
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; } }