Belle II Software development
TRGCDCInterfaceBuilder.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9//-----------------------------------------------------------------------------
10// Description : A program to generate VHDL code for the packages.
11//-----------------------------------------------------------------------------
12
13#define TRG_SHORT_NAMES
14
15#include <cstdlib>
16#include <iostream>
17#include <fstream>
18#include <string>
19#include <vector>
20#include <boost/algorithm/string.hpp>
21#include <boost/lexical_cast.hpp>
22#include "trg/trg/Utilities.h"
23
24using namespace std;
25using namespace Belle2;
26
27#define DEBUG_LEVEL 1
28#define NAME "TRGCDCInterfaceBuilder"
29#define VERSION string("0.00")
30#define ENV_PATH "BELLE2_LOCAL_DIR"
31#define FRONT_END "/OpticalLinkFrontEnd.h"
32#define MARKER_0 "VHDL : begin"
33#define MARKER_1 "VHDL : end"
34#define N_KEYWORDS 5
35#define KEYWORD_0 "TRGOpticalLinkVersion"
36#define KEYWORD_1 "VHDL : type" // TRGSignalVector
37#define KEYWORD_2 "vector<const TRGSignalVector" // vector<TRGSignalVector
38#define KEYWORD_3 "vector<const TRGSignal" // vector<TRGSignal
39#define KEYWORD_4 "TRGSignal" // TRGSignal
40
41const string Keys[] = {
42 KEYWORD_0,
43 KEYWORD_1,
44 KEYWORD_2,
45 KEYWORD_3,
46 KEYWORD_4
47};
48vector<string> Definitions;
49unsigned LinesOfs2 = 0;
50const string Out0name = ".TRGCDCInterfaceBuilder0.vhdl";
51const string Out1name = ".TRGCDCInterfaceBuilder1.vhdl";
52const string Out2name = ".TRGCDCInterfaceBuilder2.vhdl";
53const string Out3name = ".TRGCDCInterfaceBuilder3.vhdl";
54ofstream Ofs0(Out0name.c_str(), ios::out);
55ofstream Ofs1(Out1name.c_str(), ios::out);
56ofstream Ofs2(Out2name.c_str(), ios::out);
57ofstream Ofs3(Out3name.c_str(), ios::out);
58const string Tab = " ";
59
60void Parser(ifstream&);
61void Parser0(const string&);
62void ParserTS(const string&);
63void ParserVTS(const string&);
64void ParserVTS2(const string&);
65void ParserTSV(const string&);
66void ParserVTSV(const string&);
67
68void TypeDefinition(const string& name, const string& line);
69void TypeDefinition(const string& name, unsigned size, const string& base);
70void Functions(const string& name, unsigned size);
71void GetName(const string& line,
72 string& name,
73 string& base,
74 bool& array,
75 unsigned& size);
76
77//---
78
79void (* ParserN[N_KEYWORDS])(const string&) = {
80 Parser0,
81 ParserTSV,
82 ParserVTSV,
83 ParserVTS,
84 ParserTS
85};
86
87int
88main(int argc, char**) // argv[]) {
89{
90//main(int argc) {
91
92 cout << NAME << " ... " << VERSION << endl;
93
94 //...Check arguments...
95 if (argc > 2) {
96 cout << NAME << " !!! no argument is necessary" << endl;
97 return -1;
98 }
99
100 //...Date...
101 // const string ts0 = TRGUtil::dateStringF();
102 const string ts1 = TRGUtil::dateString();
103
104 //...Get path to include directory...
105 const char* envPath = getenv(ENV_PATH);
106 const string path = (envPath != nullptr ? envPath : "");
107 const string indir = path + "/include/trg/cdc";
108
109 //...Temporary output file...
110 if (Ofs0.fail()) {
111 cout << NAME << " !!! can not open file" << endl
112 << " " << Out0name << endl;
113 return -2;
114 }
115 if (Ofs1.fail()) {
116 cout << NAME << " !!! can not open file" << endl
117 << " " << Out1name << endl;
118 return -3;
119 }
120 if (Ofs2.fail()) {
121 cout << NAME << " !!! can not open file" << endl
122 << " " << Out2name << endl;
123 return -4;
124 }
125 if (Ofs3.fail()) {
126 cout << NAME << " !!! can not open file" << endl
127 << " " << Out3name << endl;
128 return -5;
129 }
130
131 //...Banner...
132 Ofs0 << "-- Generated by " << NAME << " " << VERSION << endl;
133 Ofs0 << "-- " << ts1 << endl;
134 Ofs0 << "--" << endl;
135
136 //...Front-end Link...
137// TRGCDCFrontEnd::implementation(TRGCDCFrontEnd::inner, outfile);
138 const string fename = indir + FRONT_END;
139 ifstream fefile(fename.c_str(), ios::in);
140 if (fefile.fail()) {
141 cout << NAME << " !!! can not open file" << endl
142 << " " << fename << endl;
143 return -6;
144 }
145
146 //...Header...
147 Ofs0 << "-- Data file : " << endl;
148 Ofs0 << "-- " << fename << endl;
149 Ofs0 << "--" << endl;
150 Ofs0 << "" << endl;
151 Ofs0 << "library IEEE;" << endl;
152 Ofs0 << "use IEEE.STD_LOGIC_1164.all;" << endl << endl;
153 Ofs0 << "package CDCTRG_pkg is" << endl << endl;
154
155 Ofs1 << "package body CDCTRG_pkg is" << endl << endl;
156
157 //...Frame...
158 Ofs2 << Tab << "-- TRGFrame" << endl;
159 Ofs2 << Tab << "function TRGFrame (" << endl;
160
161 //...Frame body...
162 Ofs3 << Tab << "begin" << endl;
163 Ofs3 << Tab << " return" << endl;
164
165 //...Call the Parser...
166 Parser(fefile);
167
168 //...Copy Ofs2 and reopen it...
169 Ofs2.close();
170 string tmp = Out2name + ".tmp";
171 string cmd = "cp " + Out2name + " " + tmp;
172 system(cmd.c_str());
173 ofstream ofs2(Out2name.c_str(), ios::app);
174
175 //...For function body of TRGFrame...
176 string tmq = Out2name + ".tmp2";
177 cmd = "sed -e 's/std_logic_vector;/std_logic_vector is/g' " + tmp
178 + " > " + tmq;
179 system(cmd.c_str());
180
181 //...Trailer...
182 ofs2 << "end;" << endl << endl;
183
184 //...End of writing tmp files...
185 Ofs0.close();
186 Ofs1.close();
187 ofs2.close();
188 Ofs3.close();
189
190 //...Merge files...
191 cmd = "cat " + Out0name + " " + Out2name + " " + Out1name + " "
192 + tmq + " " + Out3name + " > TRGCDCInterfaceBuilder.vhdl";
193 system(cmd.c_str());
194
195 //...Termination...
196 cout << NAME << " ... terminated" << endl;
197}
198
199void
200Parser(ifstream& ifs)
201{
202
203 //...Main loop...
204 char b[800];
205 bool beginConversion = false;
206 bool endConversion = false;
207 while (! ifs.eof()) {
208 ifs.getline(b, 800);
209 string l(b);
210
211 //...Check 'begin' and 'end' markers...
212 string::size_type pos = l.find(MARKER_0);
213 if (pos != string::npos) {
214 beginConversion = true;
215 continue;
216 }
217 pos = l.find(MARKER_1);
218 if (pos != string::npos) {
219 endConversion = true;
220 continue;
221 }
222
223 //...Do convert...
224 if (beginConversion && (! endConversion)) {
225
226 //...Keyword loop...
227 for (unsigned i = 0; i < N_KEYWORDS; i++) {
228
229 //...Check keywords...
230 pos = l.find(Keys[i].c_str());
231 if (pos != string::npos) {
232 ParserN[i](l);
233 break;
234 }
235 }
236 } else if (endConversion) {
237
238 //...Do the final job...
239 Ofs2 << ")" << endl;
240 Ofs2 << Tab << " return std_logic_vector;" << endl << endl;
241
242 Ofs3 << ");" << endl;
243 Ofs3 << Tab << "end TRGFrame;" << endl;
244 Ofs3 << "end;" << endl;
245
246 break;
247 }
248 }
249}
250
251//...Parser for the keyword TRGOpticalLinkVersion...
252void
253Parser0(const string& line)
254{
255 string l = line;
256 // const string car0 = TRGUtil::carstring(l);
257 l = TRGUtil::cdrstring(l);
258 const string car1 = TRGUtil::carstring(l);
259 l = TRGUtil::cdrstring(l);
260 const string car2 = TRGUtil::carstring(l);
261 l = TRGUtil::cdrstring(l);
262 Ofs0 << "-- Version : " << car1 << " " << car2 << endl;
263 Ofs0 << "" << endl;
264}
265
266//...Parser for the keyword TRGSignal...
267void
268ParserTS(const string& l)
269{
270 string name;
271 string none;
272 bool array = false;
273 unsigned size = 0;
274 GetName(l, name, none, array, size);
275
276 //...Termination mark...
277 if (LinesOfs2) {
278 Ofs2 << ";" << endl;
279 Ofs3 << " &" << endl;
280 }
281
282 //...TRGFrame definition...
283 char v = 'a' + LinesOfs2;
284 Ofs2 << Tab << " " << v << " : in " << name;
285
286 //...TRGFrame body...
287 Ofs3 << Tab << " ToLogicVector(" << name << ")";
288
289 ++LinesOfs2;
290}
291
292//...Parser for the keyword VHDL...
293void
294ParserTSV(const string& line)
295{
296 string l = line;
297 // const string car0 = TRGUtil::carstring(l);
298 l = TRGUtil::cdrstring(l);
299 // const string car1 = TRGUtil::carstring(l);
300 l = TRGUtil::cdrstring(l);
301 // const string car2 = TRGUtil::carstring(l);
302 l = TRGUtil::cdrstring(l);
303 // const string car3 = TRGUtil::carstring(l);
304
305 //...Definition...
306 string m = TRGUtil::cdrstring(l);
307 string car4 = TRGUtil::carstring(m);
308 string vnv = car4;
309 Definitions.push_back(car4);
310
311 //...Look for array size...
312 string last = car4;
313 string top = "";
314 while (1) {
315 car4 = TRGUtil::carstring(m);
316 m = TRGUtil::cdrstring(m);
317 if (car4 == "downto") {
318 top = last;
319 break;
320 }
321 last = car4;
322 }
323 string dim;
324 for (unsigned i = 0; i < top.size(); i++) {
325 if (isdigit(top[i]))
326 dim += top[i];
327 else
328 dim = "";
329 }
330 unsigned arraySize = boost::lexical_cast<int>(dim) + 1;
331
332 //...Type definition...
333 TypeDefinition(vnv, l);
334
335 //...Functions...
336 Functions(vnv, arraySize);
337}
338
339//...Parser for the keyword vector<TRGSignal...
340void
341ParserVTS(const string& l)
342{
343
344 string name;
345 string base;
346 bool array = false;
347 unsigned size = 0;
348 GetName(l, name, base, array, size);
349
350 //...Check definitions...
351 bool defined = false;
352 for (unsigned i = 0; i < Definitions.size(); i++) {
353 if (Definitions[i] == name) {
354 defined = true;
355 break;
356 }
357 }
358 if (! defined)
359 cout << "TRGCDCInterfaceBuilder::ParserVTS !!! " << name
360 << " is not defined" << endl;
361
362 //...Type definition...
363 TypeDefinition(name, size, "std_logic");
364
365 //...Functions...
366 Functions(name, size);
367
368 //...TRGFrame...
369 ParserTS(l);
370}
371
372//...Parser for the keyword vector<TRGSignalVector...
373void
374ParserVTSV(const string& l)
375{
376
377 string name;
378 string base;
379 bool array = false;
380 unsigned size = 0;
381 GetName(l, name, base, array, size);
382
383 //...Check definitions...
384 bool defined = false;
385 for (unsigned i = 0; i < Definitions.size(); i++) {
386 if (Definitions[i] == name) {
387 defined = true;
388 break;
389 }
390 }
391 if (! defined)
392 cout << "TRGCDCInterfaceBuilder::ParserVTS !!! " << name
393 << " is not defined" << endl;
394
395 //...Type definition...
396 TypeDefinition(name, size, base);
397
398 //...Functions...
399 Functions(name, size);
400
401 //...TRGFrame...
402 ParserTS(l);
403}
404
405void
406TypeDefinition(const string& name, const string& l)
407{
408
409 //...Type definition...
410 Ofs0 << Tab << "-- " << name << endl;
411 Ofs0 << Tab << l << endl;
412 Ofs0 << endl;
413}
414
415void
416TypeDefinition(const string& name, unsigned size, const string& base)
417{
418
419 //...Type definition...
420 Ofs0 << Tab << "-- " << name << endl;
421 Ofs0 << Tab << "type " << name << " is array (" << size - 1
422 << " downto 0) of " << base << ";" << endl;
423 Ofs0 << endl;
424}
425
426void
427Functions(const string& name, unsigned arraySize)
428{
429
430 //...Conversion function : ToLogicVector...
431 Ofs0 << Tab << "-- " << name << endl;
432 Ofs0 << Tab << "function ToLogicVector (a : in " << name
433 << ") return std_logic_vector;" << endl;
434
435 //...Body...
436 Ofs1 << Tab << "-- " << name << " to std_logic_vector" << endl;
437 Ofs1 << Tab << "function ToLogicVector (a : in " << name
438 << ") return std_logic_vector is" << endl;
439 Ofs1 << Tab << "begin" << endl;
440 Ofs1 << Tab << " return" << endl;
441 for (unsigned i = arraySize; i > 0; --i) {
442 if (i > 1)
443 Ofs1 << Tab << " a(" << i - 1 << ") &"
444 << endl;
445 else
446 Ofs1 << Tab << " a(" << i - 1 << ");"
447 << endl;
448 }
449 Ofs1 << Tab << "end ToLogicVector;" << endl;
450 Ofs1 << endl;
451
452 //...Conversion function : to name...
453 Ofs0 << Tab << "function To" << name
454 << " (a : in std_logic_vector) return " << name << ";" << endl;
455 Ofs0 << endl;
456
457 //...Body...
458 Ofs1 << Tab << "-- std_logic_vector to " << name << endl;
459 Ofs1 << Tab << "function To" << name
460 << " (a : in std_logic_vector) return " << name << " is" << endl;
461 Ofs1 << Tab << "begin" << endl;
462 Ofs1 << Tab << " return" << endl;
463 for (unsigned i = arraySize; i > 0; --i) {
464 if (i > 1)
465 Ofs1 << Tab << " a(" << i - 1 << ") &" << endl;
466 else
467 Ofs1 << Tab << " a(" << i - 1 << ");" << endl;
468 }
469 Ofs1 << Tab << "end " << name << ";" << endl;
470 Ofs1 << endl;
471}
472
473void
474GetName(const string& line,
475 string& name,
476 string& base,
477 bool& array,
478 unsigned& size)
479{
480
481 string l = line;
482
483 //...Is this a vector? Then make an array...
484 array = false;
485 string::size_type pos = l.find("std::vector");
486 if (pos != string::npos)
487 array = true;
488
489 //...Keep the last word as a variable name...
490 name = "";
491 while (1) {
492 string car = TRGUtil::carstring(l);
493 l = TRGUtil::cdrstring(l);
494
495 if (l.size() == 0) {
496 name = car;
497 break;
498 }
499 }
500
501 //...Change variable name from C++ style...
502 string vnv = name.substr(1, name.size() - 2);
503 string vnf = vnv.substr(0, 1);
504 boost::to_upper(vnf);
505 vnv[0] = vnf[0];
506 name = vnv;
507
508 //...Array...
509 size = 0;
510 base = "";
511 if (array) {
512
513 //...Last part of a name must be size of array...
514 string dim;
515 for (unsigned i = 0; i < vnv.size(); i++) {
516 if (isdigit(vnv[i])) {
517 dim += vnv[i];
518 } else {
519 dim = "";
520 base += vnv[i];
521 }
522 }
523 size = boost::lexical_cast<int>(dim);
524 }
525}
Abstract base class for different kinds of events.
STL namespace.