Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:22:04

0001 #include <vector>
0002 #include <utility>
0003 #include <set>
0004 #include <cmath>
0005 #include <iostream>
0006 #include <fstream>
0007 #include <sstream>
0008 #include <cstdlib>
0009 #include <cassert>
0010 #include <mutex>
0011 
0012 #include "L1Trigger/TrackFindingTracklet/interface/TrackletConfigBuilder.h"
0013 #include "L1Trigger/TrackFindingTracklet/interface/Settings.h"
0014 #ifdef CMSSW_GIT_HASH
0015 #include "L1Trigger/TrackFindingTracklet/interface/Util.h"
0016 #include "L1Trigger/TrackTrigger/interface/Setup.h"
0017 #endif
0018 
0019 using namespace std;
0020 using namespace trklet;
0021 
0022 TrackletConfigBuilder::TrackletConfigBuilder(const Settings& settings, const tt::Setup* setup) : settings_(settings) {
0023   NSector_ = N_SECTOR;
0024   rcrit_ = settings.rcrit();
0025 
0026   combinedmodules_ = settings.combined();
0027 
0028   extended_ = settings.extended();
0029 
0030   rinvmax_ = settings.rinvmax();
0031 
0032   rmaxdisk_ = settings.rmaxdisk();
0033   zlength_ = settings.zlength();
0034 
0035   for (int i = 0; i < N_LAYER; i++) {
0036     rmean_[i] = settings.rmean(i);
0037   }
0038 
0039   for (int i = 0; i < N_DISK; i++) {
0040     zmean_[i] = settings.zmean(i);
0041   }
0042 
0043   dphisectorHG_ = settings.dphisectorHG();
0044 
0045   for (int layerdisk = 0; layerdisk < N_LAYER + N_DISK; layerdisk++) {
0046     NRegions_[layerdisk] = settings.nallstubs(layerdisk);
0047     NVMME_[layerdisk] = settings.nvmme(layerdisk);
0048   }
0049 
0050   for (unsigned int iseed = 0; iseed < N_SEED_PROMPT; iseed++) {
0051     NVMTE_[iseed] = std::pair<unsigned int, unsigned int>(settings.nvmte(0, iseed), settings.nvmte(1, iseed));
0052     NTC_[iseed] = settings.NTC(iseed);
0053   }
0054 
0055   initGeom();
0056 
0057   buildTE();
0058 
0059   buildTC();
0060 
0061   buildProjections();
0062 
0063   setDTCphirange(setup);
0064 
0065   if (settings_.writeConfig()) {
0066     static std::once_flag runOnce;  // Only one thread should call this.
0067     std::call_once(runOnce, &TrackletConfigBuilder::writeDTCphirange, this);
0068   }
0069 }
0070 
0071 //--- Calculate phi range of modules read by each DTC.
0072 
0073 #ifdef CMSSW_GIT_HASH
0074 
0075 void TrackletConfigBuilder::setDTCphirange(const tt::Setup* setup) {
0076   list<DTCinfo> vecDTCinfo_unsorted;
0077 
0078   // Loop over DTCs in this tracker nonant.
0079   unsigned int numDTCsPerSector = setup->numDTCsPerRegion();
0080   for (unsigned int dtcId = 0; dtcId < numDTCsPerSector; dtcId++) {
0081     typedef std::pair<float, float> PhiRange;
0082     std::map<int, PhiRange> dtcPhiRange;
0083 
0084     // Loop over all tracker nonants, taking worst case not all identical.
0085     for (unsigned int iSector = 0; iSector < N_SECTOR; iSector++) {
0086       unsigned int dtcId_regI = iSector * numDTCsPerSector + dtcId;
0087       const std::vector<tt::SensorModule*>& dtcModules = setup->dtcModules(dtcId_regI);
0088       for (const tt::SensorModule* sm : dtcModules) {
0089         // Convert layer number to Hybrid convention.
0090         int layer = sm->layerId();  // Barrel = 1-6, Endcap = 11-15;
0091         if (sm->barrel()) {
0092           layer--;  // Barrel 0-5
0093         } else {
0094           const int endcapOffsetHybrid = 5;
0095           layer -= endcapOffsetHybrid;  // Layer 6-19
0096         }
0097         // Inner radius of module.
0098         float r = sm->r() - 0.5 * sm->numColumns() * sm->pitchCol() * fabs(sm->sinTilt());
0099         // phi with respect to tracker nonant centre.
0100         float phiMin = sm->phi() - 0.5 * sm->numRows() * sm->pitchRow() / r;
0101         float phiMax = sm->phi() + 0.5 * sm->numRows() * sm->pitchRow() / r;
0102         // Hybrid measures phi w.r.t. lower edge of tracker nonant.
0103         const float phiOffsetHybrid = 0.5 * dphisectorHG_;
0104         phiMin += phiOffsetHybrid;
0105         phiMax += phiOffsetHybrid;
0106         if (dtcPhiRange.find(layer) == dtcPhiRange.end()) {
0107           dtcPhiRange[layer] = {phiMin, phiMax};
0108         } else {
0109           dtcPhiRange.at(layer).first = std::min(phiMin, dtcPhiRange.at(layer).first);
0110           dtcPhiRange.at(layer).second = std::max(phiMax, dtcPhiRange.at(layer).second);
0111         }
0112       }
0113     }
0114     for (const auto& p : dtcPhiRange) {
0115       const unsigned int numSlots = setup->numATCASlots();
0116       std::string dtcName = settings_.slotToDTCname(dtcId % numSlots);
0117       if (dtcId >= numSlots)
0118         dtcName = "neg" + dtcName;
0119       DTCinfo info;
0120       info.name = dtcName;
0121       info.layer = p.first;
0122       info.phimin = p.second.first;
0123       info.phimax = p.second.second;
0124       vecDTCinfo_unsorted.push_back(info);
0125     }
0126   }
0127 
0128   // Put DTCinfo vector in traditional order (PS first). (Needed?)
0129   for (const DTCinfo& info : vecDTCinfo_unsorted) {
0130     string dtcname = info.name;
0131     if (dtcname.find("PS") != std::string::npos) {
0132       vecDTCinfo_.push_back(info);
0133     }
0134   }
0135   for (const DTCinfo& info : vecDTCinfo_unsorted) {
0136     string dtcname = info.name;
0137     if (dtcname.find("PS") == std::string::npos) {
0138       vecDTCinfo_.push_back(info);
0139     }
0140   }
0141 }
0142 
0143 //--- Write DTC phi ranges to file to support stand-alone emulation.
0144 //--- (Only needed to support stand-alone emulation)
0145 
0146 void TrackletConfigBuilder::writeDTCphirange() const {
0147   bool first = true;
0148   for (const DTCinfo& info : vecDTCinfo_) {
0149     string dirName = settings_.tablePath();
0150     string fileName = dirName + "../dtcphirange.dat";
0151     std::ofstream out;
0152     openfile(out, first, dirName, fileName, __FILE__, __LINE__);
0153     if (first) {
0154       out << "// layer & phi ranges of modules read by each DTC" << endl;
0155       out << "// (Used by stand-alone emulation)" << endl;
0156     }
0157     out << info.name << " " << info.layer << " " << info.phimin << " " << info.phimax << endl;
0158     out.close();
0159     first = false;
0160   }
0161 }
0162 
0163 #else
0164 
0165 //--- Set DTC phi ranges from .txt file (stand-alone operation only)
0166 
0167 void TrackletConfigBuilder::setDTCphirange(const tt::Setup* setup) {
0168   // This file previously written by writeDTCphirange().
0169   const string fname = "../data/dtcphirange.txt";
0170   if (vecDTCinfo_.empty()) {  // Only run once per thread.
0171     std::ifstream str_dtc;
0172     str_dtc.open(fname);
0173     assert(str_dtc.good());
0174     string line;
0175     while (ifstream, getline(line)) {
0176       std::istringstream iss(line);
0177       DTCinfo info;
0178       iss >> info.name >> info.layer >> info.phimin >> info.phimax;
0179       vecDTCinfo_.push_back(info);
0180     }
0181     str_dtc.close();
0182   }
0183 }
0184 
0185 #endif
0186 
0187 //--- Helper fcn. to get the layers/disks for a seed
0188 
0189 std::pair<unsigned int, unsigned int> TrackletConfigBuilder::seedLayers(unsigned int iSeed) {
0190   return std::pair<unsigned int, unsigned int>(settings_.seedlayers(0, iSeed), settings_.seedlayers(1, iSeed));
0191 }
0192 
0193 //--- Method to initialize the regions and VM in each layer
0194 
0195 void TrackletConfigBuilder::initGeom() {
0196   for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0197     double dphi = dphisectorHG_ / NRegions_[ilayer];
0198     for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
0199       std::vector<std::pair<unsigned int, unsigned int> > emptyVec;
0200       projections_[ilayer].push_back(emptyVec);
0201       // FIX: sector doesn't have hourglass shape
0202       double phimin = dphi * iReg;
0203       double phimax = phimin + dphi;
0204       std::pair<double, double> tmp(phimin, phimax);
0205       allStubs_[ilayer].push_back(tmp);
0206       double dphiVM = dphi / NVMME_[ilayer];
0207       for (unsigned int iVM = 0; iVM < NVMME_[ilayer]; iVM++) {
0208         double phivmmin = phimin + iVM * dphiVM;
0209         double phivmmax = phivmmin + dphiVM;
0210         std::pair<double, double> tmp(phivmmin, phivmmax);
0211         VMStubsME_[ilayer].push_back(tmp);
0212       }
0213     }
0214   }
0215   for (unsigned int iseed = 0; iseed < N_SEED_PROMPT; iseed++) {
0216     unsigned int l1 = seedLayers(iseed).first;
0217     unsigned int l2 = seedLayers(iseed).second;
0218     unsigned int nVM1 = NVMTE_[iseed].first;
0219     unsigned int nVM2 = NVMTE_[iseed].second;
0220     double dphiVM = dphisectorHG_ / (nVM1 * NRegions_[l1]);
0221     for (unsigned int iVM = 0; iVM < nVM1 * NRegions_[l1]; iVM++) {
0222       double phivmmin = iVM * dphiVM;
0223       double phivmmax = phivmmin + dphiVM;
0224       std::pair<double, double> tmp(phivmmin, phivmmax);
0225       VMStubsTE_[iseed].first.push_back(tmp);
0226     }
0227     dphiVM = dphisectorHG_ / (nVM2 * NRegions_[l2]);
0228     for (unsigned int iVM = 0; iVM < nVM2 * NRegions_[l2]; iVM++) {
0229       double phivmmin = iVM * dphiVM;
0230       double phivmmax = phivmmin + dphiVM;
0231       std::pair<double, double> tmp(phivmmin, phivmmax);
0232       VMStubsTE_[iseed].second.push_back(tmp);
0233     }
0234   }
0235 }
0236 
0237 //--- Helper fcn to get the radii of the two layers in a seed
0238 
0239 std::pair<double, double> TrackletConfigBuilder::seedRadii(unsigned int iseed) {
0240   std::pair<unsigned int, unsigned int> seedlayers = seedLayers(iseed);
0241 
0242   unsigned int l1 = seedlayers.first;
0243   unsigned int l2 = seedlayers.second;
0244 
0245   double r1, r2;
0246 
0247   if (iseed < 4) {  //barrel seeding
0248     r1 = rmean_[l1];
0249     r2 = rmean_[l2];
0250   } else if (iseed < 6) {   //disk seeding
0251     r1 = rmean_[0] + 40.0;  //FIX: Somewhat of a hack - but allows finding all the regions
0252     //when projecting to L1
0253     r2 = r1 * zmean_[l2 - 6] / zmean_[l1 - 6];
0254   } else {  //overlap seeding
0255     r1 = rmean_[l1];
0256     r2 = r1 * zmean_[l2 - 6] / zlength_;
0257   }
0258 
0259   return std::pair<double, double>(r1, r2);
0260 }
0261 
0262 //--- Helper function to determine if a pair of VM memories form valid TE
0263 
0264 bool TrackletConfigBuilder::validTEPair(unsigned int iseed, unsigned int iTE1, unsigned int iTE2) {
0265   double rinvmin = 999.9;
0266   double rinvmax = -999.9;
0267 
0268   double phi1[2] = {VMStubsTE_[iseed].first[iTE1].first, VMStubsTE_[iseed].first[iTE1].second};
0269   double phi2[2] = {VMStubsTE_[iseed].second[iTE2].first, VMStubsTE_[iseed].second[iTE2].second};
0270 
0271   std::pair<double, double> seedradii = seedRadii(iseed);
0272 
0273   for (unsigned int i1 = 0; i1 < 2; i1++) {
0274     for (unsigned int i2 = 0; i2 < 2; i2++) {
0275       double arinv = rinv(seedradii.first, phi1[i1], seedradii.second, phi2[i2]);
0276       if (arinv < rinvmin)
0277         rinvmin = arinv;
0278       if (arinv > rinvmax)
0279         rinvmax = arinv;
0280     }
0281   }
0282 
0283   if (rinvmin > rinvmax_)
0284     return false;
0285   if (rinvmax < -rinvmax_)
0286     return false;
0287 
0288   return true;
0289 }
0290 
0291 //--- Builds the list of TE for each seeding combination
0292 
0293 void TrackletConfigBuilder::buildTE() {
0294   for (unsigned int iseed = 0; iseed < N_SEED_PROMPT; iseed++) {
0295     for (unsigned int i1 = 0; i1 < VMStubsTE_[iseed].first.size(); i1++) {
0296       for (unsigned int i2 = 0; i2 < VMStubsTE_[iseed].second.size(); i2++) {
0297         if (validTEPair(iseed, i1, i2)) {
0298           std::pair<unsigned int, unsigned int> tmp(i1, i2);
0299           // Contains pairs of indices of all valid VM pairs in seeding layers
0300           TE_[iseed].push_back(tmp);
0301         }
0302       }
0303     }
0304   }
0305 }
0306 
0307 //--- Builds the lists of TC for each seeding combination
0308 
0309 void TrackletConfigBuilder::buildTC() {
0310   for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
0311     unsigned int nTC = NTC_[iSeed];
0312     std::vector<std::pair<unsigned int, unsigned int> >& TEs = TE_[iSeed];
0313     std::vector<std::vector<unsigned int> >& TCs = TC_[iSeed];
0314 
0315     //Very naive method to group TEs in TC
0316 
0317     double invnTC = nTC * (1.0 / TEs.size());
0318 
0319     for (unsigned int iTE = 0; iTE < TEs.size(); iTE++) {
0320       int iTC = invnTC * iTE;
0321       assert(iTC < (int)nTC);
0322       if (iTC >= (int)TCs.size()) {
0323         std::vector<unsigned int> tmp;
0324         tmp.push_back(iTE);
0325         TCs.push_back(tmp);
0326       } else {
0327         TCs[iTC].push_back(iTE);
0328       }
0329     }
0330   }
0331 }
0332 
0333 //--- Helper fcn to return the phi range of a projection of a tracklet from a TC
0334 
0335 std::pair<double, double> TrackletConfigBuilder::seedPhiRange(double rproj, unsigned int iSeed, unsigned int iTC) {
0336   std::vector<std::vector<unsigned int> >& TCs = TC_[iSeed];
0337 
0338   std::pair<double, double> seedradii = seedRadii(iSeed);
0339 
0340   double phimin = 999.0;
0341   double phimax = -999.0;
0342   for (unsigned int iTE = 0; iTE < TCs[iTC].size(); iTE++) {
0343     unsigned int theTE = TCs[iTC][iTE];
0344     unsigned int l1TE = TE_[iSeed][theTE].first;
0345     unsigned int l2TE = TE_[iSeed][theTE].second;
0346     double phi1[2] = {VMStubsTE_[iSeed].first[l1TE].first, VMStubsTE_[iSeed].first[l1TE].second};
0347     double phi2[2] = {VMStubsTE_[iSeed].second[l2TE].first, VMStubsTE_[iSeed].second[l2TE].second};
0348     for (unsigned int i1 = 0; i1 < 2; i1++) {
0349       for (unsigned int i2 = 0; i2 < 2; i2++) {
0350         double aphi = phi(seedradii.first, phi1[i1], seedradii.second, phi2[i2], rproj);
0351         if (aphi < phimin)
0352           phimin = aphi;
0353         if (aphi > phimax)
0354           phimax = aphi;
0355       }
0356     }
0357   }
0358   return std::pair<double, double>(phimin, phimax);
0359 }
0360 
0361 //--- Finds the projections needed for each seeding combination
0362 
0363 void TrackletConfigBuilder::buildProjections() {
0364   set<string> emptyProjStandard = {
0365       "TPROJ_L1L2H_L3PHIB", "TPROJ_L1L2E_L3PHIC", "TPROJ_L1L2K_L3PHIC", "TPROJ_L1L2H_L3PHID", "TPROJ_L1L2F_L5PHIA",
0366       "TPROJ_L1L2G_L5PHID", "TPROJ_L1L2A_L6PHIA", "TPROJ_L1L2J_L6PHIB", "TPROJ_L1L2C_L6PHIC", "TPROJ_L1L2L_L6PHID",
0367       "TPROJ_L3L4D_D1PHIB", "TPROJ_L2L3A_D1PHIC", "TPROJ_L3L4A_D1PHIC", "TPROJ_L1L2G_D2PHIA", "TPROJ_L1D1D_D2PHIA",
0368       "TPROJ_L1D1E_D2PHIA", "TPROJ_L1L2J_D2PHIB", "TPROJ_L3L4D_D2PHIB", "TPROJ_L1D1A_D2PHIB", "TPROJ_L1D1F_D2PHIB",
0369       "TPROJ_L1D1G_D2PHIB", "TPROJ_L1L2C_D2PHIC", "TPROJ_L2L3A_D2PHIC", "TPROJ_L3L4A_D2PHIC", "TPROJ_L1D1B_D2PHIC",
0370       "TPROJ_L1D1C_D2PHIC", "TPROJ_L1D1H_D2PHIC", "TPROJ_L2D1A_D2PHIC", "TPROJ_L1L2F_D2PHID", "TPROJ_L1D1D_D2PHID",
0371       "TPROJ_L1D1E_D2PHID", "TPROJ_L1L2G_D3PHIA", "TPROJ_L1D1D_D3PHIA", "TPROJ_L1D1E_D3PHIA", "TPROJ_L1L2J_D3PHIB",
0372       "TPROJ_L1D1A_D3PHIB", "TPROJ_L1D1F_D3PHIB", "TPROJ_L1D1G_D3PHIB", "TPROJ_L1L2C_D3PHIC", "TPROJ_L2L3A_D3PHIC",
0373       "TPROJ_L1D1B_D3PHIC", "TPROJ_L1D1C_D3PHIC", "TPROJ_L1D1H_D3PHIC", "TPROJ_L2D1A_D3PHIC", "TPROJ_L1L2F_D3PHID",
0374       "TPROJ_L1D1D_D3PHID", "TPROJ_L1D1E_D3PHID", "TPROJ_L1L2G_D4PHIA", "TPROJ_L1D1D_D4PHIA", "TPROJ_L1D1E_D4PHIA",
0375       "TPROJ_L1L2J_D4PHIB", "TPROJ_L1D1G_D4PHIB", "TPROJ_L1L2C_D4PHIC", "TPROJ_L2L3A_D4PHIC", "TPROJ_L1D1B_D4PHIC",
0376       "TPROJ_L2D1A_D4PHIC", "TPROJ_L1L2F_D4PHID", "TPROJ_L1D1D_D4PHID", "TPROJ_L1D1E_D5PHIA", "TPROJ_L1D1G_D5PHIB",
0377       "TPROJ_L1D1B_D5PHIC", "TPROJ_L1D1D_D5PHID"};
0378 
0379   set<string> emptyProjCombined = {
0380       "TPROJ_L1L2J_L6PHIB", "TPROJ_L1L2C_L6PHIC", "TPROJ_L1L2G_D1PHIA", "TPROJ_L1L2J_D1PHIB", "TPROJ_L2L3D_D1PHIB",
0381       "TPROJ_L3L4D_D1PHIB", "TPROJ_L1L2C_D1PHIC", "TPROJ_L2L3A_D1PHIC", "TPROJ_L3L4A_D1PHIC", "TPROJ_L1L2F_D1PHID",
0382       "TPROJ_L1L2G_D2PHIA", "TPROJ_L1D1E_D2PHIA", "TPROJ_L1L2J_D2PHIB", "TPROJ_L2L3D_D2PHIB", "TPROJ_L3L4D_D2PHIB",
0383       "TPROJ_L1D1G_D2PHIB", "TPROJ_L1L2C_D2PHIC", "TPROJ_L2L3A_D2PHIC", "TPROJ_L3L4A_D2PHIC", "TPROJ_L1D1B_D2PHIC",
0384       "TPROJ_L2D1A_D2PHIC", "TPROJ_L1L2F_D2PHID", "TPROJ_L1D1D_D2PHID", "TPROJ_L1L2G_D3PHIA", "TPROJ_L1D1E_D3PHIA",
0385       "TPROJ_L1L2J_D3PHIB", "TPROJ_L2L3D_D3PHIB", "TPROJ_L1D1G_D3PHIB", "TPROJ_L1L2C_D3PHIC", "TPROJ_L2L3A_D3PHIC",
0386       "TPROJ_L1D1B_D3PHIC", "TPROJ_L2D1A_D3PHIC", "TPROJ_L1L2F_D3PHID", "TPROJ_L1D1D_D3PHID", "TPROJ_L1L2G_D4PHIA",
0387       "TPROJ_L1D1E_D4PHIA", "TPROJ_L1L2J_D4PHIB", "TPROJ_L2L3D_D4PHIB", "TPROJ_L1D1G_D4PHIB", "TPROJ_L1L2C_D4PHIC",
0388       "TPROJ_L2L3A_D4PHIC", "TPROJ_L1D1B_D4PHIC", "TPROJ_L2D1A_D4PHIC", "TPROJ_L1L2F_D4PHID", "TPROJ_L1D1D_D4PHID",
0389       "TPROJ_L1D1E_D5PHIA", "TPROJ_L1D1G_D5PHIB", "TPROJ_L1D1B_D5PHIC", "TPROJ_L1D1D_D5PHID"};
0390 
0391   for (unsigned int iseed = 0; iseed < N_SEED_PROMPT; iseed++) {
0392     std::vector<std::vector<unsigned int> >& TCs = TC_[iseed];
0393 
0394     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0395       if (matchport_[iseed][ilayer] == -1)
0396         continue;
0397       for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
0398         for (unsigned int iTC = 0; iTC < TCs.size(); iTC++) {
0399           double rproj = rmaxdisk_;
0400           if (ilayer < 6)
0401             rproj = rmean_[ilayer];
0402           std::pair<double, double> phiRange = seedPhiRange(rproj, iseed, iTC);
0403           if (phiRange.first < allStubs_[ilayer][iReg].second && phiRange.second > allStubs_[ilayer][iReg].first) {
0404             std::pair<unsigned int, unsigned int> tmp(iseed, iTC);  //seedindex and TC
0405             string projName = TPROJName(iseed, iTC, ilayer, iReg);
0406             if (combinedmodules_) {
0407               if (emptyProjCombined.find(projName) == emptyProjCombined.end()) {
0408                 projections_[ilayer][iReg].push_back(tmp);
0409               }
0410             } else {
0411               if (emptyProjStandard.find(projName) == emptyProjStandard.end()) {
0412                 projections_[ilayer][iReg].push_back(tmp);
0413               }
0414             }
0415           }
0416         }
0417       }
0418     }
0419   }
0420 }
0421 
0422 //--- Helper function to calculate the phi position of a seed at radius r that is formed
0423 //--- by two stubs at (r1,phi1) and (r2, phi2)
0424 
0425 double TrackletConfigBuilder::phi(double r1, double phi1, double r2, double phi2, double r) {
0426   double rhoinv = rinv(r1, phi1, r2, phi2);
0427   if (std::abs(rhoinv) > rinvmax_) {
0428     rhoinv = rinvmax_ * rhoinv / std::abs(rhoinv);
0429   }
0430   return phi1 + asin(0.5 * r * rhoinv) - asin(0.5 * r1 * rhoinv);
0431 }
0432 
0433 //--- Helper function to calculate rinv for two stubs at (r1,phi1) and (r2,phi2)
0434 
0435 double TrackletConfigBuilder::rinv(double r1, double phi1, double r2, double phi2) {
0436   double deltaphi = phi1 - phi2;
0437   return 2 * sin(deltaphi) / sqrt(r2 * r2 + r1 * r1 - 2 * r1 * r2 * cos(deltaphi));
0438 }
0439 
0440 std::string TrackletConfigBuilder::iSeedStr(unsigned int iSeed) const {
0441   static std::string name[8] = {"L1L2", "L2L3", "L3L4", "L5L6", "D1D2", "D3D4", "L1D1", "L2D1"};
0442 
0443   assert(iSeed < 8);
0444   return name[iSeed];
0445 }
0446 
0447 std::string TrackletConfigBuilder::numStr(unsigned int i) {
0448   static std::string num[32] = {"1",  "2",  "3",  "4",  "5",  "6",  "7",  "8",  "9",  "10", "11",
0449                                 "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",
0450                                 "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"};
0451   assert(i < 32);
0452   return num[i];
0453 }
0454 
0455 std::string TrackletConfigBuilder::iTCStr(unsigned int iTC) const {
0456   static std::string name[12] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"};
0457 
0458   assert(iTC < 12);
0459   return name[iTC];
0460 }
0461 
0462 std::string TrackletConfigBuilder::iRegStr(unsigned int iReg, unsigned int iSeed) const {
0463   static std::string name[8] = {"A", "B", "C", "D", "E", "F", "G", "H"};
0464 
0465   static std::string nameOverlap[8] = {"X", "Y", "Z", "W", "Q", "R", "S", "T"};
0466 
0467   static std::string nameL2L3[4] = {"I", "J", "K", "L"};
0468 
0469   if (iSeed == Seed::L2L3) {
0470     assert(iReg < 4);
0471     return nameL2L3[iReg];
0472   }
0473   if (iSeed == Seed::L1D1 || iSeed == Seed::L2D1) {
0474     assert(iReg < 8);
0475     return nameOverlap[iReg];
0476   }
0477   assert(iReg < 8);
0478   return name[iReg];
0479 }
0480 
0481 std::string TrackletConfigBuilder::TCName(unsigned int iSeed, unsigned int iTC) const {
0482   if (combinedmodules_) {
0483     return "TP_" + iSeedStr(iSeed) + iTCStr(iTC);
0484   } else {
0485     return "TC_" + iSeedStr(iSeed) + iTCStr(iTC);
0486   }
0487 }
0488 
0489 std::string TrackletConfigBuilder::LayerName(unsigned int ilayer) {
0490   return ilayer < 6 ? ("L" + numStr(ilayer)) : ("D" + numStr(ilayer - 6));
0491 }
0492 
0493 std::string TrackletConfigBuilder::TPROJName(unsigned int iSeed,
0494                                              unsigned int iTC,
0495                                              unsigned int ilayer,
0496                                              unsigned int ireg) const {
0497   return "TPROJ_" + iSeedStr(iSeed) + iTCStr(iTC) + "_" + LayerName(ilayer) + "PHI" + iTCStr(ireg);
0498 }
0499 
0500 std::string TrackletConfigBuilder::PRName(unsigned int ilayer, unsigned int ireg) const {
0501   if (combinedmodules_) {
0502     return "MP_" + LayerName(ilayer) + "PHI" + iTCStr(ireg);
0503   } else {
0504     return "PR_" + LayerName(ilayer) + "PHI" + iTCStr(ireg);
0505   }
0506 }
0507 
0508 void TrackletConfigBuilder::writeProjectionMemories(std::ostream& os, std::ostream& memories, std::ostream&) {
0509   // Each TC (e.g. TC_L1L2D) writes a projection memory (TPROJ) for each layer the seed projects to,
0510   // with name indicating the TC and which layer & phi region it projects to (e.g. TPROJ_L1L2D_L3PHIA).
0511   //
0512   // Each PR (e.g. PR_L3PHIA) reads all TPROJ memories for the given layer & phi region.
0513 
0514   for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0515     for (unsigned int ireg = 0; ireg < projections_[ilayer].size(); ireg++) {
0516       for (unsigned int imem = 0; imem < projections_[ilayer][ireg].size(); imem++) {
0517         unsigned int iSeed = projections_[ilayer][ireg][imem].first;
0518         unsigned int iTC = projections_[ilayer][ireg][imem].second;
0519 
0520         memories << "TrackletProjections: " + TPROJName(iSeed, iTC, ilayer, ireg) + " [54]" << std::endl;
0521 
0522         os << TPROJName(iSeed, iTC, ilayer, ireg) << " input=> " << TCName(iSeed, iTC) << ".projout"
0523            << LayerName(ilayer) << "PHI" << iTCStr(ireg) << " output=> " << PRName(ilayer, ireg) << ".projin"
0524            << std::endl;
0525       }
0526     }
0527   }
0528 }
0529 
0530 std::string TrackletConfigBuilder::SPName(unsigned int l1,
0531                                           unsigned int ireg1,
0532                                           unsigned int ivm1,
0533                                           unsigned int l2,
0534                                           unsigned int ireg2,
0535                                           unsigned int ivm2,
0536                                           unsigned int iseed) const {
0537   return "SP_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" +
0538          iRegStr(ireg2, iseed) + numStr(ivm2);
0539 }
0540 
0541 std::string TrackletConfigBuilder::SPDName(unsigned int l1,
0542                                            unsigned int ireg1,
0543                                            unsigned int ivm1,
0544                                            unsigned int l2,
0545                                            unsigned int ireg2,
0546                                            unsigned int ivm2,
0547                                            unsigned int l3,
0548                                            unsigned int ireg3,
0549                                            unsigned int ivm3,
0550                                            unsigned int iseed) const {
0551   return "SPD_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" +
0552          iRegStr(ireg2, iseed) + numStr(ivm2) + "_" + LayerName(l3) + "PHI" + iRegStr(ireg3, iseed) + numStr(ivm3);
0553 }
0554 
0555 std::string TrackletConfigBuilder::TEName(unsigned int l1,
0556                                           unsigned int ireg1,
0557                                           unsigned int ivm1,
0558                                           unsigned int l2,
0559                                           unsigned int ireg2,
0560                                           unsigned int ivm2,
0561                                           unsigned int iseed) const {
0562   return "TE_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" +
0563          iRegStr(ireg2, iseed) + numStr(ivm2);
0564 }
0565 
0566 std::string TrackletConfigBuilder::TEDName(unsigned int l1,
0567                                            unsigned int ireg1,
0568                                            unsigned int ivm1,
0569                                            unsigned int l2,
0570                                            unsigned int ireg2,
0571                                            unsigned int ivm2,
0572                                            unsigned int iseed) const {
0573   return "TED_" + LayerName(l1) + "PHI" + iRegStr(ireg1, iseed) + numStr(ivm1) + "_" + LayerName(l2) + "PHI" +
0574          iRegStr(ireg2, iseed) + numStr(ivm2);
0575 }
0576 
0577 std::string TrackletConfigBuilder::TParName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) const {
0578   return "TPAR_" + LayerName(l1) + LayerName(l2) + LayerName(l3) + iTCStr(itc);
0579 }
0580 
0581 std::string TrackletConfigBuilder::TCDName(unsigned int l1, unsigned int l2, unsigned int l3, unsigned int itc) const {
0582   return "TCD_" + LayerName(l1) + LayerName(l2) + LayerName(l3) + iTCStr(itc);
0583 }
0584 
0585 std::string TrackletConfigBuilder::TPROJName(unsigned int l1,
0586                                              unsigned int l2,
0587                                              unsigned int l3,
0588                                              unsigned int itc,
0589                                              unsigned int projlayer,
0590                                              unsigned int projreg) const {
0591   return "TPROJ_" + LayerName(l1) + LayerName(l2) + LayerName(l3) + iTCStr(itc) + "_" + LayerName(projlayer) + "PHI" +
0592          iTCStr(projreg);
0593 }
0594 
0595 std::string TrackletConfigBuilder::FTName(unsigned int l1, unsigned int l2, unsigned int l3) const {
0596   return "FT_" + LayerName(l1) + LayerName(l2) + LayerName(l3);
0597 }
0598 
0599 std::string TrackletConfigBuilder::TREName(unsigned int l1,
0600                                            unsigned int ireg1,
0601                                            unsigned int l2,
0602                                            unsigned int ireg2,
0603                                            unsigned int iseed,
0604                                            unsigned int count) const {
0605   return "TRE_" + LayerName(l1) + iRegStr(ireg1, iseed) + LayerName(l2) + iRegStr(ireg2, iseed) + "_" + numStr(count);
0606 }
0607 
0608 std::string TrackletConfigBuilder::STName(unsigned int l1,
0609                                           unsigned int ireg1,
0610                                           unsigned int l2,
0611                                           unsigned int ireg2,
0612                                           unsigned int l3,
0613                                           unsigned int ireg3,
0614                                           unsigned int iseed,
0615                                           unsigned int count) const {
0616   return "ST_" + LayerName(l1) + iRegStr(ireg1, iseed) + LayerName(l2) + iRegStr(ireg2, iseed) + "_" + LayerName(l3) +
0617          iRegStr(ireg3, iseed) + "_" + numStr(count);
0618 }
0619 
0620 void TrackletConfigBuilder::writeSPMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
0621   // Each TE reads one VM in two seed layers, finds stub pairs & writes to a StubPair ("SP") memory.
0622   //
0623   // Each TC reads several StubPair (SP) memories, each containing a pair of VMs of two seeding layers.
0624   // Several TC are created for each layer pair, and the SP distributed between them.
0625   // If TC name is TC_L1L2C, "C" indicates this is the 3rd TC in L1L2.
0626 
0627   if (combinedmodules_)
0628     return;
0629 
0630   for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
0631     for (unsigned int iTC = 0; iTC < TC_[iSeed].size(); iTC++) {
0632       for (unsigned int iTE = 0; iTE < TC_[iSeed][iTC].size(); iTE++) {
0633         unsigned int theTE = TC_[iSeed][iTC][iTE];
0634 
0635         unsigned int TE1 = TE_[iSeed][theTE].first;
0636         unsigned int TE2 = TE_[iSeed][theTE].second;
0637 
0638         unsigned int l1 = seedLayers(iSeed).first;
0639         unsigned int l2 = seedLayers(iSeed).second;
0640 
0641         memories << "StubPairs: "
0642                  << SPName(l1, TE1 / NVMTE_[iSeed].first, TE1, l2, TE2 / NVMTE_[iSeed].second, TE2, iSeed) << " [12]"
0643                  << std::endl;
0644         modules << "TrackletEngine: "
0645                 << TEName(l1, TE1 / NVMTE_[iSeed].first, TE1, l2, TE2 / NVMTE_[iSeed].second, TE2, iSeed) << std::endl;
0646 
0647         os << SPName(l1, TE1 / NVMTE_[iSeed].first, TE1, l2, TE2 / NVMTE_[iSeed].second, TE2, iSeed) << " input=> "
0648            << TEName(l1, TE1 / NVMTE_[iSeed].first, TE1, l2, TE2 / NVMTE_[iSeed].second, TE2, iSeed)
0649            << ".stubpairout output=> " << TCName(iSeed, iTC) << ".stubpairin" << std::endl;
0650       }
0651     }
0652   }
0653 }
0654 
0655 void TrackletConfigBuilder::writeSPDMemories(std::ostream& wires, std::ostream& memories, std::ostream& modules) {
0656   // Similar to writeSPMemories, but for displaced (=extended) tracking,
0657   // with seeds based on triplets of layers.
0658 
0659   if (!extended_)
0660     return;
0661 
0662   vector<string> stubTriplets[N_SEED];
0663 
0664   for (unsigned int iSeed = N_SEED_PROMPT; iSeed < N_SEED; iSeed++) {
0665     int layerdisk1 = settings_.seedlayers(0, iSeed);
0666     int layerdisk2 = settings_.seedlayers(1, iSeed);
0667     int layerdisk3 = settings_.seedlayers(2, iSeed);
0668 
0669     unsigned int nallstub1 = settings_.nallstubs(layerdisk1);
0670     unsigned int nallstub2 = settings_.nallstubs(layerdisk2);
0671     unsigned int nallstub3 = settings_.nallstubs(layerdisk3);
0672 
0673     unsigned int nvm1 = settings_.nvmte(0, iSeed);
0674     unsigned int nvm2 = settings_.nvmte(1, iSeed);
0675     unsigned int nvm3 = settings_.nvmte(2, iSeed);
0676 
0677     int count = 0;
0678     for (unsigned int ireg1 = 0; ireg1 < nallstub1; ireg1++) {
0679       for (unsigned int ireg2 = 0; ireg2 < nallstub2; ireg2++) {
0680         for (unsigned int ireg3 = 0; ireg3 < nallstub3; ireg3++) {
0681           count++;
0682           memories << "StubTriplets: " << STName(layerdisk1, ireg1, layerdisk2, ireg2, layerdisk3, ireg3, iSeed, count)
0683                    << " [18]" << std::endl;
0684           stubTriplets[iSeed].push_back(STName(layerdisk1, ireg1, layerdisk2, ireg2, layerdisk3, ireg3, iSeed, count));
0685         }
0686       }
0687     }
0688 
0689     for (unsigned int ireg1 = 0; ireg1 < nallstub1; ireg1++) {
0690       for (unsigned int ivm1 = 0; ivm1 < nvm1; ivm1++) {
0691         for (unsigned int ireg2 = 0; ireg2 < nallstub2; ireg2++) {
0692           for (unsigned int ivm2 = 0; ivm2 < nvm2; ivm2++) {
0693             int count = 0;
0694 
0695             modules << "TrackletEngineDisplaced: "
0696                     << TEDName(layerdisk1, ireg1, ireg1 * nvm1 + ivm1, layerdisk2, ireg2, ireg2 * nvm2 + ivm2, iSeed)
0697                     << std::endl;
0698 
0699             for (unsigned int ireg3 = 0; ireg3 < nallstub3; ireg3++) {
0700               for (unsigned int ivm3 = 0; ivm3 < nvm3; ivm3++) {
0701                 count++;
0702 
0703                 memories << "StubPairsDisplaced: "
0704                          << SPDName(layerdisk1,
0705                                     ireg1,
0706                                     ireg1 * nvm1 + ivm1,
0707                                     layerdisk2,
0708                                     ireg2,
0709                                     ireg2 * nvm2 + ivm2,
0710                                     layerdisk3,
0711                                     ireg3,
0712                                     ireg3 * nvm3 + ivm3,
0713                                     iSeed)
0714                          << " [12]" << std::endl;
0715 
0716                 modules << "TripletEngine: " << TREName(layerdisk1, ireg1, layerdisk2, ireg2, iSeed, count)
0717                         << std::endl;
0718 
0719                 wires << SPDName(layerdisk1,
0720                                  ireg1,
0721                                  ireg1 * nvm1 + ivm1,
0722                                  layerdisk2,
0723                                  ireg2,
0724                                  ireg2 * nvm2 + ivm2,
0725                                  layerdisk3,
0726                                  ireg3,
0727                                  ireg3 * nvm3 + ivm3,
0728                                  iSeed)
0729                       << " input=> "
0730                       << TEDName(layerdisk1, ireg1, ireg1 * nvm1 + ivm1, layerdisk2, ireg2, ireg2 * nvm2 + ivm2, iSeed)
0731                       << ".stubpairout output=> " << TREName(layerdisk1, ireg1, layerdisk2, ireg2, iSeed, count)
0732                       << ".stubpair"
0733                       << "1"
0734                       << "in" << std::endl;
0735               }
0736             }
0737           }
0738         }
0739       }
0740     }
0741 
0742     unsigned int nTC = 10;
0743     for (unsigned int itc = 0; itc < nTC; itc++) {
0744       for (int iproj = 0; iproj < 4; iproj++) {
0745         int ilay = settings_.projlayers(iSeed, iproj);
0746         if (ilay > 0) {
0747           unsigned int nallstub = settings_.nallstubs(ilay - 1);
0748           for (unsigned int ireg = 0; ireg < nallstub; ireg++) {
0749             memories << "TrackletProjections: " << TPROJName(layerdisk1, layerdisk2, layerdisk3, itc, ilay - 1, ireg)
0750                      << " [54]" << std::endl;
0751           }
0752         }
0753 
0754         int idisk = settings_.projdisks(iSeed, iproj);
0755         if (idisk > 0) {
0756           unsigned int nallstub = settings_.nallstubs(idisk + 5);
0757           for (unsigned int ireg = 0; ireg < nallstub; ireg++) {
0758             memories << "TrackletProjections: " << TPROJName(layerdisk1, layerdisk2, layerdisk3, itc, idisk + 5, ireg)
0759                      << " [54]" << std::endl;
0760 
0761             wires << TPROJName(layerdisk1, layerdisk2, layerdisk3, itc, idisk + 5, ireg) << " input=> "
0762                   << TCDName(layerdisk1, layerdisk2, layerdisk3, itc) << ".projout" << LayerName(idisk + 1) << "PHI"
0763                   << iTCStr(ireg) << " output=> "
0764                   << "PR_" << LayerName(idisk + 1) << "PHI" << iTCStr(ireg) << ".projin" << std::endl;
0765           }
0766         }
0767       }
0768 
0769       memories << "TrackletParameters: " << TParName(layerdisk1, layerdisk2, layerdisk3, itc) << " [56]" << std::endl;
0770 
0771       modules << "TrackletCalculatorDisplaced: " << TCDName(layerdisk1, layerdisk2, layerdisk3, itc) << std::endl;
0772     }
0773 
0774     unsigned int nST = stubTriplets[iSeed].size();
0775     for (unsigned int iST = 0; iST < nST; iST++) {
0776       unsigned int iTC = (iST * nTC) / nST;
0777       assert(iTC < nTC);
0778       string stname = stubTriplets[iSeed][iST];
0779       string trename = "TRE_" + stname.substr(3, 6) + "_";
0780       unsigned int stlen = stname.size();
0781       if (stname[stlen - 2] == '_')
0782         trename += stname.substr(stlen - 1, 1);
0783       if (stname[stlen - 3] == '_')
0784         trename += stname.substr(stlen - 2, 2);
0785       wires << stname << " input=> " << trename << ".stubtripout output=> "
0786             << TCDName(layerdisk1, layerdisk2, layerdisk3, iTC) << ".stubtriplet" << ((iST * nTC) % nST) << "in"
0787             << std::endl;
0788     }
0789 
0790     modules << "FitTrack: " << FTName(layerdisk1, layerdisk2, layerdisk3) << std::endl;
0791   }
0792 }
0793 
0794 void TrackletConfigBuilder::writeAPMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
0795   // The AllProjection memories (e.g. AP_L2PHIA) contain the intercept point of the projection to
0796   // a layer. Each is written by one PR module of similar name (e.g. PR_L2PHIA), and read by
0797   // a MC (e.g. MC_L2PHIA).
0798 
0799   if (combinedmodules_)
0800     return;
0801 
0802   for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0803     for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
0804       memories << "AllProj: AP_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << " [56]" << std::endl;
0805       modules << "ProjectionRouter: PR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << std::endl;
0806 
0807       os << "AP_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << " input=> PR_" << LayerName(ilayer) << "PHI"
0808          << iTCStr(iReg) << ".allprojout output=> MC_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".allprojin"
0809          << std::endl;
0810     }
0811   }
0812 }
0813 
0814 void TrackletConfigBuilder::writeCMMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
0815   // The CandidateMatch memory (e.g. CM_L1PHIA1) are each written by ME module of similar name
0816   // (e.g. ME_L1PHIA1) and contain indices of matching (tracklet projections,stubs) in the specified
0817   // VM region.
0818   // All CM memories in a given phi region (e.g. L1PHIA) are read by a MC module (e.g. MC_L1PHIA) that
0819   // does more precise matching.
0820 
0821   if (combinedmodules_)
0822     return;
0823 
0824   for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0825     for (unsigned int iME = 0; iME < NVMME_[ilayer] * NRegions_[ilayer]; iME++) {
0826       memories << "CandidateMatch: CM_" << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << iME + 1
0827                << " [12]" << std::endl;
0828       modules << "MatchEngine: ME_" << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << iME + 1
0829               << std::endl;
0830 
0831       os << "CM_" << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << iME + 1 << " input=> ME_"
0832          << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << iME + 1 << ".matchout output=> MC_"
0833          << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << ".matchin" << std::endl;
0834     }
0835   }
0836 }
0837 
0838 void TrackletConfigBuilder::writeVMPROJMemories(std::ostream& os, std::ostream& memories, std::ostream&) {
0839   // The VMPROJ memories (e.g. VMPROJ_L2PHIA1) written by a PR module each correspond to projections to
0840   // a single VM region in a layer. Each is filled by the PR using all projections (TPROJ) to this VM
0841   // from different seeding layers.
0842   //
0843   // Each VMPROJ memory is read by a ME module, which matches the projection to stubs.
0844 
0845   if (combinedmodules_)
0846     return;
0847 
0848   for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0849     for (unsigned int iME = 0; iME < NVMME_[ilayer] * NRegions_[ilayer]; iME++) {
0850       memories << "VMProjections: VMPROJ_" << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << iME + 1
0851                << " [13]" << std::endl;
0852 
0853       os << "VMPROJ_" << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << iME + 1 << " input=> PR_"
0854          << LayerName(ilayer) << "PHI" << iTCStr(iME / NVMME_[ilayer]) << ".vmprojout"
0855          << "PHI" << iTCStr(iME / NVMME_[ilayer]) << iME + 1 << " output=> ME_" << LayerName(ilayer) << "PHI"
0856          << iTCStr(iME / NVMME_[ilayer]) << iME + 1 << ".vmprojin" << std::endl;
0857     }
0858   }
0859 }
0860 
0861 void TrackletConfigBuilder::writeFMMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
0862   // All FullMatch (e.g. FM_L2L3_L1PHIA) memories corresponding to a matches between stubs & tracklets
0863   // in a given region (e.g. L1PHIA) from all seeding layers, are written by a MC module (e.g. MC_L1PHIA).
0864   //
0865   // All FullMatch memories corresponding to a given seed pair are read by the TrackBuilder (e.g. FT_L1L2),
0866   // which checks if the track has stubs in enough layers.
0867 
0868   if (combinedmodules_) {
0869     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0870       for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
0871         modules << "MatchProcessor: MP_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << std::endl;
0872         for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
0873           if (matchport_[iSeed][ilayer] == -1)
0874             continue;
0875           memories << "FullMatch: FM_" << iSeedStr(iSeed) << "_" << LayerName(ilayer) << "PHI" << iTCStr(iReg)
0876                    << " [36]" << std::endl;
0877           os << "FM_" << iSeedStr(iSeed) << "_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << " input=> MP_"
0878              << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".matchout1 output=> FT_" << iSeedStr(iSeed)
0879              << ".fullmatch" << matchport_[iSeed][ilayer] << "in" << iReg + 1 << std::endl;
0880         }
0881       }
0882     }
0883   } else {
0884     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0885       for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
0886         modules << "MatchCalculator: MC_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << std::endl;
0887         for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
0888           if (matchport_[iSeed][ilayer] == -1)
0889             continue;
0890           memories << "FullMatch: FM_" << iSeedStr(iSeed) << "_" << LayerName(ilayer) << "PHI" << iTCStr(iReg)
0891                    << " [36]" << std::endl;
0892           os << "FM_" << iSeedStr(iSeed) << "_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << " input=> MC_"
0893              << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".matchout1 output=> FT_" << iSeedStr(iSeed)
0894              << ".fullmatch" << matchport_[iSeed][ilayer] << "in" << iReg + 1 << std::endl;
0895         }
0896       }
0897     }
0898   }
0899 }
0900 
0901 void TrackletConfigBuilder::writeASMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
0902   // Each VMR writes AllStub memories (AS) for a single phi region (e.g. PHIC),
0903   // merging data from all DTCs related to this phi region. It does so by merging data from
0904   // the IL memories written by all IRs for this phi region. The wiring map lists all
0905   // IL memories that feed (">") into a single VMR ("VMR_L1PHIC") that writes to the
0906   // an AS memory ("AS_L1PHIC").
0907   // Multiple copies of each AS memory exist where several modules in chain want to read it.
0908 
0909   if (combinedmodules_) {
0910     //First write AS memories used by MatchProcessor
0911     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0912       for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
0913         memories << "AllStubs: AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n1"
0914                  << " [42]" << std::endl;
0915         if (combinedmodules_) {
0916           modules << "VMRouterCM: VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << std::endl;
0917         } else {
0918           modules << "VMRouter: VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << std::endl;
0919         }
0920         os << "AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n1"
0921            << " input=> VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".allstubout output=> MP_"
0922            << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".allstubin" << std::endl;
0923       }
0924     }
0925 
0926     //Next write AS memories used by TrackletProcessor
0927     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
0928       for (int iReg = 0; iReg < (int)NRegions_[ilayer]; iReg++) {
0929         for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
0930           unsigned int l1 = seedLayers(iSeed).first;
0931           unsigned int l2 = seedLayers(iSeed).second;
0932 
0933           if (ilayer != l1 && ilayer != l2)
0934             continue;
0935 
0936           bool inner = ilayer == l1;
0937 
0938           for (unsigned int iTC = 0; iTC < TC_[iSeed].size(); iTC++) {
0939             int nTCReg = TC_[iSeed].size() / NRegions_[l2];
0940 
0941             int iTCReg = iTC / nTCReg;
0942 
0943             int jTCReg = iTC % nTCReg;
0944 
0945             if (ilayer == l2) {
0946               if (iTCReg != iReg)
0947                 continue;
0948             }
0949 
0950             string ext = "";
0951 
0952             if (ilayer == l1) {
0953               int ratio = NRegions_[l1] / NRegions_[l2];
0954               int min = iTCReg * ratio - 1 + jTCReg;
0955               int max = (iTCReg + 1) * ratio - (nTCReg - jTCReg - 1);
0956               if ((int)iReg < min || (int)iReg > max)
0957                 continue;
0958 
0959               if (max - min >= 2) {
0960                 ext = "M";
0961                 if (iReg == min)
0962                   ext = "R";
0963                 if (iReg == max)
0964                   ext = "L";
0965               }
0966 
0967               if (max - min == 1) {
0968                 if (nTCReg == 2) {
0969                   assert(0);
0970                   if (jTCReg == 0) {
0971                     if (iReg == min)
0972                       ext = "R";
0973                     if (iReg == max)
0974                       ext = "B";
0975                   }
0976                   if (jTCReg == 1) {
0977                     if (iReg == min)
0978                       ext = "A";
0979                     if (iReg == max)
0980                       ext = "L";
0981                   }
0982                 }
0983                 if (nTCReg == 3) {
0984                   if (jTCReg == 0) {
0985                     if (iReg == min)
0986                       ext = "A";
0987                     if (iReg == max)
0988                       ext = "F";
0989                   }
0990                   if (jTCReg == 1) {
0991                     if (iReg == min)
0992                       ext = "E";
0993                     if (iReg == max)
0994                       ext = "D";
0995                   }
0996                   if (jTCReg == 2) {
0997                     if (iReg == min)
0998                       ext = "C";
0999                     if (iReg == max)
1000                       ext = "B";
1001                   }
1002                 }
1003               }
1004               assert(!ext.empty());
1005             }
1006 
1007             if (ext.empty()) {
1008               ext = "_" + LayerName(l1) + iTCStr(iTC);
1009             }
1010 
1011             if (iSeed < 4) {  //Barrel seeding
1012               ext = "_B" + ext;
1013             } else if (iSeed > 5) {
1014               ext = "_O" + ext;
1015             } else {
1016               ext = "_D" + ext;
1017             }
1018 
1019             if (inner) {
1020               memories << "AllInnerStubs: ";
1021             } else {
1022               memories << "AllStubs: ";
1023             }
1024             memories << "AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ext << " [42]" << std::endl;
1025             os << "AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ext << " input=> VMR_" << LayerName(ilayer)
1026                << "PHI" << iTCStr(iReg) << ".all" << (inner ? "inner" : "") << "stubout output=> TP_" << iSeedStr(iSeed)
1027                << iTCStr(iTC);
1028             if (inner) {
1029               os << ".innerallstubin" << std::endl;
1030             } else {
1031               os << ".outerallstubin" << std::endl;
1032             }
1033           }
1034         }
1035       }
1036     }
1037 
1038   } else {
1039     //First write AS memories used by MatchCalculator
1040     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
1041       for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
1042         memories << "AllStubs: AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n1"
1043                  << " [42]" << std::endl;
1044         if (combinedmodules_) {
1045           modules << "VMRouterCM: VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << std::endl;
1046         } else {
1047           modules << "VMRouter: VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << std::endl;
1048         }
1049         os << "AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n1"
1050            << " input=> VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".allstubout output=> MC_"
1051            << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".allstubin" << std::endl;
1052       }
1053     }
1054 
1055     //Next write AS memories used by TrackletCalculator
1056     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
1057       for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
1058         unsigned int nmem = 1;
1059 
1060         for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
1061           unsigned int l1 = seedLayers(iSeed).first;
1062           unsigned int l2 = seedLayers(iSeed).second;
1063 
1064           if (ilayer != l1 && ilayer != l2)
1065             continue;
1066 
1067           for (unsigned int iTC = 0; iTC < TC_[iSeed].size(); iTC++) {
1068             bool used = false;
1069             // Each TC processes data from several TEs.
1070             for (unsigned int iTE = 0; iTE < TC_[iSeed][iTC].size(); iTE++) {
1071               unsigned int theTE = TC_[iSeed][iTC][iTE];
1072 
1073               unsigned int TE1 = TE_[iSeed][theTE].first;  // VM in inner/outer layer of this TE.
1074               unsigned int TE2 = TE_[iSeed][theTE].second;
1075 
1076               if (l1 == ilayer && iReg == TE1 / NVMTE_[iSeed].first)
1077                 used = true;
1078               if (l2 == ilayer && iReg == TE2 / NVMTE_[iSeed].second)
1079                 used = true;
1080             }
1081 
1082             if (used) {
1083               nmem++;  // Another copy of memory
1084               memories << "AllStubs: AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n" << nmem << " [42]"
1085                        << std::endl;
1086               os << "AS_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n" << nmem << " input=> VMR_"
1087                  << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".allstubout output=> TC_" << iSeedStr(iSeed)
1088                  << iTCStr(iTC);
1089               if (ilayer == l1) {
1090                 os << ".innerallstubin" << std::endl;
1091               } else {
1092                 os << ".outerallstubin" << std::endl;
1093               }
1094             }
1095           }
1096         }
1097       }
1098     }
1099   }
1100 }
1101 
1102 void TrackletConfigBuilder::writeVMSMemories(std::ostream& os, std::ostream& memories, std::ostream&) {
1103   // Each VMR writes to Virtual Module memories ("VMS") to be used later by the ME or TE etc.
1104   // Memory VMSTE_L1PHIC9-12 is the memory for small phi region C in L1 for the TE module.
1105   // Numbers 9-12 correspond to the 4 VMs in this phi region.
1106   //
1107   // Each TE reads one VMS memory in each seeding layer.
1108 
1109   if (combinedmodules_) {
1110     //First write VMS memories used by MatchProcessor
1111     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
1112       for (unsigned int iReg = 0; iReg < NRegions_[ilayer]; iReg++) {
1113         memories << "VMStubsME: VMSME_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n1 [18]" << std::endl;
1114         os << "VMSME_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << "n1"
1115            << " input=> VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".vmstuboutPHI" << iTCStr(iReg)
1116            << " output=> MP_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".vmstubin" << std::endl;
1117       }
1118     }
1119 
1120     //Next write VMS memories used by TrackletProcessor
1121     for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
1122       //FIXME - code could be cleaner
1123       unsigned int l1 = seedLayers(iSeed).first;
1124       unsigned int l2 = seedLayers(iSeed).second;
1125 
1126       unsigned int ilayer = seedLayers(iSeed).second;
1127 
1128       //for(unsigned int iReg=0;iReg<NRegions_[ilayer];iReg++){
1129 
1130       unsigned int nTCReg = TC_[iSeed].size() / NRegions_[l2];
1131 
1132       for (unsigned int iReg = 0; iReg < NRegions_[l2]; iReg++) {
1133         unsigned int nmem = 0;
1134         //Hack since we use same module twice
1135         if (iSeed == Seed::L2D1) {
1136           nmem = 2;
1137         }
1138 
1139         for (unsigned iTC = 0; iTC < nTCReg; iTC++) {
1140           nmem++;
1141           memories << "VMStubsTE: VMSTE_" << LayerName(ilayer) << "PHI" << iRegStr(iReg, iSeed) << "n" << nmem
1142                    << " [18]" << std::endl;
1143           os << "VMSTE_" << LayerName(ilayer) << "PHI" << iRegStr(iReg, iSeed) << "n" << nmem << " input=> VMR_"
1144              << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".vmstubout_seed_" << iSeed << " output=> TP_"
1145              << LayerName(l1) << LayerName(l2) << iTCStr(iReg * nTCReg + iTC) << ".outervmstubin" << std::endl;
1146         }
1147       }
1148     }
1149 
1150   } else {
1151     //First write VMS memories used by MatchEngine
1152     for (unsigned int ilayer = 0; ilayer < N_LAYER + N_DISK; ilayer++) {
1153       for (unsigned int iVMME = 0; iVMME < NVMME_[ilayer] * NRegions_[ilayer]; iVMME++) {
1154         unsigned int iReg = iVMME / NVMME_[ilayer];
1155         memories << "VMStubsME: VMSME_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << iVMME + 1 << "n1 [18]"
1156                  << std::endl;
1157         os << "VMSME_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << iVMME + 1 << "n1"
1158            << " input=> VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".vmstuboutMEPHI" << iTCStr(iReg)
1159            << iVMME + 1 << " output=> ME_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << iVMME + 1 << ".vmstubin"
1160            << std::endl;
1161       }
1162     }
1163 
1164     // Next write VMS memories used by TrackletEngine
1165     // Each TE processes one VM region in inner + outer seeding layers, and needs its own copy of input memories.
1166     for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
1167       for (unsigned int innerouterseed = 0; innerouterseed < 2; innerouterseed++) {
1168         //FIXME - code could be cleaner
1169         unsigned int l1 = seedLayers(iSeed).first;
1170         unsigned int l2 = seedLayers(iSeed).second;
1171 
1172         unsigned int NVMTE1 = NVMTE_[iSeed].first;
1173         unsigned int NVMTE2 = NVMTE_[iSeed].second;
1174 
1175         unsigned int ilayer = l1;
1176         unsigned int NVMTE = NVMTE1;
1177         if (innerouterseed == 1) {
1178           ilayer = l2;
1179           NVMTE = NVMTE2;
1180         }
1181 
1182         for (unsigned int iVMTE = 0; iVMTE < NVMTE * NRegions_[ilayer]; iVMTE++) {
1183           unsigned int iReg = iVMTE / NVMTE;
1184 
1185           unsigned int nmem = 0;
1186 
1187           if (iSeed == Seed::L2D1) {
1188             nmem = 4;
1189           }
1190 
1191           for (unsigned int iTE = 0; iTE < TE_[iSeed].size(); iTE++) {
1192             unsigned int TE1 = TE_[iSeed][iTE].first;  // VM region in inner/outer layer of this TE
1193             unsigned int TE2 = TE_[iSeed][iTE].second;
1194 
1195             bool used = false;
1196 
1197             if (innerouterseed == 0 && iVMTE == TE1)
1198               used = true;
1199             if (innerouterseed == 1 && iVMTE == TE2)
1200               used = true;
1201 
1202             if (!used)
1203               continue;
1204 
1205             string inorout = "I";
1206             if (innerouterseed == 1)
1207               inorout = "O";
1208 
1209             nmem++;  // Add another copy of memory.
1210             memories << "VMStubsTE: VMSTE_" << LayerName(ilayer) << "PHI" << iRegStr(iReg, iSeed) << iVMTE + 1 << "n"
1211                      << nmem << " [18]" << std::endl;
1212             os << "VMSTE_" << LayerName(ilayer) << "PHI" << iRegStr(iReg, iSeed) << iVMTE + 1 << "n" << nmem
1213                << " input=> VMR_" << LayerName(ilayer) << "PHI" << iTCStr(iReg) << ".vmstuboutTE" << inorout << "PHI"
1214                << iRegStr(iReg, iSeed) << iVMTE + 1 << " output=> TE_" << LayerName(l1) << "PHI"
1215                << iRegStr(TE1 / NVMTE1, iSeed) << TE1 + 1 << "_" << LayerName(l2) << "PHI"
1216                << iRegStr(TE2 / NVMTE2, iSeed) << TE2 + 1;
1217             if (innerouterseed == 0) {
1218               os << ".innervmstubin" << std::endl;
1219             } else {
1220               os << ".outervmstubin" << std::endl;
1221             }
1222           }
1223         }
1224       }
1225     }
1226   }
1227 }
1228 
1229 void TrackletConfigBuilder::writeTPARMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
1230   // Each TC module (e.g. TC_L1L2A) stores helix params in a single TPAR memory of similar name
1231   // (e.g. TPAR_L1L2A). The TPAR is subsequently read by the TrackBuilder (FT).
1232 
1233   if (combinedmodules_) {
1234     for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
1235       for (unsigned int iTP = 0; iTP < TC_[iSeed].size(); iTP++) {
1236         memories << "TrackletParameters: TPAR_" << iSeedStr(iSeed) << iTCStr(iTP) << " [56]" << std::endl;
1237         modules << "TrackletProcessor: TP_" << iSeedStr(iSeed) << iTCStr(iTP) << std::endl;
1238         os << "TPAR_" << iSeedStr(iSeed) << iTCStr(iTP) << " input=> TP_" << iSeedStr(iSeed) << iTCStr(iTP)
1239            << ".trackpar output=> FT_" << iSeedStr(iSeed) << ".tparin" << std::endl;
1240       }
1241     }
1242   } else {
1243     for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
1244       for (unsigned int iTC = 0; iTC < TC_[iSeed].size(); iTC++) {
1245         memories << "TrackletParameters: TPAR_" << iSeedStr(iSeed) << iTCStr(iTC) << " [56]" << std::endl;
1246         modules << "TrackletCalculator: TC_" << iSeedStr(iSeed) << iTCStr(iTC) << std::endl;
1247         os << "TPAR_" << iSeedStr(iSeed) << iTCStr(iTC) << " input=> TC_" << iSeedStr(iSeed) << iTCStr(iTC)
1248            << ".trackpar output=> FT_" << iSeedStr(iSeed) << ".tparin" << std::endl;
1249       }
1250     }
1251   }
1252 }
1253 
1254 void TrackletConfigBuilder::writeTFMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
1255   for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
1256     memories << "TrackFit: TF_" << iSeedStr(iSeed) << " [126]" << std::endl;
1257     modules << "FitTrack: FT_" << iSeedStr(iSeed) << std::endl;
1258     os << "TF_" << iSeedStr(iSeed) << " input=> FT_" << iSeedStr(iSeed) << ".trackout output=> PD.trackin" << std::endl;
1259   }
1260 }
1261 
1262 void TrackletConfigBuilder::writeCTMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
1263   modules << "PurgeDuplicate: PD" << std::endl;
1264 
1265   for (unsigned int iSeed = 0; iSeed < N_SEED_PROMPT; iSeed++) {
1266     memories << "CleanTrack: CT_" << iSeedStr(iSeed) << " [126]" << std::endl;
1267     os << "CT_" << iSeedStr(iSeed) << " input=> PD.trackout output=>" << std::endl;
1268   }
1269 }
1270 
1271 void TrackletConfigBuilder::writeILMemories(std::ostream& os, std::ostream& memories, std::ostream& modules) {
1272   // Each Input Router (IR) reads stubs from one DTC (e.g. PS10G_1) & sends them
1273   // to 4-8 InputLink (IL) memories (labelled PHIA-PHIH), each corresponding to a small
1274   // phi region of a nonant, for each tracklet layer (L1-L6 or D1-D5) that the DTC
1275   // reads. The InputLink memories have names such as IL_L1PHIC_PS10G_1 to reflect this.
1276 
1277   string olddtc = "";
1278   for (const DTCinfo& info : vecDTCinfo_) {
1279     string dtcname = info.name;
1280     if (olddtc != dtcname) {
1281       // Write one entry per DTC, with each DTC connected to one IR.
1282       modules << "InputRouter: IR_" << dtcname << "_A" << std::endl;
1283       modules << "InputRouter: IR_" << dtcname << "_B" << std::endl;
1284       memories << "DTCLink: DL_" << dtcname << "_A [36]" << std::endl;
1285       memories << "DTCLink: DL_" << dtcname << "_B [36]" << std::endl;
1286       os << "DL_" << dtcname << "_A"
1287          << " input=> output=> IR_" << dtcname << "_A.stubin" << std::endl;
1288       os << "DL_" << dtcname << "_B"
1289          << " input=> output=> IR_" << dtcname << "_B.stubin" << std::endl;
1290     }
1291     olddtc = dtcname;
1292   }
1293 
1294   for (const DTCinfo& info : vecDTCinfo_) {
1295     string dtcname = info.name;
1296     int layerdisk = info.layer;
1297 
1298     for (unsigned int iReg = 0; iReg < NRegions_[layerdisk]; iReg++) {
1299       //--- Ian Tomalin's proposed bug fix
1300       double phiminDTC_A = info.phimin - M_PI / N_SECTOR;  // Phi range of each DTC.
1301       double phimaxDTC_A = info.phimax - M_PI / N_SECTOR;
1302       double phiminDTC_B = info.phimin + M_PI / N_SECTOR;  // Phi range of each DTC.
1303       double phimaxDTC_B = info.phimax + M_PI / N_SECTOR;
1304       if (allStubs_[layerdisk][iReg].second > phiminDTC_A && allStubs_[layerdisk][iReg].first < phimaxDTC_A) {
1305         memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A"
1306                  << " [36]" << std::endl;
1307         os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A"
1308            << " input=> IR_" << dtcname << "_A.stubout output=> VMR_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg)
1309            << ".stubin" << std::endl;
1310       }
1311       if (allStubs_[layerdisk][iReg].second > phiminDTC_B && allStubs_[layerdisk][iReg].first < phimaxDTC_B) {
1312         memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B"
1313                  << " [36]" << std::endl;
1314         os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B"
1315            << " input=> IR_" << dtcname << "_B.stubout output=> VMR_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg)
1316            << ".stubin" << std::endl;
1317       }
1318       //--- Original (buggy) code
1319       /*
1320       double phiminDTC = info.phimin; // Phi range of each DTC.
1321       double phimaxDTC = info.phimax;
1322 
1323       if (allStubs_[layerdisk][iReg].first > phimaxDTC && allStubs_[layerdisk][iReg].second < phiminDTC) 
1324         continue;
1325 
1326       // Phi region range must be entirely contained in this DTC to keep this connection.
1327       if (allStubs_[layerdisk][iReg].second < phimaxDTC) {
1328         memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A"
1329                  << " [36]" << std::endl;
1330         os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_A"
1331            << " input=> IR_" << dtcname << "_A.stubout output=> VMR_" << LayerName(layerdisk) << "PHI"
1332            << iTCStr(iReg) << ".stubin" << std::endl;
1333       }
1334 
1335       if (allStubs_[layerdisk][iReg].first > phiminDTC) {
1336         memories << "InputLink: IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B"
1337                  << " [36]" << std::endl;
1338         os << "IL_" << LayerName(layerdisk) << "PHI" << iTCStr(iReg) << "_" << dtcname << "_B"
1339            << " input=> IR_" << dtcname << "_B.stubout output=> VMR_" << LayerName(layerdisk) << "PHI"
1340            << iTCStr(iReg) << ".stubin" << std::endl;
1341       }
1342 */
1343     }
1344   }
1345 }
1346 
1347 //--- Fill streams used to write wiring map to file
1348 
1349 void TrackletConfigBuilder::writeAll(std::ostream& wires, std::ostream& memories, std::ostream& modules) {
1350   writeILMemories(wires, memories, modules);
1351   writeASMemories(wires, memories, modules);
1352   writeVMSMemories(wires, memories, modules);
1353   writeSPMemories(wires, memories, modules);
1354   writeSPDMemories(wires, memories, modules);
1355   writeProjectionMemories(wires, memories, modules);
1356   writeTPARMemories(wires, memories, modules);
1357   writeVMPROJMemories(wires, memories, modules);
1358   writeAPMemories(wires, memories, modules);
1359   writeCMMemories(wires, memories, modules);
1360   writeFMMemories(wires, memories, modules);
1361   writeTFMemories(wires, memories, modules);
1362   writeCTMemories(wires, memories, modules);
1363 }