File indexing completed on 2023-03-17 11:13:51
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
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
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
0468 int maxstep = 0;
0469
0470
0471
0472
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
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
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
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 }