Type.py (6862:3d308cbd1657) Type.py (6877:2a1a3d916ca8)
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 code_formatter, 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 if machine:
55 if self.isExternal or self.isPrimitive:
56 if "external_name" in self:
57 self.c_ident = self["external_name"]
58 else:
59 # Append with machine name
60 self.c_ident = "%s_%s" % (machine, ident)
61
62 self.pairs.setdefault("desc", "No description avaliable")
63
64 # check for interface that this Type implements
65 if "interface" in self:
66 interface = self["interface"]
67 if interface in ("Message", "NetworkMessage"):
68 self["message"] = "yes"
69 if interface == "NetworkMessage":
70 self["networkmessage"] = "yes"
71
72 # FIXME - all of the following id comparisons are fragile hacks
73 if self.ident in ("CacheMemory", "NewCacheMemory",
74 "TLCCacheMemory", "DNUCACacheMemory",
75 "DNUCABankCacheMemory", "L2BankCacheMemory",
76 "CompressedCacheMemory", "PrefetchCacheMemory"):
77 self["cache"] = "yes"
78
79 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
80 self["tbe"] = "yes"
81
82 if self.ident == "NewTBETable":
83 self["newtbe"] = "yes"
84
85 if self.ident == "TimerTable":
86 self["timer"] = "yes"
87
88 if self.ident == "DirectoryMemory":
89 self["dir"] = "yes"
90
91 if self.ident == "PersistentTable":
92 self["persistent"] = "yes"
93
94 if self.ident == "Prefetcher":
95 self["prefetcher"] = "yes"
96
97 if self.ident == "DNUCA_Movement":
98 self["mover"] = "yes"
99
100 self.isMachineType = (ident == "MachineType")
101
102 self.data_members = orderdict()
103
104 # Methods
105 self.methods = {}
106
107 # Enums
108 self.enums = orderdict()
109
110 @property
111 def isPrimitive(self):
112 return "primitive" in self
113 @property
114 def isNetworkMessage(self):
115 return "networkmessage" in self
116 @property
117 def isMessage(self):
118 return "message" in self
119 @property
120 def isBuffer(self):
121 return "buffer" in self
122 @property
123 def isInPort(self):
124 return "inport" in self
125 @property
126 def isOutPort(self):
127 return "outport" in self
128 @property
129 def isEnumeration(self):
130 return "enumeration" in self
131 @property
132 def isExternal(self):
133 return "external" in self
134 @property
135 def isGlobal(self):
136 return "global" in self
137 @property
138 def isInterface(self):
139 return "interface" in self
140
141 # Return false on error
142 def dataMemberAdd(self, ident, type, pairs, init_code):
143 if ident in self.data_members:
144 return False
145
146 member = DataMember(ident, type, pairs, init_code)
147 self.data_members[ident] = member
148
149 return True
150
151 def dataMemberType(self, ident):
152 return self.data_members[ident].type
153
154 def methodId(self, name, param_type_vec):
155 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
156
157 def methodAdd(self, name, return_type, param_type_vec):
158 ident = self.methodId(name, param_type_vec)
159 if ident in self.methods:
160 return False
161
162 self.methods[ident] = Method(return_type, param_type_vec)
163 return True
164
165 def enumAdd(self, ident, pairs):
166 if ident in self.enums:
167 return False
168
169 self.enums[ident] = Enumeration(ident, pairs)
170
171 # Add default
172 if "default" not in self:
173 self["default"] = "%s_NUM" % self.c_ident
174
175 return True
176
177 def writeCodeFiles(self, path):
178 if self.isExternal:
179 # Do nothing
180 pass
181 elif self.isEnumeration:
182 self.printEnumHH(path)
183 self.printEnumCC(path)
184 else:
185 # User defined structs and messages
186 self.printTypeHH(path)
187 self.printTypeCC(path)
188
189 def printTypeHH(self, path):
190 code = code_formatter()
191 code('''
192/** \\file ${{self.c_ident}}.hh
193 *
194 *
195 * Auto generated C++ code started by $__file__:$__line__
196 */
197
198#ifndef ${{self.c_ident}}_H
199#define ${{self.c_ident}}_H
200
201#include "mem/ruby/common/Global.hh"
202#include "mem/gems_common/Allocator.hh"
203''')
204
205 for dm in self.data_members.values():
206 if not dm.type.isPrimitive:
207 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
208
209 parent = ""
210 if "interface" in self:
211 code('#include "mem/protocol/$0.hh"', self["interface"])
212 parent = " : public %s" % self["interface"]
213
214 code('''
215$klass ${{self.c_ident}}$parent {
216 public:
217 ${{self.c_ident}}()
218''', klass="class")
219
220 # Call superclass constructor
221 if "interface" in self:
222 code(' : ${{self["interface"]}}()')
223
224 code.indent()
225 code("{")
226 if not self.isGlobal:
227 code.indent()
228 for dm in self.data_members.values():
229 ident = dm.ident
230 if "default" in dm:
231 # look for default value
232 code('m_$ident = ${{dm["default"]}}; // default for this field')
233 elif "default" in dm.type:
234 # Look for the type default
235 tid = dm.type.c_ident
236 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
237 else:
238 code('// m_$ident has no default')
239 code.dedent()
240 code('}')
241
242 # ******** Default destructor ********
243 code('~${{self.c_ident}}() { };')
244
245 # ******** Full init constructor ********
246 if not self.isGlobal:
247 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
248 for dm in self.data_members.itervalues() ]
249
250 if self.isMessage:
251 params.append('const unsigned local_proc_id')
252
253 params = ', '.join(params)
254 code('${{self.c_ident}}($params)')
255
256 # Call superclass constructor
257 if "interface" in self:
258 code(' : ${{self["interface"]}}()')
259
260 code('{')
261 code.indent()
262 for dm in self.data_members.values():
263 code('m_${{dm.ident}} = local_${{dm.ident}};')
264 if "nextLineCallHack" in dm:
265 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
266
267 if self.isMessage:
268 code('proc_id = local_proc_id;')
269
270 code.dedent()
271 code('}')
272
273 # create a static factory method
274 if "interface" in self:
275 code('''
276static ${{self["interface"]}}* create() {
277 return new ${{self.c_ident}}();
278}
279''')
280
281 # ******** Message member functions ********
282 # FIXME: those should be moved into slicc file, slicc should
283 # support more of the c++ class inheritance
284
285 if self.isMessage:
286 code('''
287Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }
288void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }
289static Allocator<${{self.c_ident}}>* s_allocator_ptr;
290static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }}
291''')
292
293 if not self.isGlobal:
294 # const Get methods for each field
295 code('// Const accessors methods for each field')
296 for dm in self.data_members.values():
297 code('''
298/** \\brief Const accessor method for ${{dm.ident}} field.
299 * \\return ${{dm.ident}} field
300 */
301const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; }
302''')
303
304 # Non-const Get methods for each field
305 code('// Non const Accessors methods for each field')
306 for dm in self.data_members.values():
307 code('''
308/** \\brief Non-const accessor method for ${{dm.ident}} field.
309 * \\return ${{dm.ident}} field
310 */
311${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; }
312''')
313
314 #Set methods for each field
315 code('// Mutator methods for each field')
316 for dm in self.data_members.values():
317 code('''
318/** \\brief Mutator method for ${{dm.ident}} field */
319void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; }
320''')
321
322 code('void print(ostream& out) const;')
323 code.dedent()
324 code(' //private:')
325 code.indent()
326
327 # Data members for each field
328 for dm in self.data_members.values():
329 if "abstract" not in dm:
330 const = ""
331 init = ""
332
333 # global structure
334 if self.isGlobal:
335 const = "static const "
336
337 # init value
338 if dm.init_code:
339 # only global structure can have init value here
340 assert self.isGlobal
341 init = " = %s" % (dm.init_code)
342
343 desc = ""
344 if "desc" in dm:
345 desc = '/**< %s */' % dm["desc"]
346
347 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc')
348
349 if self.isMessage:
350 code('unsigned proc_id;')
351
352 code.dedent()
353 code('};')
354
355 code('''
356// Output operator declaration
357ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
358
359// Output operator definition
360extern inline
361ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
362{
363 obj.print(out);
364 out << flush;
365 return out;
366}
367
368#endif // ${{self.c_ident}}_H
369''')
370
371 code.write(path, "%s.hh" % self.c_ident)
372
373 def printTypeCC(self, path):
374 code = code_formatter()
375
376 code('''
377/** \\file ${{self.c_ident}}.cc
378 *
379 * Auto generated C++ code started by $__file__:$__line__
380 */
381
382#include "mem/protocol/${{self.c_ident}}.hh"
383''')
384
385 if self.isMessage:
386 code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
387 code('''
388/** \\brief Print the state of this object */
389void ${{self.c_ident}}::print(ostream& out) const
390{
391 out << "[${{self.c_ident}}: ";
392''')
393
394 # For each field
395 code.indent()
396 for dm in self.data_members.values():
397 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
398
399 if self.isMessage:
400 code('out << "Time = " << getTime() << " ";')
401 code.dedent()
402
403 # Trailer
404 code('''
405 out << "]";
406}''')
407
408 code.write(path, "%s.cc" % self.c_ident)
409
410 def printEnumHH(self, path):
411 code = code_formatter()
412 code('''
413/** \\file ${{self.c_ident}}.hh
414 *
415 * Auto generated C++ code started by $__file__:$__line__
416 */
417#ifndef ${{self.c_ident}}_H
418#define ${{self.c_ident}}_H
419
420#include "mem/ruby/common/Global.hh"
421
422/** \\enum ${{self.c_ident}}
423 * \\brief ${{self.desc}}
424 */
425enum ${{self.c_ident}} {
426 ${{self.c_ident}}_FIRST,
427''')
428
429 code.indent()
430 # For each field
431 for i,(ident,enum) in enumerate(self.enums.iteritems()):
432 desc = enum.get("desc", "No description avaliable")
433 if i == 0:
434 init = ' = %s_FIRST' % self.c_ident
435 else:
436 init = ''
437 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
438 code.dedent()
439 code('''
440 ${{self.c_ident}}_NUM
441};
442${{self.c_ident}} string_to_${{self.c_ident}}(const string& str);
443string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
444${{self.c_ident}} &operator++(${{self.c_ident}} &e);
445''')
446
447 # MachineType hack used to set the base component id for each Machine
448 if self.isMachineType:
449 code('''
450int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
451MachineType ${{self.c_ident}}_from_base_level(int);
452int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
453int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
454''')
455
456 for enum in self.enums.itervalues():
457 code('#define MACHINETYPE_${{enum.ident}} 1')
458
459 # Trailer
460 code('''
461ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
462
463#endif // ${{self.c_ident}}_H
464''')
465
466 code.write(path, "%s.hh" % self.c_ident)
467
468 def printEnumCC(self, path):
469 code = code_formatter()
470 code('''
471/** \\file ${{self.c_ident}}.hh
472 *
473 * Auto generated C++ code started by $__file__:$__line__
474 */
475
476#include "mem/protocol/${{self.c_ident}}.hh"
477
478''')
479
480 if self.isMachineType:
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 code_formatter, 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 if machine:
55 if self.isExternal or self.isPrimitive:
56 if "external_name" in self:
57 self.c_ident = self["external_name"]
58 else:
59 # Append with machine name
60 self.c_ident = "%s_%s" % (machine, ident)
61
62 self.pairs.setdefault("desc", "No description avaliable")
63
64 # check for interface that this Type implements
65 if "interface" in self:
66 interface = self["interface"]
67 if interface in ("Message", "NetworkMessage"):
68 self["message"] = "yes"
69 if interface == "NetworkMessage":
70 self["networkmessage"] = "yes"
71
72 # FIXME - all of the following id comparisons are fragile hacks
73 if self.ident in ("CacheMemory", "NewCacheMemory",
74 "TLCCacheMemory", "DNUCACacheMemory",
75 "DNUCABankCacheMemory", "L2BankCacheMemory",
76 "CompressedCacheMemory", "PrefetchCacheMemory"):
77 self["cache"] = "yes"
78
79 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
80 self["tbe"] = "yes"
81
82 if self.ident == "NewTBETable":
83 self["newtbe"] = "yes"
84
85 if self.ident == "TimerTable":
86 self["timer"] = "yes"
87
88 if self.ident == "DirectoryMemory":
89 self["dir"] = "yes"
90
91 if self.ident == "PersistentTable":
92 self["persistent"] = "yes"
93
94 if self.ident == "Prefetcher":
95 self["prefetcher"] = "yes"
96
97 if self.ident == "DNUCA_Movement":
98 self["mover"] = "yes"
99
100 self.isMachineType = (ident == "MachineType")
101
102 self.data_members = orderdict()
103
104 # Methods
105 self.methods = {}
106
107 # Enums
108 self.enums = orderdict()
109
110 @property
111 def isPrimitive(self):
112 return "primitive" in self
113 @property
114 def isNetworkMessage(self):
115 return "networkmessage" in self
116 @property
117 def isMessage(self):
118 return "message" in self
119 @property
120 def isBuffer(self):
121 return "buffer" in self
122 @property
123 def isInPort(self):
124 return "inport" in self
125 @property
126 def isOutPort(self):
127 return "outport" in self
128 @property
129 def isEnumeration(self):
130 return "enumeration" in self
131 @property
132 def isExternal(self):
133 return "external" in self
134 @property
135 def isGlobal(self):
136 return "global" in self
137 @property
138 def isInterface(self):
139 return "interface" in self
140
141 # Return false on error
142 def dataMemberAdd(self, ident, type, pairs, init_code):
143 if ident in self.data_members:
144 return False
145
146 member = DataMember(ident, type, pairs, init_code)
147 self.data_members[ident] = member
148
149 return True
150
151 def dataMemberType(self, ident):
152 return self.data_members[ident].type
153
154 def methodId(self, name, param_type_vec):
155 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
156
157 def methodAdd(self, name, return_type, param_type_vec):
158 ident = self.methodId(name, param_type_vec)
159 if ident in self.methods:
160 return False
161
162 self.methods[ident] = Method(return_type, param_type_vec)
163 return True
164
165 def enumAdd(self, ident, pairs):
166 if ident in self.enums:
167 return False
168
169 self.enums[ident] = Enumeration(ident, pairs)
170
171 # Add default
172 if "default" not in self:
173 self["default"] = "%s_NUM" % self.c_ident
174
175 return True
176
177 def writeCodeFiles(self, path):
178 if self.isExternal:
179 # Do nothing
180 pass
181 elif self.isEnumeration:
182 self.printEnumHH(path)
183 self.printEnumCC(path)
184 else:
185 # User defined structs and messages
186 self.printTypeHH(path)
187 self.printTypeCC(path)
188
189 def printTypeHH(self, path):
190 code = code_formatter()
191 code('''
192/** \\file ${{self.c_ident}}.hh
193 *
194 *
195 * Auto generated C++ code started by $__file__:$__line__
196 */
197
198#ifndef ${{self.c_ident}}_H
199#define ${{self.c_ident}}_H
200
201#include "mem/ruby/common/Global.hh"
202#include "mem/gems_common/Allocator.hh"
203''')
204
205 for dm in self.data_members.values():
206 if not dm.type.isPrimitive:
207 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
208
209 parent = ""
210 if "interface" in self:
211 code('#include "mem/protocol/$0.hh"', self["interface"])
212 parent = " : public %s" % self["interface"]
213
214 code('''
215$klass ${{self.c_ident}}$parent {
216 public:
217 ${{self.c_ident}}()
218''', klass="class")
219
220 # Call superclass constructor
221 if "interface" in self:
222 code(' : ${{self["interface"]}}()')
223
224 code.indent()
225 code("{")
226 if not self.isGlobal:
227 code.indent()
228 for dm in self.data_members.values():
229 ident = dm.ident
230 if "default" in dm:
231 # look for default value
232 code('m_$ident = ${{dm["default"]}}; // default for this field')
233 elif "default" in dm.type:
234 # Look for the type default
235 tid = dm.type.c_ident
236 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
237 else:
238 code('// m_$ident has no default')
239 code.dedent()
240 code('}')
241
242 # ******** Default destructor ********
243 code('~${{self.c_ident}}() { };')
244
245 # ******** Full init constructor ********
246 if not self.isGlobal:
247 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
248 for dm in self.data_members.itervalues() ]
249
250 if self.isMessage:
251 params.append('const unsigned local_proc_id')
252
253 params = ', '.join(params)
254 code('${{self.c_ident}}($params)')
255
256 # Call superclass constructor
257 if "interface" in self:
258 code(' : ${{self["interface"]}}()')
259
260 code('{')
261 code.indent()
262 for dm in self.data_members.values():
263 code('m_${{dm.ident}} = local_${{dm.ident}};')
264 if "nextLineCallHack" in dm:
265 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
266
267 if self.isMessage:
268 code('proc_id = local_proc_id;')
269
270 code.dedent()
271 code('}')
272
273 # create a static factory method
274 if "interface" in self:
275 code('''
276static ${{self["interface"]}}* create() {
277 return new ${{self.c_ident}}();
278}
279''')
280
281 # ******** Message member functions ********
282 # FIXME: those should be moved into slicc file, slicc should
283 # support more of the c++ class inheritance
284
285 if self.isMessage:
286 code('''
287Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }
288void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }
289static Allocator<${{self.c_ident}}>* s_allocator_ptr;
290static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }}
291''')
292
293 if not self.isGlobal:
294 # const Get methods for each field
295 code('// Const accessors methods for each field')
296 for dm in self.data_members.values():
297 code('''
298/** \\brief Const accessor method for ${{dm.ident}} field.
299 * \\return ${{dm.ident}} field
300 */
301const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; }
302''')
303
304 # Non-const Get methods for each field
305 code('// Non const Accessors methods for each field')
306 for dm in self.data_members.values():
307 code('''
308/** \\brief Non-const accessor method for ${{dm.ident}} field.
309 * \\return ${{dm.ident}} field
310 */
311${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; }
312''')
313
314 #Set methods for each field
315 code('// Mutator methods for each field')
316 for dm in self.data_members.values():
317 code('''
318/** \\brief Mutator method for ${{dm.ident}} field */
319void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; }
320''')
321
322 code('void print(ostream& out) const;')
323 code.dedent()
324 code(' //private:')
325 code.indent()
326
327 # Data members for each field
328 for dm in self.data_members.values():
329 if "abstract" not in dm:
330 const = ""
331 init = ""
332
333 # global structure
334 if self.isGlobal:
335 const = "static const "
336
337 # init value
338 if dm.init_code:
339 # only global structure can have init value here
340 assert self.isGlobal
341 init = " = %s" % (dm.init_code)
342
343 desc = ""
344 if "desc" in dm:
345 desc = '/**< %s */' % dm["desc"]
346
347 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc')
348
349 if self.isMessage:
350 code('unsigned proc_id;')
351
352 code.dedent()
353 code('};')
354
355 code('''
356// Output operator declaration
357ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
358
359// Output operator definition
360extern inline
361ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
362{
363 obj.print(out);
364 out << flush;
365 return out;
366}
367
368#endif // ${{self.c_ident}}_H
369''')
370
371 code.write(path, "%s.hh" % self.c_ident)
372
373 def printTypeCC(self, path):
374 code = code_formatter()
375
376 code('''
377/** \\file ${{self.c_ident}}.cc
378 *
379 * Auto generated C++ code started by $__file__:$__line__
380 */
381
382#include "mem/protocol/${{self.c_ident}}.hh"
383''')
384
385 if self.isMessage:
386 code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
387 code('''
388/** \\brief Print the state of this object */
389void ${{self.c_ident}}::print(ostream& out) const
390{
391 out << "[${{self.c_ident}}: ";
392''')
393
394 # For each field
395 code.indent()
396 for dm in self.data_members.values():
397 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
398
399 if self.isMessage:
400 code('out << "Time = " << getTime() << " ";')
401 code.dedent()
402
403 # Trailer
404 code('''
405 out << "]";
406}''')
407
408 code.write(path, "%s.cc" % self.c_ident)
409
410 def printEnumHH(self, path):
411 code = code_formatter()
412 code('''
413/** \\file ${{self.c_ident}}.hh
414 *
415 * Auto generated C++ code started by $__file__:$__line__
416 */
417#ifndef ${{self.c_ident}}_H
418#define ${{self.c_ident}}_H
419
420#include "mem/ruby/common/Global.hh"
421
422/** \\enum ${{self.c_ident}}
423 * \\brief ${{self.desc}}
424 */
425enum ${{self.c_ident}} {
426 ${{self.c_ident}}_FIRST,
427''')
428
429 code.indent()
430 # For each field
431 for i,(ident,enum) in enumerate(self.enums.iteritems()):
432 desc = enum.get("desc", "No description avaliable")
433 if i == 0:
434 init = ' = %s_FIRST' % self.c_ident
435 else:
436 init = ''
437 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
438 code.dedent()
439 code('''
440 ${{self.c_ident}}_NUM
441};
442${{self.c_ident}} string_to_${{self.c_ident}}(const string& str);
443string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
444${{self.c_ident}} &operator++(${{self.c_ident}} &e);
445''')
446
447 # MachineType hack used to set the base component id for each Machine
448 if self.isMachineType:
449 code('''
450int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
451MachineType ${{self.c_ident}}_from_base_level(int);
452int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
453int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
454''')
455
456 for enum in self.enums.itervalues():
457 code('#define MACHINETYPE_${{enum.ident}} 1')
458
459 # Trailer
460 code('''
461ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
462
463#endif // ${{self.c_ident}}_H
464''')
465
466 code.write(path, "%s.hh" % self.c_ident)
467
468 def printEnumCC(self, path):
469 code = code_formatter()
470 code('''
471/** \\file ${{self.c_ident}}.hh
472 *
473 * Auto generated C++ code started by $__file__:$__line__
474 */
475
476#include "mem/protocol/${{self.c_ident}}.hh"
477
478''')
479
480 if self.isMachineType:
481 code('#include "mem/protocol/ControllerFactory.hh"')
482 for enum in self.enums.itervalues():
483 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
484
485 code('''
486ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
487{
488 out << ${{self.c_ident}}_to_string(obj);
489 out << flush;
490 return out;
491}
492
493string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
494{
495 switch(obj) {
496''')
497
498 # For each field
499 code.indent()
500 for enum in self.enums.itervalues():
501 code(' case ${{self.c_ident}}_${{enum.ident}}:')
502 code(' return "${{enum.ident}}";')
503 code.dedent()
504
505 # Trailer
506 code('''
507 default:
508 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
509 return "";
510 }
511}
512
513${{self.c_ident}} string_to_${{self.c_ident}}(const string& str)
514{
515''')
516
517 # For each field
518 code.indent()
519 code("if (false) {")
520 start = "} else "
521 for enum in self.enums.itervalues():
522 code('${start}if (str == "${{enum.ident}}") {')
523 code(' return ${{self.c_ident}}_${{enum.ident}};')
524 code.dedent()
525
526 code('''
527 } else {
528 WARN_EXPR(str);
529 ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
530 }
531}
532
533${{self.c_ident}}& operator++(${{self.c_ident}}& e) {
534 assert(e < ${{self.c_ident}}_NUM);
535 return e = ${{self.c_ident}}(e+1);
536}
537''')
538
539 # MachineType hack used to set the base level and number of
540 # components for each Machine
541 if self.isMachineType:
542 code('''
543/** \\brief returns the base vector index for each machine type to be used by NetDest
544 *
545 * \\return the base vector index for each machine type to be used by NetDest
546 * \\see NetDest.hh
547 */
548int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
549{
550 switch(obj) {
551''')
552
553 # For each field
554 code.indent()
555 for i,enum in enumerate(self.enums.itervalues()):
556 code(' case ${{self.c_ident}}_${{enum.ident}}:')
557 code(' return $i;')
558 code.dedent()
559
560 # total num
561 code('''
562 case ${{self.c_ident}}_NUM:
563 return ${{len(self.enums)}};
564
565 default:
566 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
567 return -1;
568 }
569}
570
571/** \\brief returns the machine type for each base vector index used by NetDest
572 *
573 * \\return the MachineTYpe
574 */
575MachineType ${{self.c_ident}}_from_base_level(int type)
576{
577 switch(type) {
578''')
579
580 # For each field
581 code.indent()
582 for i,enum in enumerate(self.enums.itervalues()):
583 code(' case $i:')
584 code(' return ${{self.c_ident}}_${{enum.ident}};')
585 code.dedent()
586
587 # Trailer
588 code('''
589 default:
590 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
591 return MachineType_NUM;
592 }
593}
594
595/** \\brief The return value indicates the number of components created
596 * before a particular machine\'s components
597 *
598 * \\return the base number of components for each machine
599 */
600int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
601{
602 int base = 0;
603 switch(obj) {
604''')
605
606 # For each field
607 code.indent()
608 code(' case ${{self.c_ident}}_NUM:')
609 for enum in reversed(self.enums.values()):
610 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
611 code(' case ${{self.c_ident}}_${{enum.ident}}:')
612 code(' break;')
613 code.dedent()
614
615 code('''
616 default:
617 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
618 return -1;
619 }
620
621 return base;
622}
623
624/** \\brief returns the total number of components for each machine
625 * \\return the total number of components for each machine
626 */
627int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
628{
629 switch(obj) {
630''')
631
632 # For each field
633 for enum in self.enums.itervalues():
634 code('''
635 case ${{self.c_ident}}_${{enum.ident}}:
636 return ${{enum.ident}}_Controller::getNumControllers();
637''')
638
639 # total num
640 code('''
641 case ${{self.c_ident}}_NUM:
642 default:
643 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
644 return -1;
645 }
646}
647''')
648
649 # Write the file
650 code.write(path, "%s.cc" % self.c_ident)
651
652__all__ = [ "Type" ]
481 for enum in self.enums.itervalues():
482 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
483
484 code('''
485ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
486{
487 out << ${{self.c_ident}}_to_string(obj);
488 out << flush;
489 return out;
490}
491
492string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
493{
494 switch(obj) {
495''')
496
497 # For each field
498 code.indent()
499 for enum in self.enums.itervalues():
500 code(' case ${{self.c_ident}}_${{enum.ident}}:')
501 code(' return "${{enum.ident}}";')
502 code.dedent()
503
504 # Trailer
505 code('''
506 default:
507 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
508 return "";
509 }
510}
511
512${{self.c_ident}} string_to_${{self.c_ident}}(const string& str)
513{
514''')
515
516 # For each field
517 code.indent()
518 code("if (false) {")
519 start = "} else "
520 for enum in self.enums.itervalues():
521 code('${start}if (str == "${{enum.ident}}") {')
522 code(' return ${{self.c_ident}}_${{enum.ident}};')
523 code.dedent()
524
525 code('''
526 } else {
527 WARN_EXPR(str);
528 ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
529 }
530}
531
532${{self.c_ident}}& operator++(${{self.c_ident}}& e) {
533 assert(e < ${{self.c_ident}}_NUM);
534 return e = ${{self.c_ident}}(e+1);
535}
536''')
537
538 # MachineType hack used to set the base level and number of
539 # components for each Machine
540 if self.isMachineType:
541 code('''
542/** \\brief returns the base vector index for each machine type to be used by NetDest
543 *
544 * \\return the base vector index for each machine type to be used by NetDest
545 * \\see NetDest.hh
546 */
547int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
548{
549 switch(obj) {
550''')
551
552 # For each field
553 code.indent()
554 for i,enum in enumerate(self.enums.itervalues()):
555 code(' case ${{self.c_ident}}_${{enum.ident}}:')
556 code(' return $i;')
557 code.dedent()
558
559 # total num
560 code('''
561 case ${{self.c_ident}}_NUM:
562 return ${{len(self.enums)}};
563
564 default:
565 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
566 return -1;
567 }
568}
569
570/** \\brief returns the machine type for each base vector index used by NetDest
571 *
572 * \\return the MachineTYpe
573 */
574MachineType ${{self.c_ident}}_from_base_level(int type)
575{
576 switch(type) {
577''')
578
579 # For each field
580 code.indent()
581 for i,enum in enumerate(self.enums.itervalues()):
582 code(' case $i:')
583 code(' return ${{self.c_ident}}_${{enum.ident}};')
584 code.dedent()
585
586 # Trailer
587 code('''
588 default:
589 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
590 return MachineType_NUM;
591 }
592}
593
594/** \\brief The return value indicates the number of components created
595 * before a particular machine\'s components
596 *
597 * \\return the base number of components for each machine
598 */
599int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
600{
601 int base = 0;
602 switch(obj) {
603''')
604
605 # For each field
606 code.indent()
607 code(' case ${{self.c_ident}}_NUM:')
608 for enum in reversed(self.enums.values()):
609 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
610 code(' case ${{self.c_ident}}_${{enum.ident}}:')
611 code(' break;')
612 code.dedent()
613
614 code('''
615 default:
616 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
617 return -1;
618 }
619
620 return base;
621}
622
623/** \\brief returns the total number of components for each machine
624 * \\return the total number of components for each machine
625 */
626int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
627{
628 switch(obj) {
629''')
630
631 # For each field
632 for enum in self.enums.itervalues():
633 code('''
634 case ${{self.c_ident}}_${{enum.ident}}:
635 return ${{enum.ident}}_Controller::getNumControllers();
636''')
637
638 # total num
639 code('''
640 case ${{self.c_ident}}_NUM:
641 default:
642 ERROR_MSG("Invalid range for type ${{self.c_ident}}");
643 return -1;
644 }
645}
646''')
647
648 # Write the file
649 code.write(path, "%s.cc" % self.c_ident)
650
651__all__ = [ "Type" ]