Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-03 00:12:16

0001 #include "L1Trigger/TrackerTFP/interface/Demonstrator.h"
0002 
0003 #include <vector>
0004 #include <set>
0005 #include <string>
0006 #include <sstream>
0007 #include <fstream>
0008 #include <numeric>
0009 
0010 namespace trackerTFP {
0011 
0012   Demonstrator::Demonstrator(const Config& iConfig, const tt::Setup* setup)
0013       : dirIPBB_(iConfig.dirIPBB_),
0014         runTime_(iConfig.runTime_),
0015         linkMappingIn_(iConfig.linkMappingIn_),
0016         linkMappingOut_(iConfig.linkMappingOut_),
0017         dirIn_(dirIPBB_ + "in.txt"),
0018         dirOut_(dirIPBB_ + "out.txt"),
0019         dirPre_(dirIPBB_ + "pre.txt"),
0020         dirDiff_(dirIPBB_ + "diff.txt"),
0021         numFrames_(setup->numFramesIOHigh()),
0022         numFramesInfra_(setup->numFramesInfra()),
0023         numRegions_(setup->numRegions()) {}
0024 
0025   // plays input through modelsim and compares result with output
0026   bool Demonstrator::analyze(const std::vector<std::vector<tt::Frame>>& input,
0027                              const std::vector<std::vector<tt::Frame>>& output) const {
0028     // default link mapping
0029     auto linkMapping =
0030         [this](const std::vector<int>& mapC, std::vector<int>& map, const std::vector<std::vector<tt::Frame>>& data) {
0031           if (mapC.empty()) {
0032             map.resize(data.size() / numRegions_);
0033             std::iota(map.begin(), map.end(), 0);
0034           } else
0035             map = mapC;
0036         };
0037     // converts input into stringstream
0038     std::stringstream ss;
0039     std::vector<int> map;
0040     linkMapping(linkMappingIn_, map, input);
0041     convert(input, ss, map);
0042     // play input through modelsim
0043     sim(ss);
0044     // converts output into stringstream
0045     map.clear();
0046     linkMapping(linkMappingOut_, map, output);
0047     convert(output, ss, map);
0048     // compares output with modelsim output
0049     return compare(ss);
0050   }
0051 
0052   // converts streams of bv into stringstream
0053   void Demonstrator::convert(const std::vector<std::vector<tt::Frame>>& bits,
0054                              std::stringstream& ss,
0055                              const std::vector<int>& mapping) const {
0056     // reset ss
0057     ss.str("");
0058     ss.clear();
0059     // number of tranceiver in a quad
0060     static constexpr int quad = 4;
0061     std::set<int> quads;
0062     for (int channel : mapping)
0063       quads.insert(channel / quad);
0064     std::vector<int> links;
0065     links.reserve(quads.size() * quad);
0066     for (int q : quads) {
0067       const int offset = q * quad;
0068       for (int c = 0; c < quad; c++)
0069         links.push_back(offset + c);
0070     }
0071     // start with header
0072     ss << header(links);
0073     int nFrame(0);
0074     // create one packet per region
0075     bool first = true;
0076     for (int region = 0; region < numRegions_; region++) {
0077       const int offset = region * mapping.size();
0078       // start with emp 6 frame gap
0079       ss << infraGap(nFrame, links.size());
0080       for (int frame = 0; frame < numFrames_; frame++) {
0081         // write one frame for all channel
0082         ss << this->frame(nFrame);
0083         for (int link : links) {
0084           const auto channel = find(mapping.begin(), mapping.end(), link);
0085           if (channel == mapping.end())
0086             ss << "  0000 " << std::string(TTBV::S_ / 4, '0');
0087           else {
0088             const std::vector<tt::Frame>& bvs = bits[offset + std::distance(mapping.begin(), channel)];
0089             ss << (frame < static_cast<int>(bvs.size()) ? hex(bvs[frame], first) : hex(tt::Frame(), first));
0090           }
0091         }
0092         ss << std::endl;
0093         first = false;
0094       }
0095     }
0096   }
0097 
0098   // plays stringstream through modelsim
0099   void Demonstrator::sim(const std::stringstream& ss) const {
0100     // write ss to disk
0101     std::fstream fs;
0102     fs.open(dirIn_.c_str(), std::fstream::out);
0103     fs << ss.rdbuf();
0104     fs.close();
0105     // run modelsim
0106     std::stringstream cmd;
0107     cmd << "cd " << dirIPBB_ << " && ./run_sim -quiet -c work.top -do 'run " << runTime_
0108         << "us' -do 'quit' &> /dev/null";
0109     std::system(cmd.str().c_str());
0110   }
0111 
0112   // compares stringstream with modelsim output
0113   bool Demonstrator::compare(std::stringstream& ss) const {
0114     // write ss to disk
0115     std::fstream fs;
0116     fs.open(dirPre_.c_str(), std::fstream::out);
0117     fs << ss.rdbuf();
0118     fs.close();
0119     // use linux diff on disk
0120     const std::string c = "diff " + dirPre_ + " " + dirOut_ + " &> " + dirDiff_;
0121     std::system(c.c_str());
0122     ss.str("");
0123     ss.clear();
0124     // read diff output
0125     fs.open(dirDiff_.c_str(), std::fstream::in);
0126     ss << fs.rdbuf();
0127     fs.close();
0128     // count lines, 4 are expected
0129     int n(0);
0130     std::string token;
0131     while (getline(ss, token))
0132       n++;
0133     return n == 4;
0134   }
0135 
0136   // creates emp file header
0137   std::string Demonstrator::header(const std::vector<int>& links) const {
0138     std::stringstream ss;
0139     // file header
0140     ss << "Id: CMSSW" << std::endl
0141        << "Metadata: (strobe,) start of orbit, start of packet, end of packet, valid" << std::endl
0142        << std::endl;
0143     // link header
0144     ss << "      Link  ";
0145     for (int link : links)
0146       ss << "            " << std::setfill('0') << std::setw(3) << link << "        ";
0147     ss << std::endl;
0148     return ss.str();
0149   }
0150 
0151   // creates 6 frame gap between packets
0152   std::string Demonstrator::infraGap(int& nFrame, int numLinks) const {
0153     std::stringstream ss;
0154     for (int gap = 0; gap < numFramesInfra_; gap++) {
0155       ss << frame(nFrame);
0156       for (int link = 0; link < numLinks; link++)
0157         ss << "  0000 " << std::string(TTBV::S_ / 4, '0');
0158       ss << std::endl;
0159     }
0160     return ss.str();
0161   }
0162 
0163   // creates frame number
0164   std::string Demonstrator::frame(int& nFrame) const {
0165     std::stringstream ss;
0166     ss << "Frame " << std::setfill('0') << std::setw(4) << nFrame++ << "  ";
0167     return ss.str();
0168   }
0169 
0170   // converts bv into hex
0171   std::string Demonstrator::hex(const tt::Frame& bv, bool first) const {
0172     std::stringstream ss;
0173     ss << (first ? "  1001 " : "  0001 ") << std::setfill('0') << std::setw(TTBV::S_ / 4) << std::hex << bv.to_ullong();
0174     return ss.str();
0175   }
0176 
0177 }  // namespace trackerTFP