Belle II Software  release-05-02-19
CDCTriggerTSFFirmwareWorker.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2017 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Tzu-An Sheng *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include "trg/cdc/xsi_loader.h"
12 
13 #include <trg/cdc/Cosim.h>
14 
15 #include <string>
16 #include <iostream>
17 #include <array>
18 #include <algorithm>
19 #include <tuple>
20 
21 #include <cstdio>
22 #include <cstring>
23 #include <unistd.h>
24 
25 
26 int Xsi::Loader::get_port_number_or_exit(std::string name)
27 {
28  int portNumber = get_port_number(name.c_str());
29  if (portNumber < 0) {
30  std::cerr << "ERROR: " << name << " not found" << std::endl;
31  throw;
32  }
33  return portNumber;
34 }
35 
38 public:
40  CDCTriggerTSFFirmwareWorker(std::string design, std::string waveform, int nMergersIn):
41  design_libname{design}, wdbName{waveform},
42  loader{design, simengine_libname}, nMergers{nMergersIn}
43  {
44  inputWidth = nMergers * mergerWidth;
45  inputToTSF.fill(Cosim::zero_val);
46  outputToTracker.fill(0);
47  };
49  void initialize();
51  void clock();
53  void terminate();
55  bool setInput(FILE*);
57  void setInput(char*);
58 
60  static constexpr int mergerWidth = 256;
62  static constexpr int maxInputWidth = 24 * mergerWidth;
64  static constexpr int outputWidth = 429;
66  static constexpr int nTrackers = 429;
67 
69  inline char* getInput()
70  {
71  return inputToTSF.data();
72  }
73 
75  inline std::array<char, outputWidth * 4> getOutput()
76  {
77  return outputToTracker;
78  }
79 
80  // inline std::array<char, outputWidth * nTrackers> getFlatOutput()
81  // {
82  // std::array<char, outputWidth * nTrackers> flatOutput;
83  // auto itr = flatOutput.begin();
84  // for (const auto& out : outputToTracker) {
85  // copy(out.begin(), out.end(), itr);
86  // itr += outputWidth;
87  // }
88  // return flatOutput;
89  // }
90 
92  inline std::string getStrOutput()
93  {
94  return std::string(outputToTracker.data());
95  }
96 
97 protected:
99  std::string simengine_libname = "librdi_simulator_kernel.so";
101  std::string design_libname;
103  std::string wdbName;
108 
110  int clk = 0;
112  int inPort = 0;
114  int outPort = 0;
116  int enableIn = 0;
118  int enableOutTracker = 0;
120  int enableOutEVT = 0;
121 
123  int nMergers;
126 
128  std::array<char, maxInputWidth> inputToTSF;
130  std::array<char, outputWidth * 4> outputToTracker;
132  char outputArray[429] = {};
133 
134 };
135 
136 using namespace Belle2;
137 using namespace Cosim;
138 using namespace std;
139 
140 
142 {
143  // array<char, 16384> buffer;
144  // strangly, using 16384 or smaller for buffer size doesn't work.
145  array<char, 32768> buffer;
146  buffer.fill(1);
147  // if (fgets(buffer.data(), maxInputWidth + 10, stream) != NULL) {
148  if (fgets(buffer.data(), buffer.size(), stream) != NULL) {
149  // if (LogSystem::Instance().getLogConfig()->getDebugLevel() > 100) {
150  if (false) {
151  cout << "received input to " << wdbName << ":\n";
152  for (int i = 0; i < inputWidth; ++i) {
153  cout << static_cast<int>(buffer[i]);
154  }
155  cout << endl;
156  }
157  copy(buffer.begin(), buffer.begin() + inputWidth, inputToTSF.begin());
158  return true;
159  } else {
160  return false;
161  }
162 }
163 
165 {
166  string buffer(input);
167  copy(buffer.begin(), buffer.begin() + inputWidth, inputToTSF.begin());
168 }
169 
171 {
172  std::cout << "Design DLL : " << design_libname << std::endl;
173  std::cout << "Sim Engine DLL : " << simengine_libname << std::endl;
174 
175  cout << getpid() << "\n";
176  sleep(1);
177  // try {
178  memset(&info, 0, sizeof(info));
179  info.logFileName = NULL;
180  info.wdbFileName = const_cast<char*>(wdbName.c_str());
181  loader.open(&info);
182  loader.trace_all();
183  string clkName = "user_clk_127";
184  string inName = "data_in";
185  string outName = "TSF_TRACKER_OUT";
186  string enableInName = "valid_in";
187  string enableTrackerName = "valid_tracker";
188  string enableEVTName = "valid_evttime";
189  // get I/O port signals
190  clk = loader.get_port_number_or_exit(clkName);
191  inPort = loader.get_port_number_or_exit(inName);
192  outPort = loader.get_port_number_or_exit(outName);
193  enableIn = loader.get_port_number_or_exit(enableInName);
194  enableOutTracker = loader.get_port_number_or_exit(enableTrackerName);
195  enableOutEVT = loader.get_port_number_or_exit(enableEVTName);
196  int dataClock = loader.get_port_number_or_exit("user_clk_3175");
197  // Start low clock
198  loader.put_value(dataClock, &zero_val);
199  loader.put_value(enableIn, &zero_val);
200  loader.put_value(inPort, inputToTSF.data());
201  for (int i = 0; i < 32; ++i) {
202  if (i == 1) {
203  loader.put_value(enableIn, &one_val);
204  }
205  loader.put_value(clk, &one_val);
206  loader.run(10);
207  loader.put_value(clk, &zero_val);
208  loader.run(10);
209  }
210  cout << "worker " << design_libname << " initialized \n";
211  // } catch (std::exception& e) {
212  // std::cerr << "ERROR: An exception occurred: " << e.what() << std::endl;
213  // } catch (...) {
214  // std::cerr << "ERROR: An unknown exception occurred." << std::endl;
215  // // Xsi_Instance.get_error_info();
216  // throw;
217  // }
218 }
219 
221 {
222  loader.close();
223 }
224 
226 {
227  int status = 0;
228  // assign input signals
229  try {
230  // Put clk to one
231  // write the input
232  loader.put_value(inPort, inputToTSF.data());
233 
234  loader.put_value(enableIn, &one_val);
235  for (int j = 0; j < 4; j++) {
236  // if (j == 0) {
237  // loader.put_value(enableIn, &one_val);
238  // } else {
239  // loader.put_value(enableIn, &zero_val);
240  // }
241 
242  loader.put_value(clk, &one_val);
243  loader.run(10);
244 
245  // read the output
246  loader.get_value(outPort, outputToTracker.data());
247  // cout << "clk " << j << "\n";
248  // for (int i2d=0; i2d < 4; ++i2d) {
249  // for (int i = outputWidth * i2d; i < outputWidth * (i2d + 1); ++i ) {
250  // cout << std_logic_literal[static_cast<int>(outputToTracker[i])];
251  // }
252  // cout << endl << flush;
253  // }
254  // Put clk to zero
255  loader.put_value(clk, &zero_val);
256  loader.run(10);
257  }
258  } catch (std::exception& e) {
259  std::cerr << "ERROR: An exception occurred: " << e.what() << std::endl;
260  status = 2;
261  } catch (...) {
262  std::cerr << "ERROR: An unknown exception occurred." << std::endl;
263  status = 3;
264  }
265  ignore = status;
266 }
267 
268 int main(int argc, char* argv[])
269 {
270  if (argc < 6) {
271  cerr << "too few arguments!" << "\n";
272  throw;
273  }
274  int inputFileDescriptor = stoi(argv[1]);
275  int outputFileDescriptor = stoi(argv[2]);
276  FILE* instream = fdopen(inputFileDescriptor, "r");
277  // FILE * outstream = fdopen(outputFileDescriptor, "w");
278  ostream* outstream = createOutStreamFromFD(outputFileDescriptor);
279  CDCTriggerTSFFirmwareWorker worker(argv[3], argv[4], stoi(argv[5]));
280  worker.initialize();
281  (*outstream) << "init" << endl;
282  // read from pipe and put input to array
283  while (!feof(instream) && !ferror(instream) && worker.setInput(instream)) {
284  // while (!feof(instream) && !ferror(instream) &&
285  // fgets(buffer, sizeof (buffer), instream) != NULL) {
286  // drive the simulation
287  worker.clock();
288 
289  // cout << "sending tsf output:\n";
290  // for (int i2d = 0; i2d < 4; ++i2d) {
291  // for (int i = worker.outputWidth * i2d; i < worker.outputWidth * (i2d + 1); ++i ) {
292  // cout << std_logic_literal[static_cast<int>(worker.getOutput()[i])];
293  // }
294  // cout << endl;
295  // }
296 
297  // send output to the module
298  // string constructor from buffer of fixed size.
299  (*outstream) << string(worker.getOutput().data(), worker.outputWidth * 4) << endl;
300 
301  // fprintf(outstream, "%s\n" , con.data());
302  }
303  close(inputFileDescriptor);
304  close(outputFileDescriptor);
305  worker.terminate();
306  return 0;
307 }
CDCTriggerTSFFirmwareWorker::initialize
void initialize()
Intialization.
Definition: CDCTriggerTSFFirmwareWorker.cc:170
CDCTriggerTSFFirmwareWorker::inputToTSF
std::array< char, maxInputWidth > inputToTSF
array of input data to TSF
Definition: CDCTriggerTSFFirmwareWorker.cc:128
CDCTriggerTSFFirmwareWorker::CDCTriggerTSFFirmwareWorker
CDCTriggerTSFFirmwareWorker(std::string design, std::string waveform, int nMergersIn)
Construtor.
Definition: CDCTriggerTSFFirmwareWorker.cc:40
CDCTriggerTSFFirmwareWorker::nMergers
int nMergers
Number of Mergers.
Definition: CDCTriggerTSFFirmwareWorker.cc:123
CDCTriggerTSFFirmwareWorker::clock
void clock()
clock function
Definition: CDCTriggerTSFFirmwareWorker.cc:225
Cosim
Helper class for software (C++) / firmware (VHDL) co-simulation.
Definition: Cosim.h:15
CDCTriggerTSFFirmwareWorker::design_libname
std::string design_libname
string of design libname
Definition: CDCTriggerTSFFirmwareWorker.cc:101
Cosim::zero_val
const char zero_val
'0' in XSI VHDL simulation
Definition: Cosim.h:38
CDCTriggerTSFFirmwareWorker
a class for CDCTRG TSF firmware worker
Definition: CDCTriggerTSFFirmwareWorker.cc:37
CDCTriggerTSFFirmwareWorker::getStrOutput
std::string getStrOutput()
get output in string
Definition: CDCTriggerTSFFirmwareWorker.cc:92
CDCTriggerTSFFirmwareWorker::wdbName
std::string wdbName
string of wdb name
Definition: CDCTriggerTSFFirmwareWorker.cc:103
CDCTriggerTSFFirmwareWorker::terminate
void terminate()
Termination.
Definition: CDCTriggerTSFFirmwareWorker.cc:220
Belle2::mergerWidth
static constexpr int mergerWidth
Merger data width.
Definition: CDCTriggerUnpackerModule.h:53
main
int main(int argc, char **argv)
Run all tests.
Definition: test_main.cc:77
CDCTriggerTSFFirmwareWorker::getInput
char * getInput()
get input
Definition: CDCTriggerTSFFirmwareWorker.cc:69
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Cosim::one_val
const char one_val
'1' in XSI VHDL simulation
Definition: Cosim.h:36
t_xsi_setup_info
Note: VHDL std_logic value is stored in a byte (char).
Definition: xsi.h:137
CDCTriggerTSFFirmwareWorker::setInput
bool setInput(FILE *)
set input with FILE*
Definition: CDCTriggerTSFFirmwareWorker.cc:141
Xsi::Loader
Definition: xsi_loader.h:23
CDCTriggerTSFFirmwareWorker::inputWidth
int inputWidth
input data width
Definition: CDCTriggerTSFFirmwareWorker.cc:125
CDCTriggerTSFFirmwareWorker::loader
Xsi::Loader loader
Xsi Loader of Xilinx software.
Definition: CDCTriggerTSFFirmwareWorker.cc:105
CDCTriggerTSFFirmwareWorker::getOutput
std::array< char, outputWidth *4 > getOutput()
get output
Definition: CDCTriggerTSFFirmwareWorker.cc:75
CDCTriggerTSFFirmwareWorker::info
s_xsi_setup_info info
s_xsi_setup_info of Xilinx software
Definition: CDCTriggerTSFFirmwareWorker.cc:107
CDCTriggerTSFFirmwareWorker::outputToTracker
std::array< char, outputWidth *4 > outputToTracker
array of output data to tracker
Definition: CDCTriggerTSFFirmwareWorker.cc:130