Type.py (7805:f249937228b5) Type.py (7832:de7601e6e19d)
1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
2# Copyright (c) 2009 The Hewlett-Packard Development Company
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28from m5.util import orderdict
29
30from slicc.util import PairContainer
31from slicc.symbols.Symbol import Symbol
32
33class DataMember(PairContainer):
34 def __init__(self, ident, type, pairs, init_code):
35 super(DataMember, self).__init__(pairs)
36 self.ident = ident
37 self.type = type
38 self.init_code = init_code
39
40class Enumeration(PairContainer):
41 def __init__(self, ident, pairs):
42 super(Enumeration, self).__init__(pairs)
43 self.ident = ident
44
45class Method(object):
46 def __init__(self, return_type, param_types):
47 self.return_type = return_type
48 self.param_types = param_types
49
50class Type(Symbol):
51 def __init__(self, table, ident, location, pairs, machine=None):
52 super(Type, self).__init__(table, ident, location, pairs)
53 self.c_ident = ident
54 self.abstract_ident = ""
55 if machine:
56 if self.isExternal or self.isPrimitive:
57 if "external_name" in self:
58 self.c_ident = self["external_name"]
59 else:
60 # Append with machine name
61 self.c_ident = "%s_%s" % (machine, ident)
62
63 self.pairs.setdefault("desc", "No description avaliable")
64
65 # check for interface that this Type implements
66 if "interface" in self:
67 interface = self["interface"]
68 if interface in ("Message", "NetworkMessage"):
69 self["message"] = "yes"
70 if interface == "NetworkMessage":
71 self["networkmessage"] = "yes"
72
73 # FIXME - all of the following id comparisons are fragile hacks
74 if self.ident in ("CacheMemory", "NewCacheMemory",
75 "TLCCacheMemory", "DNUCACacheMemory",
76 "DNUCABankCacheMemory", "L2BankCacheMemory",
77 "CompressedCacheMemory", "PrefetchCacheMemory"):
78 self["cache"] = "yes"
79
80 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
81 self["tbe"] = "yes"
82
83 if self.ident == "NewTBETable":
84 self["newtbe"] = "yes"
85
86 if self.ident == "TimerTable":
87 self["timer"] = "yes"
88
89 if self.ident == "DirectoryMemory":
90 self["dir"] = "yes"
91
92 if self.ident == "PersistentTable":
93 self["persistent"] = "yes"
94
95 if self.ident == "Prefetcher":
96 self["prefetcher"] = "yes"
97
98 if self.ident == "DNUCA_Movement":
99 self["mover"] = "yes"
100
101 self.isMachineType = (ident == "MachineType")
102
103 self.data_members = orderdict()
104
105 # Methods
106 self.methods = {}
107
108 # Enums
109 self.enums = orderdict()
110
111 @property
112 def isPrimitive(self):
113 return "primitive" in self
114 @property
115 def isNetworkMessage(self):
116 return "networkmessage" in self
117 @property
118 def isMessage(self):
119 return "message" in self
120 @property
121 def isBuffer(self):
122 return "buffer" in self
123 @property
124 def isInPort(self):
125 return "inport" in self
126 @property
127 def isOutPort(self):
128 return "outport" in self
129 @property
130 def isEnumeration(self):
131 return "enumeration" in self
132 @property
133 def isExternal(self):
134 return "external" in self
135 @property
136 def isGlobal(self):
137 return "global" in self
138 @property
139 def isInterface(self):
140 return "interface" in self
141
142 # Return false on error
143 def dataMemberAdd(self, ident, type, pairs, init_code):
144 if ident in self.data_members:
145 return False
146
147 member = DataMember(ident, type, pairs, init_code)
148 self.data_members[ident] = member
149
150 return True
151
152 def dataMemberType(self, ident):
153 return self.data_members[ident].type
154
155 def methodId(self, name, param_type_vec):
156 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
157
158 def methodIdAbstract(self, name, param_type_vec):
159 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
160
161 def methodAdd(self, name, return_type, param_type_vec):
162 ident = self.methodId(name, param_type_vec)
163 if ident in self.methods:
164 return False
165
166 self.methods[ident] = Method(return_type, param_type_vec)
167 return True
168
169 def enumAdd(self, ident, pairs):
170 if ident in self.enums:
171 return False
172
173 self.enums[ident] = Enumeration(ident, pairs)
174
175 # Add default
176 if "default" not in self:
177 self["default"] = "%s_NUM" % self.c_ident
178
179 return True
180
181 def writeCodeFiles(self, path):
182 if self.isExternal:
183 # Do nothing
184 pass
185 elif self.isEnumeration:
186 self.printEnumHH(path)
187 self.printEnumCC(path)
188 else:
189 # User defined structs and messages
190 self.printTypeHH(path)
191 self.printTypeCC(path)
192
193 def printTypeHH(self, path):
194 code = self.symtab.codeFormatter()
195 code('''
196/** \\file ${{self.c_ident}}.hh
197 *
198 *
199 * Auto generated C++ code started by $__file__:$__line__
200 */
201
202#ifndef __${{self.c_ident}}_HH__
203#define __${{self.c_ident}}_HH__
204
205#include <iostream>
206
207#include "mem/ruby/common/Global.hh"
208''')
209
210 for dm in self.data_members.values():
211 if not dm.type.isPrimitive:
212 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
213
214 parent = ""
215 if "interface" in self:
216 code('#include "mem/protocol/$0.hh"', self["interface"])
217 parent = " : public %s" % self["interface"]
218
219 code('''
220$klass ${{self.c_ident}}$parent
221{
222 public:
223 ${{self.c_ident}}()
224 {
225''', klass="class")
226
227 code.indent()
228 if not self.isGlobal:
229 code.indent()
230 for dm in self.data_members.values():
231 ident = dm.ident
232 if "default" in dm:
233 # look for default value
234 code('m_$ident = ${{dm["default"]}}; // default for this field')
235 elif "default" in dm.type:
236 # Look for the type default
237 tid = dm.type.c_ident
238 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
239 else:
240 code('// m_$ident has no default')
241 code.dedent()
242 code('}')
243
244 # ******** Copy constructor ********
245 if not self.isGlobal:
246 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
247
248 # Call superclass constructor
249 if "interface" in self:
250 code(' : ${{self["interface"]}}(other)')
251
252 code('{')
253 code.indent()
254
255 for dm in self.data_members.values():
256 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
257
258 if self.isMessage:
259 code('proc_id = other.proc_id;')
260
261 code.dedent()
262 code('}')
263
264 # ******** Full init constructor ********
265 if not self.isGlobal:
266 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
267 for dm in self.data_members.itervalues() ]
268
269 if self.isMessage:
270 params.append('const unsigned local_proc_id')
271
272 params = ', '.join(params)
273 code('${{self.c_ident}}($params)')
274
275 # Call superclass constructor
276 if "interface" in self:
277 code(' : ${{self["interface"]}}()')
278
279 code('{')
280 code.indent()
281 for dm in self.data_members.values():
282 code('m_${{dm.ident}} = local_${{dm.ident}};')
283 if "nextLineCallHack" in dm:
284 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
285
286 if self.isMessage:
287 code('proc_id = local_proc_id;')
288
289 code.dedent()
290 code('}')
291
292 # create a static factory method and a clone member
293 code('''
294static ${{self.c_ident}}*
295create()
296{
297 return new ${{self.c_ident}}();
298}
299
300${{self.c_ident}}*
301clone() const
302{
303 return new ${{self.c_ident}}(*this);
304}
305''')
306
307 if not self.isGlobal:
308 # const Get methods for each field
309 code('// Const accessors methods for each field')
310 for dm in self.data_members.values():
311 code('''
312/** \\brief Const accessor method for ${{dm.ident}} field.
313 * \\return ${{dm.ident}} field
314 */
315const ${{dm.type.c_ident}}&
316get${{dm.ident}}() const
317{
318 return m_${{dm.ident}};
319}
320''')
321
322 # Non-const Get methods for each field
323 code('// Non const Accessors methods for each field')
324 for dm in self.data_members.values():
325 code('''
326/** \\brief Non-const accessor method for ${{dm.ident}} field.
327 * \\return ${{dm.ident}} field
328 */
329${{dm.type.c_ident}}&
330get${{dm.ident}}()
331{
332 return m_${{dm.ident}};
333}
334''')
335
336 #Set methods for each field
337 code('// Mutator methods for each field')
338 for dm in self.data_members.values():
339 code('''
340/** \\brief Mutator method for ${{dm.ident}} field */
341void
342set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
343{
344 m_${{dm.ident}} = local_${{dm.ident}};
345}
346''')
347
348 code('void print(std::ostream& out) const;')
349 code.dedent()
350 code(' //private:')
351 code.indent()
352
353 # Data members for each field
354 for dm in self.data_members.values():
355 if "abstract" not in dm:
356 const = ""
357 init = ""
358
359 # global structure
360 if self.isGlobal:
361 const = "static const "
362
363 # init value
364 if dm.init_code:
365 # only global structure can have init value here
366 assert self.isGlobal
367 init = " = %s" % (dm.init_code)
368
369 if "desc" in dm:
370 code('/** ${{dm["desc"]}} */')
371
372 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
373
374 if self.isMessage:
375 code('unsigned proc_id;')
376
377 code.dedent()
378 code('};')
379
380 code('''
381inline std::ostream&
382operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
383{
384 obj.print(out);
385 out << std::flush;
386 return out;
387}
388
389#endif // __${{self.c_ident}}_HH__
390''')
391
392 code.write(path, "%s.hh" % self.c_ident)
393
394 def printTypeCC(self, path):
395 code = self.symtab.codeFormatter()
396
397 code('''
398/** \\file ${{self.c_ident}}.cc
399 *
400 * Auto generated C++ code started by $__file__:$__line__
401 */
402
403#include <iostream>
404
405#include "mem/protocol/${{self.c_ident}}.hh"
406
407using namespace std;
408''')
409
410 code('''
411/** \\brief Print the state of this object */
412void
413${{self.c_ident}}::print(ostream& out) const
414{
415 out << "[${{self.c_ident}}: ";
416''')
417
418 # For each field
419 code.indent()
420 for dm in self.data_members.values():
421 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
422
423 if self.isMessage:
424 code('out << "Time = " << getTime() << " ";')
425 code.dedent()
426
427 # Trailer
428 code('''
429 out << "]";
430}''')
431
432 code.write(path, "%s.cc" % self.c_ident)
433
434 def printEnumHH(self, path):
435 code = self.symtab.codeFormatter()
436 code('''
437/** \\file ${{self.c_ident}}.hh
438 *
439 * Auto generated C++ code started by $__file__:$__line__
440 */
441
442#ifndef __${{self.c_ident}}_HH__
443#define __${{self.c_ident}}_HH__
444
445#include <iostream>
446#include <string>
447
448#include "mem/ruby/common/Global.hh"
449
450// Class definition
451/** \\enum ${{self.c_ident}}
452 * \\brief ${{self.desc}}
453 */
454enum ${{self.c_ident}} {
455 ${{self.c_ident}}_FIRST,
456''')
457
458 code.indent()
459 # For each field
460 for i,(ident,enum) in enumerate(self.enums.iteritems()):
461 desc = enum.get("desc", "No description avaliable")
462 if i == 0:
463 init = ' = %s_FIRST' % self.c_ident
464 else:
465 init = ''
466 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
467 code.dedent()
468 code('''
469 ${{self.c_ident}}_NUM
470};
471
472// Code to convert from a string to the enumeration
473${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
474
475// Code to convert state to a string
476std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
477
478// Code to increment an enumeration type
479${{self.c_ident}} &operator++(${{self.c_ident}} &e);
480''')
481
482 # MachineType hack used to set the base component id for each Machine
483 if self.isMachineType:
484 code('''
485int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
486MachineType ${{self.c_ident}}_from_base_level(int);
487int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
488int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
489''')
490
491 for enum in self.enums.itervalues():
492 code('#define MACHINETYPE_${{enum.ident}} 1')
493
494 # Trailer
495 code('''
496std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
497
498#endif // __${{self.c_ident}}_HH__
499''')
500
501 code.write(path, "%s.hh" % self.c_ident)
502
503 def printEnumCC(self, path):
504 code = self.symtab.codeFormatter()
505 code('''
506/** \\file ${{self.c_ident}}.hh
507 *
508 * Auto generated C++ code started by $__file__:$__line__
509 */
510
1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
2# Copyright (c) 2009 The Hewlett-Packard Development Company
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28from m5.util import orderdict
29
30from slicc.util import PairContainer
31from slicc.symbols.Symbol import Symbol
32
33class DataMember(PairContainer):
34 def __init__(self, ident, type, pairs, init_code):
35 super(DataMember, self).__init__(pairs)
36 self.ident = ident
37 self.type = type
38 self.init_code = init_code
39
40class Enumeration(PairContainer):
41 def __init__(self, ident, pairs):
42 super(Enumeration, self).__init__(pairs)
43 self.ident = ident
44
45class Method(object):
46 def __init__(self, return_type, param_types):
47 self.return_type = return_type
48 self.param_types = param_types
49
50class Type(Symbol):
51 def __init__(self, table, ident, location, pairs, machine=None):
52 super(Type, self).__init__(table, ident, location, pairs)
53 self.c_ident = ident
54 self.abstract_ident = ""
55 if machine:
56 if self.isExternal or self.isPrimitive:
57 if "external_name" in self:
58 self.c_ident = self["external_name"]
59 else:
60 # Append with machine name
61 self.c_ident = "%s_%s" % (machine, ident)
62
63 self.pairs.setdefault("desc", "No description avaliable")
64
65 # check for interface that this Type implements
66 if "interface" in self:
67 interface = self["interface"]
68 if interface in ("Message", "NetworkMessage"):
69 self["message"] = "yes"
70 if interface == "NetworkMessage":
71 self["networkmessage"] = "yes"
72
73 # FIXME - all of the following id comparisons are fragile hacks
74 if self.ident in ("CacheMemory", "NewCacheMemory",
75 "TLCCacheMemory", "DNUCACacheMemory",
76 "DNUCABankCacheMemory", "L2BankCacheMemory",
77 "CompressedCacheMemory", "PrefetchCacheMemory"):
78 self["cache"] = "yes"
79
80 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
81 self["tbe"] = "yes"
82
83 if self.ident == "NewTBETable":
84 self["newtbe"] = "yes"
85
86 if self.ident == "TimerTable":
87 self["timer"] = "yes"
88
89 if self.ident == "DirectoryMemory":
90 self["dir"] = "yes"
91
92 if self.ident == "PersistentTable":
93 self["persistent"] = "yes"
94
95 if self.ident == "Prefetcher":
96 self["prefetcher"] = "yes"
97
98 if self.ident == "DNUCA_Movement":
99 self["mover"] = "yes"
100
101 self.isMachineType = (ident == "MachineType")
102
103 self.data_members = orderdict()
104
105 # Methods
106 self.methods = {}
107
108 # Enums
109 self.enums = orderdict()
110
111 @property
112 def isPrimitive(self):
113 return "primitive" in self
114 @property
115 def isNetworkMessage(self):
116 return "networkmessage" in self
117 @property
118 def isMessage(self):
119 return "message" in self
120 @property
121 def isBuffer(self):
122 return "buffer" in self
123 @property
124 def isInPort(self):
125 return "inport" in self
126 @property
127 def isOutPort(self):
128 return "outport" in self
129 @property
130 def isEnumeration(self):
131 return "enumeration" in self
132 @property
133 def isExternal(self):
134 return "external" in self
135 @property
136 def isGlobal(self):
137 return "global" in self
138 @property
139 def isInterface(self):
140 return "interface" in self
141
142 # Return false on error
143 def dataMemberAdd(self, ident, type, pairs, init_code):
144 if ident in self.data_members:
145 return False
146
147 member = DataMember(ident, type, pairs, init_code)
148 self.data_members[ident] = member
149
150 return True
151
152 def dataMemberType(self, ident):
153 return self.data_members[ident].type
154
155 def methodId(self, name, param_type_vec):
156 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
157
158 def methodIdAbstract(self, name, param_type_vec):
159 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
160
161 def methodAdd(self, name, return_type, param_type_vec):
162 ident = self.methodId(name, param_type_vec)
163 if ident in self.methods:
164 return False
165
166 self.methods[ident] = Method(return_type, param_type_vec)
167 return True
168
169 def enumAdd(self, ident, pairs):
170 if ident in self.enums:
171 return False
172
173 self.enums[ident] = Enumeration(ident, pairs)
174
175 # Add default
176 if "default" not in self:
177 self["default"] = "%s_NUM" % self.c_ident
178
179 return True
180
181 def writeCodeFiles(self, path):
182 if self.isExternal:
183 # Do nothing
184 pass
185 elif self.isEnumeration:
186 self.printEnumHH(path)
187 self.printEnumCC(path)
188 else:
189 # User defined structs and messages
190 self.printTypeHH(path)
191 self.printTypeCC(path)
192
193 def printTypeHH(self, path):
194 code = self.symtab.codeFormatter()
195 code('''
196/** \\file ${{self.c_ident}}.hh
197 *
198 *
199 * Auto generated C++ code started by $__file__:$__line__
200 */
201
202#ifndef __${{self.c_ident}}_HH__
203#define __${{self.c_ident}}_HH__
204
205#include <iostream>
206
207#include "mem/ruby/common/Global.hh"
208''')
209
210 for dm in self.data_members.values():
211 if not dm.type.isPrimitive:
212 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
213
214 parent = ""
215 if "interface" in self:
216 code('#include "mem/protocol/$0.hh"', self["interface"])
217 parent = " : public %s" % self["interface"]
218
219 code('''
220$klass ${{self.c_ident}}$parent
221{
222 public:
223 ${{self.c_ident}}()
224 {
225''', klass="class")
226
227 code.indent()
228 if not self.isGlobal:
229 code.indent()
230 for dm in self.data_members.values():
231 ident = dm.ident
232 if "default" in dm:
233 # look for default value
234 code('m_$ident = ${{dm["default"]}}; // default for this field')
235 elif "default" in dm.type:
236 # Look for the type default
237 tid = dm.type.c_ident
238 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
239 else:
240 code('// m_$ident has no default')
241 code.dedent()
242 code('}')
243
244 # ******** Copy constructor ********
245 if not self.isGlobal:
246 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
247
248 # Call superclass constructor
249 if "interface" in self:
250 code(' : ${{self["interface"]}}(other)')
251
252 code('{')
253 code.indent()
254
255 for dm in self.data_members.values():
256 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
257
258 if self.isMessage:
259 code('proc_id = other.proc_id;')
260
261 code.dedent()
262 code('}')
263
264 # ******** Full init constructor ********
265 if not self.isGlobal:
266 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
267 for dm in self.data_members.itervalues() ]
268
269 if self.isMessage:
270 params.append('const unsigned local_proc_id')
271
272 params = ', '.join(params)
273 code('${{self.c_ident}}($params)')
274
275 # Call superclass constructor
276 if "interface" in self:
277 code(' : ${{self["interface"]}}()')
278
279 code('{')
280 code.indent()
281 for dm in self.data_members.values():
282 code('m_${{dm.ident}} = local_${{dm.ident}};')
283 if "nextLineCallHack" in dm:
284 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
285
286 if self.isMessage:
287 code('proc_id = local_proc_id;')
288
289 code.dedent()
290 code('}')
291
292 # create a static factory method and a clone member
293 code('''
294static ${{self.c_ident}}*
295create()
296{
297 return new ${{self.c_ident}}();
298}
299
300${{self.c_ident}}*
301clone() const
302{
303 return new ${{self.c_ident}}(*this);
304}
305''')
306
307 if not self.isGlobal:
308 # const Get methods for each field
309 code('// Const accessors methods for each field')
310 for dm in self.data_members.values():
311 code('''
312/** \\brief Const accessor method for ${{dm.ident}} field.
313 * \\return ${{dm.ident}} field
314 */
315const ${{dm.type.c_ident}}&
316get${{dm.ident}}() const
317{
318 return m_${{dm.ident}};
319}
320''')
321
322 # Non-const Get methods for each field
323 code('// Non const Accessors methods for each field')
324 for dm in self.data_members.values():
325 code('''
326/** \\brief Non-const accessor method for ${{dm.ident}} field.
327 * \\return ${{dm.ident}} field
328 */
329${{dm.type.c_ident}}&
330get${{dm.ident}}()
331{
332 return m_${{dm.ident}};
333}
334''')
335
336 #Set methods for each field
337 code('// Mutator methods for each field')
338 for dm in self.data_members.values():
339 code('''
340/** \\brief Mutator method for ${{dm.ident}} field */
341void
342set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
343{
344 m_${{dm.ident}} = local_${{dm.ident}};
345}
346''')
347
348 code('void print(std::ostream& out) const;')
349 code.dedent()
350 code(' //private:')
351 code.indent()
352
353 # Data members for each field
354 for dm in self.data_members.values():
355 if "abstract" not in dm:
356 const = ""
357 init = ""
358
359 # global structure
360 if self.isGlobal:
361 const = "static const "
362
363 # init value
364 if dm.init_code:
365 # only global structure can have init value here
366 assert self.isGlobal
367 init = " = %s" % (dm.init_code)
368
369 if "desc" in dm:
370 code('/** ${{dm["desc"]}} */')
371
372 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
373
374 if self.isMessage:
375 code('unsigned proc_id;')
376
377 code.dedent()
378 code('};')
379
380 code('''
381inline std::ostream&
382operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
383{
384 obj.print(out);
385 out << std::flush;
386 return out;
387}
388
389#endif // __${{self.c_ident}}_HH__
390''')
391
392 code.write(path, "%s.hh" % self.c_ident)
393
394 def printTypeCC(self, path):
395 code = self.symtab.codeFormatter()
396
397 code('''
398/** \\file ${{self.c_ident}}.cc
399 *
400 * Auto generated C++ code started by $__file__:$__line__
401 */
402
403#include <iostream>
404
405#include "mem/protocol/${{self.c_ident}}.hh"
406
407using namespace std;
408''')
409
410 code('''
411/** \\brief Print the state of this object */
412void
413${{self.c_ident}}::print(ostream& out) const
414{
415 out << "[${{self.c_ident}}: ";
416''')
417
418 # For each field
419 code.indent()
420 for dm in self.data_members.values():
421 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
422
423 if self.isMessage:
424 code('out << "Time = " << getTime() << " ";')
425 code.dedent()
426
427 # Trailer
428 code('''
429 out << "]";
430}''')
431
432 code.write(path, "%s.cc" % self.c_ident)
433
434 def printEnumHH(self, path):
435 code = self.symtab.codeFormatter()
436 code('''
437/** \\file ${{self.c_ident}}.hh
438 *
439 * Auto generated C++ code started by $__file__:$__line__
440 */
441
442#ifndef __${{self.c_ident}}_HH__
443#define __${{self.c_ident}}_HH__
444
445#include <iostream>
446#include <string>
447
448#include "mem/ruby/common/Global.hh"
449
450// Class definition
451/** \\enum ${{self.c_ident}}
452 * \\brief ${{self.desc}}
453 */
454enum ${{self.c_ident}} {
455 ${{self.c_ident}}_FIRST,
456''')
457
458 code.indent()
459 # For each field
460 for i,(ident,enum) in enumerate(self.enums.iteritems()):
461 desc = enum.get("desc", "No description avaliable")
462 if i == 0:
463 init = ' = %s_FIRST' % self.c_ident
464 else:
465 init = ''
466 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
467 code.dedent()
468 code('''
469 ${{self.c_ident}}_NUM
470};
471
472// Code to convert from a string to the enumeration
473${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
474
475// Code to convert state to a string
476std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
477
478// Code to increment an enumeration type
479${{self.c_ident}} &operator++(${{self.c_ident}} &e);
480''')
481
482 # MachineType hack used to set the base component id for each Machine
483 if self.isMachineType:
484 code('''
485int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
486MachineType ${{self.c_ident}}_from_base_level(int);
487int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
488int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
489''')
490
491 for enum in self.enums.itervalues():
492 code('#define MACHINETYPE_${{enum.ident}} 1')
493
494 # Trailer
495 code('''
496std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
497
498#endif // __${{self.c_ident}}_HH__
499''')
500
501 code.write(path, "%s.hh" % self.c_ident)
502
503 def printEnumCC(self, path):
504 code = self.symtab.codeFormatter()
505 code('''
506/** \\file ${{self.c_ident}}.hh
507 *
508 * Auto generated C++ code started by $__file__:$__line__
509 */
510
511#include <cassert>
511#include <iostream>
512#include <string>
513
514#include "base/misc.hh"
515#include "mem/protocol/${{self.c_ident}}.hh"
516
517using namespace std;
518
519''')
520
521 if self.isMachineType:
522 for enum in self.enums.itervalues():
523 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
524
525 code('''
526// Code for output operator
527ostream&
528operator<<(ostream& out, const ${{self.c_ident}}& obj)
529{
530 out << ${{self.c_ident}}_to_string(obj);
531 out << flush;
532 return out;
533}
534
535// Code to convert state to a string
536string
537${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
538{
539 switch(obj) {
540''')
541
542 # For each field
543 code.indent()
544 for enum in self.enums.itervalues():
545 code(' case ${{self.c_ident}}_${{enum.ident}}:')
546 code(' return "${{enum.ident}}";')
547 code.dedent()
548
549 # Trailer
550 code('''
551 default:
552 panic("Invalid range for type ${{self.c_ident}}");
553 }
554}
555
556// Code to convert from a string to the enumeration
557${{self.c_ident}}
558string_to_${{self.c_ident}}(const string& str)
559{
560''')
561
562 # For each field
563 start = ""
564 code.indent()
565 for enum in self.enums.itervalues():
566 code('${start}if (str == "${{enum.ident}}") {')
567 code(' return ${{self.c_ident}}_${{enum.ident}};')
568 start = "} else "
569 code.dedent()
570
571 code('''
572 } else {
573 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
574 }
575}
576
577// Code to increment an enumeration type
578${{self.c_ident}}&
579operator++(${{self.c_ident}}& e)
580{
581 assert(e < ${{self.c_ident}}_NUM);
582 return e = ${{self.c_ident}}(e+1);
583}
584''')
585
586 # MachineType hack used to set the base level and number of
587 # components for each Machine
588 if self.isMachineType:
589 code('''
590/** \\brief returns the base vector index for each machine type to be
591 * used by NetDest
592 *
593 * \\return the base vector index for each machine type to be used by NetDest
594 * \\see NetDest.hh
595 */
596int
597${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
598{
599 switch(obj) {
600''')
601
602 # For each field
603 code.indent()
604 for i,enum in enumerate(self.enums.itervalues()):
605 code(' case ${{self.c_ident}}_${{enum.ident}}:')
606 code(' return $i;')
607 code.dedent()
608
609 # total num
610 code('''
611 case ${{self.c_ident}}_NUM:
612 return ${{len(self.enums)}};
613
614 default:
615 panic("Invalid range for type ${{self.c_ident}}");
616 }
617}
618
619/** \\brief returns the machine type for each base vector index used by NetDest
620 *
621 * \\return the MachineType
622 */
623MachineType
624${{self.c_ident}}_from_base_level(int type)
625{
626 switch(type) {
627''')
628
629 # For each field
630 code.indent()
631 for i,enum in enumerate(self.enums.itervalues()):
632 code(' case $i:')
633 code(' return ${{self.c_ident}}_${{enum.ident}};')
634 code.dedent()
635
636 # Trailer
637 code('''
638 default:
639 panic("Invalid range for type ${{self.c_ident}}");
640 }
641}
642
643/** \\brief The return value indicates the number of components created
644 * before a particular machine\'s components
645 *
646 * \\return the base number of components for each machine
647 */
648int
649${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
650{
651 int base = 0;
652 switch(obj) {
653''')
654
655 # For each field
656 code.indent()
657 code(' case ${{self.c_ident}}_NUM:')
658 for enum in reversed(self.enums.values()):
659 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
660 code(' case ${{self.c_ident}}_${{enum.ident}}:')
661 code(' break;')
662 code.dedent()
663
664 code('''
665 default:
666 panic("Invalid range for type ${{self.c_ident}}");
667 }
668
669 return base;
670}
671
672/** \\brief returns the total number of components for each machine
673 * \\return the total number of components for each machine
674 */
675int
676${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
677{
678 switch(obj) {
679''')
680
681 # For each field
682 for enum in self.enums.itervalues():
683 code('''
684 case ${{self.c_ident}}_${{enum.ident}}:
685 return ${{enum.ident}}_Controller::getNumControllers();
686''')
687
688 # total num
689 code('''
690 case ${{self.c_ident}}_NUM:
691 default:
692 panic("Invalid range for type ${{self.c_ident}}");
693 }
694}
695''')
696
697 # Write the file
698 code.write(path, "%s.cc" % self.c_ident)
699
700__all__ = [ "Type" ]
512#include <iostream>
513#include <string>
514
515#include "base/misc.hh"
516#include "mem/protocol/${{self.c_ident}}.hh"
517
518using namespace std;
519
520''')
521
522 if self.isMachineType:
523 for enum in self.enums.itervalues():
524 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
525
526 code('''
527// Code for output operator
528ostream&
529operator<<(ostream& out, const ${{self.c_ident}}& obj)
530{
531 out << ${{self.c_ident}}_to_string(obj);
532 out << flush;
533 return out;
534}
535
536// Code to convert state to a string
537string
538${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
539{
540 switch(obj) {
541''')
542
543 # For each field
544 code.indent()
545 for enum in self.enums.itervalues():
546 code(' case ${{self.c_ident}}_${{enum.ident}}:')
547 code(' return "${{enum.ident}}";')
548 code.dedent()
549
550 # Trailer
551 code('''
552 default:
553 panic("Invalid range for type ${{self.c_ident}}");
554 }
555}
556
557// Code to convert from a string to the enumeration
558${{self.c_ident}}
559string_to_${{self.c_ident}}(const string& str)
560{
561''')
562
563 # For each field
564 start = ""
565 code.indent()
566 for enum in self.enums.itervalues():
567 code('${start}if (str == "${{enum.ident}}") {')
568 code(' return ${{self.c_ident}}_${{enum.ident}};')
569 start = "} else "
570 code.dedent()
571
572 code('''
573 } else {
574 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
575 }
576}
577
578// Code to increment an enumeration type
579${{self.c_ident}}&
580operator++(${{self.c_ident}}& e)
581{
582 assert(e < ${{self.c_ident}}_NUM);
583 return e = ${{self.c_ident}}(e+1);
584}
585''')
586
587 # MachineType hack used to set the base level and number of
588 # components for each Machine
589 if self.isMachineType:
590 code('''
591/** \\brief returns the base vector index for each machine type to be
592 * used by NetDest
593 *
594 * \\return the base vector index for each machine type to be used by NetDest
595 * \\see NetDest.hh
596 */
597int
598${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
599{
600 switch(obj) {
601''')
602
603 # For each field
604 code.indent()
605 for i,enum in enumerate(self.enums.itervalues()):
606 code(' case ${{self.c_ident}}_${{enum.ident}}:')
607 code(' return $i;')
608 code.dedent()
609
610 # total num
611 code('''
612 case ${{self.c_ident}}_NUM:
613 return ${{len(self.enums)}};
614
615 default:
616 panic("Invalid range for type ${{self.c_ident}}");
617 }
618}
619
620/** \\brief returns the machine type for each base vector index used by NetDest
621 *
622 * \\return the MachineType
623 */
624MachineType
625${{self.c_ident}}_from_base_level(int type)
626{
627 switch(type) {
628''')
629
630 # For each field
631 code.indent()
632 for i,enum in enumerate(self.enums.itervalues()):
633 code(' case $i:')
634 code(' return ${{self.c_ident}}_${{enum.ident}};')
635 code.dedent()
636
637 # Trailer
638 code('''
639 default:
640 panic("Invalid range for type ${{self.c_ident}}");
641 }
642}
643
644/** \\brief The return value indicates the number of components created
645 * before a particular machine\'s components
646 *
647 * \\return the base number of components for each machine
648 */
649int
650${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
651{
652 int base = 0;
653 switch(obj) {
654''')
655
656 # For each field
657 code.indent()
658 code(' case ${{self.c_ident}}_NUM:')
659 for enum in reversed(self.enums.values()):
660 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
661 code(' case ${{self.c_ident}}_${{enum.ident}}:')
662 code(' break;')
663 code.dedent()
664
665 code('''
666 default:
667 panic("Invalid range for type ${{self.c_ident}}");
668 }
669
670 return base;
671}
672
673/** \\brief returns the total number of components for each machine
674 * \\return the total number of components for each machine
675 */
676int
677${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
678{
679 switch(obj) {
680''')
681
682 # For each field
683 for enum in self.enums.itervalues():
684 code('''
685 case ${{self.c_ident}}_${{enum.ident}}:
686 return ${{enum.ident}}_Controller::getNumControllers();
687''')
688
689 # total num
690 code('''
691 case ${{self.c_ident}}_NUM:
692 default:
693 panic("Invalid range for type ${{self.c_ident}}");
694 }
695}
696''')
697
698 # Write the file
699 code.write(path, "%s.cc" % self.c_ident)
700
701__all__ = [ "Type" ]