CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
L1MuGMTLUT.cc
Go to the documentation of this file.
1 //-------------------------------------------------
2 //
3 // \class L1MuGMTLUT
9 //
10 // $Date: 2012/02/10 14:19:28 $
11 // $Revision: 1.7 $
12 //
13 // Author :
14 // H. Sakulin HEPHY Vienna
15 //
16 // Migrated to CMSSW:
17 // I. Mikulec
18 //
19 //--------------------------------------------------
20 
21 //---------------
22 // C++ Headers --
23 //---------------
24 
26 
27 #include <iostream>
28 #include <fstream>
29 #include <sstream>
30 
32 
34 
35 using namespace std;
36 
38  if (! m_UseLookupFunction ) {
39 
40  // de-allocate vectors
41  // no destuction needed for vector< vector <unsigned> >
42 
43  // for (int i=0;i < m_NLUTS; i++)
44  // m_Contents[i].clear();
45  // m_Contents.clear();
46  }
47 }
48 
49 void L1MuGMTLUT::Init(const char* name, const vector<string>& instances,
50  const vector<port>& in_widths, const vector<port>& out_widths,
51  unsigned vme_addr_width, bool distrRAM)
52 {
53  m_name = name;
54  m_InstNames = instances;
55  m_NLUTS = instances.size();
56 
57  m_Inputs = in_widths;
58  m_TotalInWidth = 0;
59  for (unsigned i=0; i< in_widths.size(); i++) m_TotalInWidth += in_widths[i].second;
60 
61  m_Outputs = out_widths;
62  m_TotalOutWidth = 0;
63  for (unsigned i=0; i< out_widths.size(); i++) m_TotalOutWidth += out_widths[i].second;
64 
65  m_vme_addr_width = vme_addr_width;
66  m_distrRAM = distrRAM;
67 
68  if (m_distrRAM && (m_TotalInWidth != vme_addr_width) ) {
69  edm::LogWarning("AddressMismatch")
70  << "L1MuGMTLUT::Init(): for distributed RAM the GMT (Input) address width "
71  << "has to match the VME address width. Core Generation will not work.";
72  }
73 
74  m_GeneralLUTVersion = L1MuGMTConfig::getVersionLUTs();
75  m_initialized = true;
76 }
77 
78 
79 void L1MuGMTLUT::Save(const char* path) {
80  if (! m_initialized) {
81  edm::LogWarning("LUTNotInitialized") << "L1MuGMTLUT::Save: LUT not initialized. ";
82  return;
83  }
84 
85  m_saveFlag = true;
86 
87  ofstream of(path);
88  of << "// This is a CMS L1 Global Muon Trigger .lut file. " << endl;
89  of << "// " << endl;
90  of << "// It defines a set of look-up-tables(LUTs) of the same type (same inputs and outputs) but" << endl;
91  of << "// with different default contents. For example a certain type of LUT can have different" << endl;
92  of << "// default values for DT for RPC and for CSC muons. " << endl;
93  of << "// " << endl;
94  of << "// NAME gives the name of the LUT. It should match the base name (name without '.lut')" << endl;
95  of << "// of the LUT file." << endl;
96  of << "// When deriving a C++ sub-class the name is used case sensitive." << endl;
97  of << "// In generated VHDL code the name is used in lower case." << endl;
98  of << "// " << endl;
99  of << "// INSTANCES is the list of instances of the LUT with different default values." << endl;
100  of << "// the lists consists of identifiers for each of the instances separated by spaces." << endl;
101  of << "// the identifiers can be made up of characters that are valid in VHDL lables. " << endl;
102  of << "// In the VHDL code they are used to label the different instances." << endl;
103  of << "// " << endl;
104  of << "// In C++ and VHDL the instance of a LUT is selected by an integer index where 0 " << endl;
105  of << "// corresponds to the leftmost identifier. Integer indices are also used in the CONTENTS_XX" << endl;
106  of << "// statements in this file." << endl;
107  of << "// " << endl;
108  of << "// LUT_INPUTS is the (space-separated) list of inputs of the LUT. Each input is specified in the form" << endl;
109  of << "// <input_name>(<number_of_bits>) where <input_name> is the name of the input and" << endl;
110  of << "// <number_of_bits> is the number of bits of the input. <input_name> has to be a valid" << endl;
111  of << "// identifier both in C++ and in VHDL. In C++ it is represented as an unsigned int." << endl;
112  of << "// " << endl;
113  of << "// All LUT inputs together make up the address of the corresponding memory." << endl;
114  of << "// The first input in the list corresponds to the most-significant bits of the address." << endl;
115  of << "// " << endl;
116  of << "// LUT_OUTPUTS is the (space-separated) list of outputs of the LUT. Each output is specified in the form" << endl;
117  of << "// <output_name>(<number_of_bits>) where <output_name> is the name of the output and" << endl;
118  of << "// <number_of_bits> is the number of bits of the output. <output_name> has to be a valid" << endl;
119  of << "// identifier both in C++ and in VHDL. In C++ it is represented as an unsigned int." << endl;
120  of << "// " << endl;
121  of << "// All LUT outputs together make up the data of the corresponding memory." << endl;
122  of << "// The first output in the list corresponds to the most-significant data bits." << endl;
123  of << "// " << endl;
124  of << "// VME_ADDR_WIDTH is the address width of the LUT memory when accessed via VME. When the LUT " << endl;
125  of << "// is implemented as dual-port block RAM, the VME address with can be different " << endl;
126  of << "// from the address width given by the sum of the input widths. It can be larger or" << endl;
127  of << "// smaller by a factor of 2^n. When the LUT is implemented as dual-port distributed RAM," << endl;
128  of << "// the VME address width has to match the input width. " << endl;
129  of << "// " << endl;
130  of << "// DISTRIBUTED_RAM is 1 if the LUT is to be implemented in distributed RAM and 0 for Block RAM " << endl;
131  of << "// Note that for distributed RAM the address width on the GMT side (sum of input widths)" << endl;
132  of << "// has to match the vme_addr_width" << endl;
133  of << "// " << endl;
134  of << "// CONTENTS_XX specifies the default contents of instance with index XX (see INSTANCES)." << endl;
135  of << "// contents are specified as decimal numbers, one number per line." << endl;
136  of << "// " << endl;
137  of << "// Hannes Sakulin / HEPHY Vienna, 2003" << endl;
138  of << "// "<< endl;
139 
140  of << "NAME = " << m_name << endl;
141  of << "INSTANCES =" ;
142  for (unsigned i=0; i<m_InstNames.size(); i++) of << " " << m_InstNames[i];
143  of << endl;
144  of << "LUT_INPUTS = " << PortDecoder(m_Inputs).str() << endl;
145  of << "LUT_OUTPUTS = " << PortDecoder(m_Outputs).str() << endl;
146  of << "VME_ADDR_WIDTH = " << m_vme_addr_width << endl;
147  of << "DISTRIBUTED_RAM = " << (m_distrRAM?"1":"0") << endl;
148  for (int i=0; i<m_NLUTS; i++) {
149  of << "// " << m_InstNames[i] << endl;
150  of << "CONTENTS_" << i << " = ";
151  for (unsigned addr = 0; addr < (unsigned) (1<<m_TotalInWidth); addr ++) {
152  of << LookupPacked (i, addr) << endl;
153  }
154  of << endl;
155  }
156 
157  m_saveFlag = false;
158 
159 }
160 
161 
162 // Rules for file
163 //
164 // NAME = VALUE1 [VALUE2 [...]]
165 // All header variables have to be set before first contents variable
166 // comments start with "//" and go up to end of line
167 //
168 // when writing back, comments will be save first
169 
170 
171 //--------------------------------------------------------------------------------
172 
173 void L1MuGMTLUT::Set (int idx, unsigned address, unsigned value) {
174  if (! m_initialized) {
175  edm::LogWarning("LUTNotInitialized") << "L1MuGMTLUT::Set: LUT not initialized. ";
176  return;
177  }
178 
179  if ( idx >= m_NLUTS ) {
180  edm::LogWarning("LUTRangeViolation") << "L1MuGMTLUT::Set: LUT index exceeds range (0 to " << ( m_NLUTS -1 ) << ").";
181  return;
182  }
183  if ( address >= (unsigned)(1 << m_TotalInWidth) ) {
184  edm::LogWarning("LUTRangeViolation") << "Error in L1MuGMTLUT::Set: LUT input exceeds range (0 to " << ( (1 << m_TotalInWidth) -1 ) << ").";
185  return;
186  }
187  if ( value >= (unsigned)(1 << m_TotalOutWidth) ) {
188  edm::LogWarning("LUTRangeViolation") << "Error in L1MuGMTLUT::Set: LUT output exceeds range (0 to " << ( (1 << m_TotalOutWidth) -1 ) << ")." ;
189  return;
190  }
191  m_Contents[idx][address] = value;
192 }
193 
194 
195 
196 void L1MuGMTLUT::Load(const char* path) {
197  string lf_name("");
198  vector <string> lf_InstNames;
199  vector <port> lf_Inputs;
200  vector <port> lf_Outputs;
201  unsigned lf_vme_addr_width=0;
202  bool lf_distrRAM=false;
203  vector<string> lf_comments;
204 
205  ifstream in (path);
206  const int sz=1000; char buf[sz];
207 
208 
209  // read header
210 
211  while ( in.getline(buf, sz) ) {
212  string line(buf);
214  if ( (i=line.find("//")) != string::npos) {
215  lf_comments.push_back( line.substr(i) ); // save comments
216  line.erase(i); // and strip
217  }
219  if (tok.size() == 2) {
220  L1MuGMTLUTHelpers::replace(tok[0], " ","", false); // skip spaces
221  L1MuGMTLUTHelpers::replace(tok[0], "\t","", false); // skip tabs
222 
223  L1MuGMTLUTHelpers::replace(tok[1], "\t", " ", false); // convert tabs to spaces
224  L1MuGMTLUTHelpers::replace(tok[1], " ", " ", true); // skip multiple spaces
225  tok[1].erase(0, tok[1].find_first_not_of(" ")); // skip leading spaces
226  tok[1].erase(tok[1].find_last_not_of(" ")+1); // skip trailing spaces
227 
228  if (tok[0] == "NAME") lf_name = tok[1];
229  else if (tok[0] == "INSTANCES") { lf_InstNames = L1MuGMTLUTHelpers::Tokenizer(" ",tok[1]); }
230  else if (tok[0] == "LUT_INPUTS") lf_Inputs = PortDecoder(tok[1]);
231  else if (tok[0] == "LUT_OUTPUTS") lf_Outputs = PortDecoder(tok[1]);
232  else if (tok[0] == "VME_ADDR_WIDTH") lf_vme_addr_width = atoi(tok[1].c_str());
233  else if (tok[0] == "DISTRIBUTED_RAM") lf_distrRAM = ( atoi(tok[1].c_str()) == 1 );
234  }
235  if (tok[0].find("CONTENTS") != string::npos) break;
236  }
237 
238  if (!m_initialized) { // then initialize
239  Init(lf_name.c_str(), lf_InstNames, lf_Inputs, lf_Outputs, lf_vme_addr_width, lf_distrRAM);
240  }
241  else { // verify compatibility
242  if (m_name != lf_name ||
243  m_InstNames != lf_InstNames ||
244  m_Inputs != lf_Inputs ||
245  m_Outputs != lf_Outputs ||
246  m_vme_addr_width != lf_vme_addr_width ||
247  m_distrRAM != lf_distrRAM) {
248  edm::LogWarning("LUTParmasMismatch")
249  << "L1MuGMTLUT::Load: error: parameters in file do not match configuration of LUT. Load failed.";
250  return;
251  }
252  }
253 
254  if (m_UseLookupFunction) {
255  // allocate vectors
256  m_Contents.resize( m_NLUTS );
257  for (int i=0;i < m_NLUTS; i++)
258  m_Contents[i].resize( 1 << m_TotalInWidth );
259 
260  // switch to table mode
261  m_UseLookupFunction = false;
262  }
263 
264  // continue to read contents (first line should be in buf)
265  int maxrows = 1 << m_TotalInWidth;
266  int row = 0;
267  int current_index = -1;
268  do {
269  string line(buf);
271  if ( (i=line.find("//")) != string::npos) line.erase(i); // strip comments
273 
274  if (tok.size() == 2 && tok[0].find("CONTENTS") != string::npos) {
275  L1MuGMTLUTHelpers::Tokenizer tok1("_",tok[0]);
276  if (tok1.size() !=2) {
277  edm::LogWarning("LUTParsingProblem") << "L1MuGMTLUT::Load: error parsing contents tag " << tok[0] << ".";
278  break;
279  }
280 
281  istringstream is(tok1[1].c_str());
282  int newindex;
283  is >> newindex;
284  if (newindex != current_index+1)
285  edm::LogWarning("LUTParsingProblem") << "L1MuGMTLUT::Load: warning: LUTS in LUT file are not in order.";
286 
287  if (newindex > m_NLUTS-1) {
288  edm::LogWarning("LUTParsingProblem") << "L1MuGMTLUT::Load: warning: LUT file contains LUT with too high index ("
289  << tok[0]
290  << "). max = " << m_NLUTS << " skipping.";
291  newindex = -1;
292  }
293  current_index = newindex;
294 
295  if (row != 0) {
296  if ( row < maxrows )
297  edm::LogWarning("LUTParsingProblem") << "L1MuGMTLUT::Load: warning: LUT file only contains part of LUT contents.";
298  row = 0;
299  }
300  istringstream is1(tok[1].c_str());
301  unsigned value;
302  if (is1 >> value) {
303  if (current_index!=-1)
304  Set (current_index, row++, value);
305  }
306  }
307  else {
308  istringstream is1(line.c_str());
309  unsigned value;
310  if (is1 >> value) {
311  if (row < maxrows) {
312  if (current_index!=-1)
313  Set (current_index, row++, value);
314  }
315  else
316  edm::LogWarning("LUTParsingProblem")
317  << "L1MuGMTLUT::Load: warning: LUT file only contains LUT with too many entries. skipping.";
318  }
319  }
320  } while ( in.getline(buf, sz) );
321 }
322 
323 //--------------------------------------------------------------------------------
324 // Generate a SubClass .h file
325 //
326 // to be used manually during code development
327 
328 void L1MuGMTLUT::MakeSubClass(const char* fname, const char* template_file_h,
329  const char* template_file_cc) {
330 
331  // prepare parts
332  string ins_name (m_name);
333  string ins_name_upper = L1MuGMTLUTHelpers::upperCase (ins_name);
334  string ins_instance_string;
335  string ins_instances_enum;
336  for (unsigned i=0; i<m_InstNames.size(); i++) {
337  if (i!=0) ins_instance_string += ' ';
338  ins_instance_string += m_InstNames[i];
339 
340  if (i!=0) ins_instances_enum += ", ";
341  ins_instances_enum += m_InstNames[i];
342  }
343  char ins_vme[100];
344  sprintf (ins_vme, "%d", m_vme_addr_width);
345 
346  char ins_distr_RAM[10];
347  sprintf (ins_distr_RAM, "%s", m_distrRAM?"true":"false");
348 
349 
350  string ins_input_decl_list, ins_input_list, ins_input_addr_list;
351  for (unsigned i=0; i<m_Inputs.size(); i++) {
352  ins_input_decl_list += string(", unsigned ") + m_Inputs[i].first;
353  ins_input_list += string(", ") + m_Inputs[i].first;
354  char tmp[100]; sprintf (tmp, " ,addr[%d]", i);
355  ins_input_addr_list += string(tmp);
356  }
357 
358  // string ins_lookup_functions;
359  ostringstream os;
360  for (unsigned i=0; i<m_Outputs.size(); i++) {
361  os << " /// specific lookup function for " << m_Outputs[i].first << endl;
362  os << " unsigned SpecificLookup_" << m_Outputs[i].first << " (int idx" << ins_input_decl_list << ") const {" << endl;
363  os << " vector<unsigned> addr(" << m_Inputs.size() << ");" << endl;
364  for (unsigned j=0; j< m_Inputs.size(); j++) {
365  os << " addr[" << j << "] = " << m_Inputs[j].first << ";" << endl;
366  }
367  os << " return Lookup(idx, addr) [" << i << "];" << endl;
368  os << " };" << endl << endl;
369  }
370  os << " /// specific lookup function for entire output field" << endl;
371  os << " unsigned SpecificLookup (int idx" << ins_input_decl_list << ") const {" << endl;
372  os << " vector<unsigned> addr(" << m_Inputs.size() << ");" << endl;
373  for (unsigned j=0; j< m_Inputs.size(); j++) {
374  os << " addr[" << j << "] = " << m_Inputs[j].first << ";" << endl;
375  }
376  os << " return LookupPacked(idx, addr);" << endl;
377  os << " };" << endl << endl;
378 
379  os << ends;
380  string ins_lookup_functions = os.str();
381 
382  // substitute in .h file
383  string outfn (fname);
384  if (outfn.size() == 0) outfn = string("../interface/L1MuGMT") + m_name + string("LUT.h");
385  ifstream of_check(outfn.c_str());
386  if (! of_check.good() ) {
387  ofstream of(outfn.c_str());
388 
389 
390  ifstream in(template_file_h);
391  const int sz=1000; char buf[sz];
392 
393  while ( in.getline(buf, sz) ) {
394  string line(buf);
395 
396  L1MuGMTLUTHelpers::replace(line, "###insert_name_upper###", ins_name_upper, false);
397  L1MuGMTLUTHelpers::replace(line, "###insert_name###", ins_name, false);
398  L1MuGMTLUTHelpers::replace(line, "###insert_instance_string###", ins_instance_string, false);
399  L1MuGMTLUTHelpers::replace(line, "###insert_instances_enum###", ins_instances_enum, false);
400  L1MuGMTLUTHelpers::replace(line, "###insert_inputs_string###", string(PortDecoder(m_Inputs).str()), false);
401  L1MuGMTLUTHelpers::replace(line, "###insert_outputs_string###", string(PortDecoder(m_Outputs).str()), false);
402  L1MuGMTLUTHelpers::replace(line, "###insert_vme_input_width###", string(ins_vme), false);
403  L1MuGMTLUTHelpers::replace(line, "###insert_distrRAM###", string(ins_distr_RAM), false);
404  L1MuGMTLUTHelpers::replace(line, "###insert_input_decl_list###", ins_input_decl_list, false);
405  L1MuGMTLUTHelpers::replace(line, "###insert_input_list###", ins_input_list, false);
406  L1MuGMTLUTHelpers::replace(line, "###insert_input_addr_list###", ins_input_addr_list, false);
407  L1MuGMTLUTHelpers::replace(line, "###insert_lookup_functions###", ins_lookup_functions, false);
408  of << line << endl;
409  }
410  }
411 
412  // substitute in .cc file
413  string outfn_cc (fname);
414  if (outfn_cc.size() == 0) outfn_cc = string("../interface/L1MuGMT") + m_name + string("LUT.cc");
415 
416  ifstream of_cc_check( outfn_cc.c_str() );
417  if (! of_cc_check.good() ) {
418  ofstream of_cc(outfn_cc.c_str());
419 
420 
421  ifstream in_cc(template_file_cc);
422  const int sz=1000; char buf[sz];
423 
424  while ( in_cc.getline(buf, sz) ) {
425  string line(buf);
426 
427  L1MuGMTLUTHelpers::replace(line, "###insert_name_upper###", ins_name_upper, false);
428  L1MuGMTLUTHelpers::replace(line, "###insert_name###", ins_name, false);
429  L1MuGMTLUTHelpers::replace(line, "###insert_instance_string###", ins_instance_string, false);
430  L1MuGMTLUTHelpers::replace(line, "###insert_instances_enum###", ins_instances_enum, false);
431  L1MuGMTLUTHelpers::replace(line, "###insert_inputs_string###", string(PortDecoder(m_Inputs).str()), false);
432  L1MuGMTLUTHelpers::replace(line, "###insert_outputs_string###", string(PortDecoder(m_Outputs).str()), false);
433  L1MuGMTLUTHelpers::replace(line, "###insert_vme_input_width###", string(ins_vme), false);
434  L1MuGMTLUTHelpers::replace(line, "###insert_distrRAM###", string(ins_distr_RAM), false);
435  L1MuGMTLUTHelpers::replace(line, "###insert_input_decl_list###", ins_input_decl_list, false);
436  L1MuGMTLUTHelpers::replace(line, "###insert_input_list###", ins_input_list, false);
437  L1MuGMTLUTHelpers::replace(line, "###insert_input_addr_list###", ins_input_addr_list, false);
438  L1MuGMTLUTHelpers::replace(line, "###insert_lookup_functions###", ins_lookup_functions, false);
439  of_cc << line << endl;
440  }
441  }
442 }
443 
444 
int i
Definition: DBlmapReader.cc:9
virtual ~L1MuGMTLUT()
destructor
Definition: L1MuGMTLUT.cc:37
char * address
Definition: mlp_lapack.h:14
void Set(int idx, unsigned address, unsigned value)
set with single address and value
Definition: L1MuGMTLUT.cc:173
void MakeSubClass(const char *fname="", const char *template_file_h="../interface/L1MuGMTLUT_SubClass.h_template", const char *template_file_cc="../interface/L1MuGMTLUT_SubClass.cc_template")
Add Generate SubClass method.
Definition: L1MuGMTLUT.cc:328
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
uint16_t size_type
U second(std::pair< T, U > const &p)
static unsigned getVersionLUTs()
list path
Definition: scaleCards.py:51
void Save(const char *path)
save to LUT file
Definition: L1MuGMTLUT.cc:79
int j
Definition: DBlmapReader.cc:9
static std::string upperCase(const std::string &s)
void Load(const char *path)
I/O functions.
Definition: L1MuGMTLUT.cc:196
string fname
main script
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
static int replace(std::string &input, const std::string &gone, const std::string &it, bool multiple)
void Init(const char *name, const std::vector< std::string > &instances, const std::vector< port > &in_widths, const std::vector< port > &out_widths, unsigned vme_addr_width=0, bool distrRAM=false)
Initialize the LUT.
Definition: L1MuGMTLUT.cc:49