Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:59

0001 #include "L1Trigger/TrackFindingTracklet/interface/imath.h"
0002 
0003 using namespace trklet;
0004 
0005 void VarInv::writeLUT(std::ofstream& fs, Verilog) const {
0006   for (int i = 0; i < Nelements_; ++i)
0007     fs << std::hex << (LUT[i] & ((1 << nbits_) - 1)) << std::dec << "\n";
0008 }
0009 
0010 void VarBase::print_truncation(std::string& t, const std::string& o1, const int ps, Verilog) const {
0011   if (ps > 0) {
0012     t += "wire signed [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0013     t += "reg signed  [" + itos(nbits_ + ps - 1) + ":0]" + name_ + "_tmp;\n";
0014     t += "always @(posedge clk) " + name_ + "_tmp <= " + o1 + ";\n";
0015     t += "assign " + name_ + " = " + name_ + "_tmp[" + itos(nbits_ + ps - 1) + ":" + itos(ps) + "];\n";
0016   } else {
0017     t += "reg signed  [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0018     t += "always @(posedge clk) " + name_ + " <= " + o1 + ";\n";
0019   }
0020 }
0021 
0022 //
0023 // print functions
0024 //
0025 
0026 void VarCut::print(std::map<const VarBase*, std::set<std::string> >& cut_strings,
0027                    const int step,
0028                    Verilog,
0029                    const std::map<const VarBase*, std::set<std::string> >* const previous_cut_strings) const {
0030   int l = step - cut_var_->latency() - cut_var_->step();
0031   std::string name = cut_var_->name();
0032   if (l > 0)
0033     name += "_delay" + itos(l);
0034 
0035   const int lower_cut = lower_cut_ / cut_var_->K();
0036   const int upper_cut = upper_cut_ / cut_var_->K();
0037   if (!previous_cut_strings || (previous_cut_strings && !previous_cut_strings->count(cut_var_))) {
0038     if (!cut_strings.count(cut_var_))
0039       cut_strings[cut_var_];
0040     cut_strings.at(cut_var_).insert(name + " > " + itos(lower_cut) + " && " + name + " < " + itos(upper_cut));
0041   }
0042 }
0043 
0044 void VarBase::print_cuts(std::map<const VarBase*, std::set<std::string> >& cut_strings,
0045                          const int step,
0046                          Verilog,
0047                          const std::map<const VarBase*, std::set<std::string> >* const previous_cut_strings) const {
0048   if (p1_)
0049     p1_->print_cuts(cut_strings, step, verilog, previous_cut_strings);
0050   if (p2_)
0051     p2_->print_cuts(cut_strings, step, verilog, previous_cut_strings);
0052   if (p3_)
0053     p3_->print_cuts(cut_strings, step, verilog, previous_cut_strings);
0054 
0055   int l = step - latency_ - step_;
0056   std::string name = name_;
0057   if (l > 0)
0058     name += "_delay" + itos(l);
0059 
0060   for (const auto& cut : cuts_) {
0061     const VarCut* const cast_cut = (VarCut*)cut;
0062     const int lower_cut = cast_cut->lower_cut() / K_;
0063     const int upper_cut = cast_cut->upper_cut() / K_;
0064     if (!previous_cut_strings || (previous_cut_strings && !previous_cut_strings->count(this))) {
0065       if (!cut_strings.count(this))
0066         cut_strings[this];
0067       cut_strings.at(this).insert(name + " > " + itos(lower_cut) + " && " + name + " < " + itos(upper_cut));
0068     }
0069   }
0070 }
0071 
0072 void VarAdjustK::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0073   assert(p1_);
0074   assert(l2 == 0);
0075   assert(l3 == 0);
0076 
0077   std::string shift = "";
0078   if (lr_ > 0)
0079     shift = " >>> " + itos(lr_);
0080   else if (lr_ < 0)
0081     shift = " << " + itos(-lr_);
0082 
0083   std::string n1 = p1_->name();
0084   if (l1 > 0)
0085     n1 = n1 + "_delay" + itos(l1);
0086 
0087   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n";
0088   std::string t = "wire signed [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0089   t += "assign " + name_ + " = " + n1 + shift;
0090   fs << t << "; \n";
0091 }
0092 
0093 void VarAdjustKR::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0094   assert(p1_);
0095   assert(l2 == 0);
0096   assert(l3 == 0);
0097 
0098   std::string n1 = p1_->name();
0099   if (l1 > 0)
0100     n1 = n1 + "_delay" + itos(l1);
0101 
0102   std::string o1 = n1;
0103   if (lr_ == 1)
0104     o1 = "(" + o1 + "+1)>>>1";
0105   if (lr_ > 1)
0106     o1 = "( (" + o1 + ">>>" + itos(lr_ - 1) + ")+1)>>>1";
0107   if (lr_ < 0)
0108     o1 = o1 + "<<" + itos(-lr_);
0109 
0110   std::string t = "reg signed [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0111   t += "always @(posedge clk) " + name_ + " <= " + o1;
0112   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t << ";\n";
0113 }
0114 
0115 void VarDef::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0116   assert(l1 == 0);
0117   assert(l2 == 0);
0118   assert(l3 == 0);
0119 
0120   std::string t = "reg signed  [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0121   t = t + "always @(posedge clk) " + name_ + " <= " + name_ + "_wire;\n";
0122   fs << "// units " << kstring() << "\t" << K_ << "\n" << t;
0123 }
0124 
0125 void VarParam::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0126   assert(l1 == 0);
0127   assert(l2 == 0);
0128   assert(l3 == 0);
0129   std::string t = "parameter " + name_ + " = ";
0130   if (ival_ < 0)
0131     t = t + "- " + itos(nbits_) + "\'sd" + itos(-ival_);
0132   else
0133     t = t + itos(nbits_) + "\'sd" + itos(ival_);
0134   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t << ";\n";
0135 }
0136 
0137 void VarAdd::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0138   assert(p1_);
0139   assert(p2_);
0140   assert(l3 == 0);
0141   std::string o1 = p1_->name();
0142   if (l1 > 0)
0143     o1 += "_delay" + itos(l1);
0144   if (shift1 > 0) {
0145     o1 += "<<" + itos(shift1);
0146     o1 = "(" + o1 + ")";
0147   }
0148 
0149   std::string o2 = p2_->name();
0150   if (l2 > 0)
0151     o2 += "_delay" + itos(l2);
0152   if (shift2 > 0) {
0153     o2 += "<<" + itos(shift2);
0154     o2 = "(" + o2 + ")";
0155   }
0156 
0157   o1 = o1 + " + " + o2;
0158 
0159   std::string t = "";
0160   print_truncation(t, o1, ps_, verilog);
0161   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t;
0162 }
0163 
0164 void VarSubtract::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0165   assert(p1_);
0166   assert(p2_);
0167   assert(l3 == 0);
0168   std::string o1 = p1_->name();
0169   if (l1 > 0)
0170     o1 += "_delay" + itos(l1);
0171   if (shift1 > 0) {
0172     o1 += "<<" + itos(shift1);
0173     o1 = "(" + o1 + ")";
0174   }
0175 
0176   std::string o2 = p2_->name();
0177   if (l2 > 0)
0178     o2 += "_delay" + itos(l2);
0179   if (shift2 > 0) {
0180     o2 += "<<" + itos(shift2);
0181     o2 = "(" + o2 + ")";
0182   }
0183 
0184   o1 = o1 + " - " + o2;
0185 
0186   std::string t = "";
0187   print_truncation(t, o1, ps_, verilog);
0188   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t;
0189 }
0190 
0191 void VarNounits::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0192   assert(p1_);
0193   assert(l2 == 0);
0194   assert(l3 == 0);
0195   std::string n1 = p1_->name();
0196   if (l1 > 0)
0197     n1 = n1 + "_delay" + itos(l1);
0198   std::string o1 = "(" + n1 + " * " + itos(cI_) + ")";
0199 
0200   std::string t = "";
0201   print_truncation(t, o1, ps_, verilog);
0202   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t;
0203 }
0204 
0205 void VarTimesC::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0206   assert(p1_);
0207   assert(l2 == 0);
0208   assert(l3 == 0);
0209   std::string n1 = p1_->name();
0210   if (l1 > 0)
0211     n1 = n1 + "_delay" + itos(l1);
0212   std::string o1 = "(" + n1 + " * " + itos(cI_) + ")";
0213 
0214   std::string t = "";
0215   print_truncation(t, o1, ps_, verilog);
0216   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t;
0217 }
0218 
0219 void VarNeg::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0220   assert(p1_);
0221   assert(l2 == 0);
0222   assert(l3 == 0);
0223   std::string n1 = p1_->name();
0224   if (l1 > 0)
0225     n1 = n1 + "_delay" + itos(l1);
0226 
0227   std::string t = "reg signed  [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0228   t += "always @(posedge clk) " + name_ + " <= - " + n1;
0229   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t << ";\n";
0230 }
0231 
0232 void VarShiftround::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0233   assert(p1_);
0234   assert(l2 == 0);
0235   assert(l3 == 0);
0236   std::string n1 = p1_->name();
0237   if (l1 > 0)
0238     n1 = n1 + "_delay" + itos(l1);
0239   std::string o1 = n1;
0240   if (shift_ == 1)
0241     o1 = "(" + o1 + "+1)>>>1";
0242   if (shift_ > 1)
0243     o1 = "( (" + o1 + ">>>" + itos(shift_ - 1) + ")+1)>>>1";
0244   if (shift_ < 0)
0245     o1 = o1 + "<<" + itos(-shift_);
0246 
0247   std::string t = "reg signed [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0248   t += "always @(posedge clk) " + name_ + " <= " + o1;
0249   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t << ";\n";
0250 }
0251 
0252 void VarShift::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0253   assert(p1_);
0254   assert(l2 == 0);
0255   assert(l3 == 0);
0256   std::string n1 = p1_->name();
0257   if (l1 > 0)
0258     n1 = n1 + "_delay" + itos(l1);
0259   std::string o1 = n1;
0260   if (shift_ > 0)
0261     o1 = o1 + ">>>" + itos(shift_);
0262   if (shift_ < 0)
0263     o1 = o1 + "<<" + itos(-shift_);
0264 
0265   std::string t = "wire signed [" + itos(nbits_ - 1) + ":0]" + name_ + ";\n";
0266   t += "assign " + name_ + " = " + o1;
0267   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t << ";\n";
0268 }
0269 
0270 void VarMult::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0271   assert(l3 == 0);
0272   assert(p1_);
0273   std::string n1 = p1_->name();
0274   if (l1 > 0)
0275     n1 = n1 + "_delay" + itos(l1);
0276   assert(p2_);
0277   std::string n2 = p2_->name();
0278   if (l2 > 0)
0279     n2 = n2 + "_delay" + itos(l2);
0280   std::string o1 = n1 + " * " + n2;
0281 
0282   std::string t = "";
0283   print_truncation(t, o1, ps_, verilog);
0284   fs << "// " << nbits_ << " bits \t " << kstring() << "\t" << K_ << "\n" << t;
0285 }
0286 
0287 void VarInv::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0288   assert(p1_);
0289   assert(l2 == 0);
0290   assert(l3 == 0);
0291   std::string n1 = p1_->name();
0292   if (l1 > 0)
0293     n1 = n1 + "_delay" + itos(l1);
0294   //first calculate address
0295   std::string t1 = "addr_" + name_;
0296   std::string t = "wire [" + itos(nbaddr_ - 1) + ":0] " + t1 + ";\n";
0297   t = t + "assign " + t1 + " = ";
0298   if (shift_ > 0)
0299     t = t + "(" + n1 + ">>>" + itos(shift_) + ") & " + itos(mask_);
0300   else
0301     t = t + n1 + " & " + itos(mask_);
0302   fs << t << "; // address for the LUT\n";
0303 
0304   t = "wire signed [" + itos(nbits_ - 1) + ":0] " + name_ + ";\n";
0305   fs << t;
0306 
0307   std::string t2 = "LUT_" + name_;
0308 
0309   fs << "Memory #( \n";
0310   fs << "         .RAM_WIDTH(" << nbits_ << "),            // Specify RAM data width \n";
0311   fs << "         .RAM_DEPTH(" << Nelements_ << "),                     // Specify RAM depth (number of entries) \n";
0312   fs << "         .RAM_PERFORMANCE(\"HIGH_PERFORMANCE\"), // \"HIGH_PERFORMANCE\" = 2 clks latency \n";
0313   fs << "         .INIT_FILE() \n";
0314   fs << "       ) " << t2 << " ( \n";
0315   fs << "         .addra(" << itos(nbaddr_) << "\'b0),    // Write address bus, width determined from RAM_DEPTH  \n";
0316   fs << "         .addrb(" << t1 << " ),                   // Read address bus, width determined from RAM_DEPTH  \n";
0317   fs << "         .dina(" << itos(nbits_) << "\'b0),      // RAM input data, width determined from RAM_WIDTH   \n";
0318   fs << "         .clka(clk),      // Write clock \n";
0319   fs << "         .clkb(clk),      // Read clock  \n";
0320   fs << "         .wea(1\'b0),        // Write enable  \n";
0321   fs << "         .enb(1\'b1),        // Read Enable, for additional power savings, disable when not in use  \n";
0322   fs << "         .rstb(reset),      // Output reset (does not affect memory contents)                      \n";
0323   fs << "         .regceb(1\'b1),  // Output register enable                                                \n";
0324   fs << "         .doutb(" << name_ << ")     // RAM output data,                                                \n";
0325   fs << "     ); \n";
0326 }
0327 
0328 void VarDSPPostadd::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0329   assert(p1_);
0330   assert(p2_);
0331   assert(p3_);
0332   std::string n1 = p1_->name();
0333   if (l1 > 0)
0334     n1 = n1 + "_delay" + itos(l1);
0335   std::string n2 = p2_->name();
0336   if (l2 > 0)
0337     n2 = n2 + "_delay" + itos(l2);
0338   std::string n3 = p3_->name();
0339   if (l3 > 0)
0340     n3 = n3 + "_delay" + itos(l3);
0341 
0342   if (shift3_ > 0)
0343     n3 = n3 + "<<" + itos(shift3_);
0344   if (shift3_ < 0)
0345     n3 = n3 + ">>>" + itos(-shift3_);
0346 
0347   std::string n4 = "";
0348   if (ps_ > 0)
0349     n4 = ">>>" + itos(ps_);
0350 
0351   fs << name_ + " = DSP_postadd(" + n1 + ", " + n2 + ", " + n3 + ")" + n4 + ";";
0352 }
0353 
0354 void VarFlag::print(std::ofstream& fs, Verilog, int l1, int l2, int l3) {
0355   assert(l1 == 0);
0356   assert(l2 == 0);
0357   assert(l3 == 0);
0358 
0359   fs << "wire " << name_ << ";" << std::endl;
0360   fs << "assign " << name_ << " = (";
0361   std::map<const VarBase*, std::set<std::string> > cut_strings0, cut_strings1;
0362   for (const auto& cut : cuts_) {
0363     if (cut->op() != "cut")
0364       continue;
0365     const VarCut* const cast_cut = (VarCut*)cut;
0366     cast_cut->print(cut_strings0, step_, verilog);
0367   }
0368   for (const auto& cut : cuts_) {
0369     if (cut->op() != "cut")
0370       cut->print_cuts(cut_strings1, step_, verilog, &cut_strings0);
0371     else {
0372       if (cut->cut_var()->p1())
0373         cut->cut_var()->p1()->print_cuts(cut_strings1, step_, verilog, &cut_strings1);
0374       if (cut->cut_var()->p2())
0375         cut->cut_var()->p2()->print_cuts(cut_strings1, step_, verilog, &cut_strings1);
0376       if (cut->cut_var()->p3())
0377         cut->cut_var()->p3()->print_cuts(cut_strings1, step_, verilog, &cut_strings1);
0378     }
0379   }
0380 
0381   std::string separator = "";
0382   for (const auto& cut_var : cut_strings0) {
0383     separator += "((";
0384     for (const auto& cut_string : cut_var.second) {
0385       fs << separator << cut_string;
0386       separator = ") || (";
0387     }
0388     separator = ")) && ";
0389   }
0390   for (const auto& cut_var : cut_strings1) {
0391     separator += "((";
0392     for (const auto& cut_string : cut_var.second) {
0393       fs << separator << cut_string;
0394       separator = ") || (";
0395     }
0396     separator = ")) && ";
0397   }
0398 
0399   fs << ")));";
0400 }
0401 
0402 void VarBase::print_step(int step, std::ofstream& fs, Verilog) {
0403   if (!readytoprint_)
0404     return;
0405   if (step > step_)
0406     return;
0407   int l1 = 0;
0408   int l2 = 0;
0409   int l3 = 0;
0410   if (p1_) {
0411     p1_->print_step(step, fs, verilog);
0412     l1 = step_ - p1_->latency() - p1_->step();
0413   }
0414   if (p2_) {
0415     p2_->print_step(step, fs, verilog);
0416     l2 = step_ - p2_->latency() - p2_->step();
0417   }
0418   if (p3_) {
0419     p3_->print_step(step, fs, verilog);
0420     l3 = step_ - p3_->latency() - p3_->step();
0421   }
0422   if (step == step_) {
0423     if (l1 < 0 || l2 < 0 || l3 < 0 || (l1 > 0 && l2 > 0 && l3 > 0)) {
0424       char slog[100];
0425       sprintf(slog, "%s::print_step(%i): something wrong with latencies! %i %i %i\n", name_.c_str(), step, l1, l2, l3);
0426       edm::LogVerbatim("Tracklet") << slog;
0427       dump_msg();
0428       assert(0);
0429     }
0430     if (l1 > 0) {
0431       if (p1_->op() != "const")
0432         fs << pipe_delay(p1_, p1_->nbits(), l1);
0433       else
0434         l1 = 0;
0435     }
0436     if (l2 > 0) {
0437       if (p2_->op() != "const")
0438         fs << pipe_delay(p2_, p2_->nbits(), l2);
0439       else
0440         l2 = 0;
0441     }
0442     if (l3 > 0) {
0443       if (p3_->op() != "const")
0444         fs << pipe_delay(p3_, p3_->nbits(), l3);
0445       else
0446         l3 = 0;
0447     }
0448 
0449     if (op_ == "flag") {
0450       for (const auto& cut : cuts_)
0451         fs << cut->cut_var()->pipe_delays(step_);
0452     }
0453 
0454     print(fs, verilog, l1, l2, l3);
0455     readytoprint_ = false;
0456   }
0457 }
0458 
0459 void VarBase::print_all(std::ofstream& fs, Verilog) {
0460   for (int i = 0; i <= step_; ++i) {
0461     fs << "//\n// STEP " << i << "\n\n";
0462     print_step(i, fs, verilog);
0463   }
0464 }
0465 
0466 void VarBase::design_print(const std::vector<VarBase*>& v, std::ofstream& fs, Verilog) {
0467   //step at which all the outputs should be valid
0468   int maxstep = 0;
0469 
0470   //header of the module
0471 
0472   //inputs
0473   std::vector<VarBase*> vd;
0474   vd.clear();
0475   int imax = v.size();
0476   for (int i = 0; i < imax; ++i) {
0477     (v[i])->inputs(&vd);
0478     int step = v[i]->step() + v[i]->latency();
0479     if (step > maxstep)
0480       maxstep = step;
0481   }
0482 
0483   //print header
0484   fs << "module \n";
0485   fs << "(\n";
0486   fs << "   input clk,\n";
0487   fs << "   input reset,\n\n";
0488 
0489   imax = vd.size();
0490   for (int i = 0; i < imax; ++i)
0491     fs << "   input [" << (vd[i])->nbits() - 1 << ":0] " << (vd[i])->name() << "_wire,\n";
0492   fs << "\n";
0493 
0494   imax = v.size() - 1;
0495   for (int i = 0; i < imax; ++i)
0496     if (v[i]->nbits() > 1)
0497       fs << "   output [" << (v[i])->nbits() - 1 << ":0] " << (v[i])->name() << "_wire,\n";
0498     else
0499       fs << "   output " << (v[i])->name() << "_wire,\n";
0500   if (imax >= 0) {
0501     if (v[imax]->nbits() > 1)
0502       fs << "   output [" << (v[imax])->nbits() - 1 << ":0] " << (v[imax])->name() << "_wire\n";
0503     else
0504       fs << "   output " << (v[imax])->name() << "_wire\n";
0505   }
0506   fs << ");\n\n";
0507 
0508   //body of the module
0509   imax = v.size();
0510   for (int i = 0; i < imax; ++i) {
0511     fs << "\n//\n";
0512     fs << "// calculating " << (v[i])->name() << "\n";
0513     fs << "//\n";
0514     (v[i])->print_all(fs, verilog);
0515   }
0516   fs << "\n";
0517 
0518   //trailer
0519   fs << "\n";
0520   fs << "\n//\n";
0521   fs << "// wiring the outputs \n";
0522   fs << "// latency = " << maxstep << "\n";
0523   fs << "//\n";
0524   for (int i = 0; i < imax; ++i) {
0525     std::string n = v[i]->name() + "_wire";
0526     int delay = maxstep - v[i]->step() - v[i]->latency();
0527     if (delay == 0)
0528       fs << "assign " << n << " = " << (v[i])->name() << ";\n";
0529     else
0530       fs << pipe_delay_wire(v[i], n, v[i]->nbits(), delay);
0531   }
0532 
0533   fs << "endmodule\n";
0534 }