Type.py (9499:b03b556a8fbb) Type.py (9500:9c3e3d1c7a87)
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
32from slicc.symbols.Var import Var
33
34class DataMember(PairContainer):
35 def __init__(self, ident, type, pairs, init_code):
36 super(DataMember, self).__init__(pairs)
37 self.ident = ident
38 self.type = type
39 self.init_code = init_code
40
41class Enumeration(PairContainer):
42 def __init__(self, ident, pairs):
43 super(Enumeration, self).__init__(pairs)
44 self.ident = ident
45
46class Method(object):
47 def __init__(self, return_type, param_types):
48 self.return_type = return_type
49 self.param_types = param_types
50
51class Type(Symbol):
52 def __init__(self, table, ident, location, pairs, machine=None):
53 super(Type, self).__init__(table, ident, location, pairs)
54 self.c_ident = ident
55 self.abstract_ident = ""
56 if machine:
57 if self.isExternal or self.isPrimitive:
58 if "external_name" in self:
59 self.c_ident = self["external_name"]
60 else:
61 # Append with machine name
62 self.c_ident = "%s_%s" % (machine, ident)
63
64 self.pairs.setdefault("desc", "No description avaliable")
65
66 # check for interface that this Type implements
67 if "interface" in self:
68 interface = self["interface"]
69 if interface in ("Message", "NetworkMessage"):
70 self["message"] = "yes"
71 if interface == "NetworkMessage":
72 self["networkmessage"] = "yes"
73
74 # FIXME - all of the following id comparisons are fragile hacks
75 if self.ident in ("CacheMemory", "NewCacheMemory",
76 "TLCCacheMemory", "DNUCACacheMemory",
77 "DNUCABankCacheMemory", "L2BankCacheMemory",
78 "CompressedCacheMemory", "PrefetchCacheMemory"):
79 self["cache"] = "yes"
80
81 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
82 self["tbe"] = "yes"
83
84 if self.ident == "NewTBETable":
85 self["newtbe"] = "yes"
86
87 if self.ident == "TimerTable":
88 self["timer"] = "yes"
89
90 if self.ident == "DirectoryMemory":
91 self["dir"] = "yes"
92
93 if self.ident == "PersistentTable":
94 self["persistent"] = "yes"
95
96 if self.ident == "Prefetcher":
97 self["prefetcher"] = "yes"
98
99 if self.ident == "DNUCA_Movement":
100 self["mover"] = "yes"
101
102 self.isMachineType = (ident == "MachineType")
103
104 self.isStateDecl = ("state_decl" in self)
105 self.statePermPairs = []
106
107 self.data_members = orderdict()
108
109 # Methods
110 self.methods = {}
111 self.functions = {}
112
113 # Enums
114 self.enums = orderdict()
115
116 @property
117 def isPrimitive(self):
118 return "primitive" in self
119 @property
120 def isNetworkMessage(self):
121 return "networkmessage" in self
122 @property
123 def isMessage(self):
124 return "message" in self
125 @property
126 def isBuffer(self):
127 return "buffer" in self
128 @property
129 def isInPort(self):
130 return "inport" in self
131 @property
132 def isOutPort(self):
133 return "outport" in self
134 @property
135 def isEnumeration(self):
136 return "enumeration" in self
137 @property
138 def isExternal(self):
139 return "external" in self
140 @property
141 def isGlobal(self):
142 return "global" in self
143 @property
144 def isInterface(self):
145 return "interface" in self
146
147 # Return false on error
148 def addDataMember(self, ident, type, pairs, init_code):
149 if ident in self.data_members:
150 return False
151
152 member = DataMember(ident, type, pairs, init_code)
153 self.data_members[ident] = member
154
155 var = Var(self.symtab, ident, self.location, type,
156 "m_%s" % ident, {}, None)
157 self.symtab.registerSym(ident, var)
158 return True
159
160 def dataMemberType(self, ident):
161 return self.data_members[ident].type
162
163 def methodId(self, name, param_type_vec):
164 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
165
166 def methodIdAbstract(self, name, param_type_vec):
167 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
168
169 def statePermPairAdd(self, state_name, perm_name):
170 self.statePermPairs.append([state_name, perm_name])
171
172 def addMethod(self, name, return_type, param_type_vec):
173 ident = self.methodId(name, param_type_vec)
174 if ident in self.methods:
175 return False
176
177 self.methods[ident] = Method(return_type, param_type_vec)
178 return True
179
180 # Ideally either this function or the one above should exist. But
181 # methods and functions have different structures right now.
182 # Hence, these are different, at least for the time being.
183 def addFunc(self, func):
184 ident = self.methodId(func.ident, func.param_types)
185 if ident in self.functions:
186 return False
187
188 self.functions[ident] = func
189 return True
190
191 def addEnum(self, ident, pairs):
192 if ident in self.enums:
193 return False
194
195 self.enums[ident] = Enumeration(ident, pairs)
196
197 # Add default
198 if "default" not in self:
199 self["default"] = "%s_NUM" % self.c_ident
200
201 return True
202
203 def writeCodeFiles(self, path, includes):
204 if self.isExternal:
205 # Do nothing
206 pass
207 elif self.isEnumeration:
208 self.printEnumHH(path)
209 self.printEnumCC(path)
210 else:
211 # User defined structs and messages
212 self.printTypeHH(path)
213 self.printTypeCC(path)
214
215 def printTypeHH(self, path):
216 code = self.symtab.codeFormatter()
217 code('''
218/** \\file ${{self.c_ident}}.hh
219 *
220 *
221 * Auto generated C++ code started by $__file__:$__line__
222 */
223
224#ifndef __${{self.c_ident}}_HH__
225#define __${{self.c_ident}}_HH__
226
227#include <iostream>
228
229#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
230''')
231
232 for dm in self.data_members.values():
233 if not dm.type.isPrimitive:
234 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
235
236 parent = ""
237 if "interface" in self:
238 code('#include "mem/protocol/$0.hh"', self["interface"])
239 parent = " : public %s" % self["interface"]
240
241 code('''
242$klass ${{self.c_ident}}$parent
243{
244 public:
245 ${{self.c_ident}}
246''', klass="class")
247
248 if self.isMessage:
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
32from slicc.symbols.Var import Var
33
34class DataMember(PairContainer):
35 def __init__(self, ident, type, pairs, init_code):
36 super(DataMember, self).__init__(pairs)
37 self.ident = ident
38 self.type = type
39 self.init_code = init_code
40
41class Enumeration(PairContainer):
42 def __init__(self, ident, pairs):
43 super(Enumeration, self).__init__(pairs)
44 self.ident = ident
45
46class Method(object):
47 def __init__(self, return_type, param_types):
48 self.return_type = return_type
49 self.param_types = param_types
50
51class Type(Symbol):
52 def __init__(self, table, ident, location, pairs, machine=None):
53 super(Type, self).__init__(table, ident, location, pairs)
54 self.c_ident = ident
55 self.abstract_ident = ""
56 if machine:
57 if self.isExternal or self.isPrimitive:
58 if "external_name" in self:
59 self.c_ident = self["external_name"]
60 else:
61 # Append with machine name
62 self.c_ident = "%s_%s" % (machine, ident)
63
64 self.pairs.setdefault("desc", "No description avaliable")
65
66 # check for interface that this Type implements
67 if "interface" in self:
68 interface = self["interface"]
69 if interface in ("Message", "NetworkMessage"):
70 self["message"] = "yes"
71 if interface == "NetworkMessage":
72 self["networkmessage"] = "yes"
73
74 # FIXME - all of the following id comparisons are fragile hacks
75 if self.ident in ("CacheMemory", "NewCacheMemory",
76 "TLCCacheMemory", "DNUCACacheMemory",
77 "DNUCABankCacheMemory", "L2BankCacheMemory",
78 "CompressedCacheMemory", "PrefetchCacheMemory"):
79 self["cache"] = "yes"
80
81 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
82 self["tbe"] = "yes"
83
84 if self.ident == "NewTBETable":
85 self["newtbe"] = "yes"
86
87 if self.ident == "TimerTable":
88 self["timer"] = "yes"
89
90 if self.ident == "DirectoryMemory":
91 self["dir"] = "yes"
92
93 if self.ident == "PersistentTable":
94 self["persistent"] = "yes"
95
96 if self.ident == "Prefetcher":
97 self["prefetcher"] = "yes"
98
99 if self.ident == "DNUCA_Movement":
100 self["mover"] = "yes"
101
102 self.isMachineType = (ident == "MachineType")
103
104 self.isStateDecl = ("state_decl" in self)
105 self.statePermPairs = []
106
107 self.data_members = orderdict()
108
109 # Methods
110 self.methods = {}
111 self.functions = {}
112
113 # Enums
114 self.enums = orderdict()
115
116 @property
117 def isPrimitive(self):
118 return "primitive" in self
119 @property
120 def isNetworkMessage(self):
121 return "networkmessage" in self
122 @property
123 def isMessage(self):
124 return "message" in self
125 @property
126 def isBuffer(self):
127 return "buffer" in self
128 @property
129 def isInPort(self):
130 return "inport" in self
131 @property
132 def isOutPort(self):
133 return "outport" in self
134 @property
135 def isEnumeration(self):
136 return "enumeration" in self
137 @property
138 def isExternal(self):
139 return "external" in self
140 @property
141 def isGlobal(self):
142 return "global" in self
143 @property
144 def isInterface(self):
145 return "interface" in self
146
147 # Return false on error
148 def addDataMember(self, ident, type, pairs, init_code):
149 if ident in self.data_members:
150 return False
151
152 member = DataMember(ident, type, pairs, init_code)
153 self.data_members[ident] = member
154
155 var = Var(self.symtab, ident, self.location, type,
156 "m_%s" % ident, {}, None)
157 self.symtab.registerSym(ident, var)
158 return True
159
160 def dataMemberType(self, ident):
161 return self.data_members[ident].type
162
163 def methodId(self, name, param_type_vec):
164 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
165
166 def methodIdAbstract(self, name, param_type_vec):
167 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
168
169 def statePermPairAdd(self, state_name, perm_name):
170 self.statePermPairs.append([state_name, perm_name])
171
172 def addMethod(self, name, return_type, param_type_vec):
173 ident = self.methodId(name, param_type_vec)
174 if ident in self.methods:
175 return False
176
177 self.methods[ident] = Method(return_type, param_type_vec)
178 return True
179
180 # Ideally either this function or the one above should exist. But
181 # methods and functions have different structures right now.
182 # Hence, these are different, at least for the time being.
183 def addFunc(self, func):
184 ident = self.methodId(func.ident, func.param_types)
185 if ident in self.functions:
186 return False
187
188 self.functions[ident] = func
189 return True
190
191 def addEnum(self, ident, pairs):
192 if ident in self.enums:
193 return False
194
195 self.enums[ident] = Enumeration(ident, pairs)
196
197 # Add default
198 if "default" not in self:
199 self["default"] = "%s_NUM" % self.c_ident
200
201 return True
202
203 def writeCodeFiles(self, path, includes):
204 if self.isExternal:
205 # Do nothing
206 pass
207 elif self.isEnumeration:
208 self.printEnumHH(path)
209 self.printEnumCC(path)
210 else:
211 # User defined structs and messages
212 self.printTypeHH(path)
213 self.printTypeCC(path)
214
215 def printTypeHH(self, path):
216 code = self.symtab.codeFormatter()
217 code('''
218/** \\file ${{self.c_ident}}.hh
219 *
220 *
221 * Auto generated C++ code started by $__file__:$__line__
222 */
223
224#ifndef __${{self.c_ident}}_HH__
225#define __${{self.c_ident}}_HH__
226
227#include <iostream>
228
229#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
230''')
231
232 for dm in self.data_members.values():
233 if not dm.type.isPrimitive:
234 code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
235
236 parent = ""
237 if "interface" in self:
238 code('#include "mem/protocol/$0.hh"', self["interface"])
239 parent = " : public %s" % self["interface"]
240
241 code('''
242$klass ${{self.c_ident}}$parent
243{
244 public:
245 ${{self.c_ident}}
246''', klass="class")
247
248 if self.isMessage:
249 code('(Time curTime) : %s(curTime) {' % self["interface"])
249 code('(Cycles curTime) : %s(curTime) {' % self["interface"])
250 else:
251 code('()\n\t\t{')
252
253 code.indent()
254 if not self.isGlobal:
255 code.indent()
256 for dm in self.data_members.values():
257 ident = dm.ident
258 if "default" in dm:
259 # look for default value
260 code('m_$ident = ${{dm["default"]}}; // default for this field')
261 elif "default" in dm.type:
262 # Look for the type default
263 tid = dm.type.c_ident
264 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
265 else:
266 code('// m_$ident has no default')
267 code.dedent()
268 code('}')
269
270 # ******** Copy constructor ********
271 if not self.isGlobal:
272 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
273
274 # Call superclass constructor
275 if "interface" in self:
276 code(' : ${{self["interface"]}}(other)')
277
278 code('{')
279 code.indent()
280
281 for dm in self.data_members.values():
282 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
283
284 code.dedent()
285 code('}')
286
287 # ******** Full init constructor ********
288 if not self.isGlobal:
289 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
290 for dm in self.data_members.itervalues() ]
291 params = ', '.join(params)
292
293 if self.isMessage:
250 else:
251 code('()\n\t\t{')
252
253 code.indent()
254 if not self.isGlobal:
255 code.indent()
256 for dm in self.data_members.values():
257 ident = dm.ident
258 if "default" in dm:
259 # look for default value
260 code('m_$ident = ${{dm["default"]}}; // default for this field')
261 elif "default" in dm.type:
262 # Look for the type default
263 tid = dm.type.c_ident
264 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
265 else:
266 code('// m_$ident has no default')
267 code.dedent()
268 code('}')
269
270 # ******** Copy constructor ********
271 if not self.isGlobal:
272 code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
273
274 # Call superclass constructor
275 if "interface" in self:
276 code(' : ${{self["interface"]}}(other)')
277
278 code('{')
279 code.indent()
280
281 for dm in self.data_members.values():
282 code('m_${{dm.ident}} = other.m_${{dm.ident}};')
283
284 code.dedent()
285 code('}')
286
287 # ******** Full init constructor ********
288 if not self.isGlobal:
289 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
290 for dm in self.data_members.itervalues() ]
291 params = ', '.join(params)
292
293 if self.isMessage:
294 params = "const Time curTime, " + params
294 params = "const Cycles curTime, " + params
295
296 code('${{self.c_ident}}($params)')
297
298 # Call superclass constructor
299 if "interface" in self:
300 if self.isMessage:
301 code(' : ${{self["interface"]}}(curTime)')
302 else:
303 code(' : ${{self["interface"]}}()')
304
305 code('{')
306 code.indent()
307 for dm in self.data_members.values():
308 code('m_${{dm.ident}} = local_${{dm.ident}};')
309 if "nextLineCallHack" in dm:
310 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
311
312 code.dedent()
313 code('}')
314
315 # create a clone member
316 code('''
317${{self.c_ident}}*
318clone() const
319{
320 return new ${{self.c_ident}}(*this);
321}
322''')
323
324 if not self.isGlobal:
325 # const Get methods for each field
326 code('// Const accessors methods for each field')
327 for dm in self.data_members.values():
328 code('''
329/** \\brief Const accessor method for ${{dm.ident}} field.
330 * \\return ${{dm.ident}} field
331 */
332const ${{dm.type.c_ident}}&
333get${{dm.ident}}() const
334{
335 return m_${{dm.ident}};
336}
337''')
338
339 # Non-const Get methods for each field
340 code('// Non const Accessors methods for each field')
341 for dm in self.data_members.values():
342 code('''
343/** \\brief Non-const accessor method for ${{dm.ident}} field.
344 * \\return ${{dm.ident}} field
345 */
346${{dm.type.c_ident}}&
347get${{dm.ident}}()
348{
349 return m_${{dm.ident}};
350}
351''')
352
353 #Set methods for each field
354 code('// Mutator methods for each field')
355 for dm in self.data_members.values():
356 code('''
357/** \\brief Mutator method for ${{dm.ident}} field */
358void
359set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
360{
361 m_${{dm.ident}} = local_${{dm.ident}};
362}
363''')
364
365 code('void print(std::ostream& out) const;')
366 code.dedent()
367 code(' //private:')
368 code.indent()
369
370 # Data members for each field
371 for dm in self.data_members.values():
372 if "abstract" not in dm:
373 const = ""
374 init = ""
375
376 # global structure
377 if self.isGlobal:
378 const = "static const "
379
380 # init value
381 if dm.init_code:
382 # only global structure can have init value here
383 assert self.isGlobal
384 init = " = %s" % (dm.init_code)
385
386 if "desc" in dm:
387 code('/** ${{dm["desc"]}} */')
388
389 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
390
391 # Prototypes for functions defined for the Type
392 for item in self.functions:
393 proto = self.functions[item].prototype
394 if proto:
395 code('$proto')
396
397 code.dedent()
398 code('};')
399
400 code('''
401inline std::ostream&
402operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
403{
404 obj.print(out);
405 out << std::flush;
406 return out;
407}
408
409#endif // __${{self.c_ident}}_HH__
410''')
411
412 code.write(path, "%s.hh" % self.c_ident)
413
414 def printTypeCC(self, path):
415 code = self.symtab.codeFormatter()
416
417 code('''
418/** \\file ${{self.c_ident}}.cc
419 *
420 * Auto generated C++ code started by $__file__:$__line__
421 */
422
423#include <iostream>
424
425#include "mem/protocol/${{self.c_ident}}.hh"
426#include "mem/ruby/common/Global.hh"
427#include "mem/ruby/system/System.hh"
428
429using namespace std;
430''')
431
432 code('''
433/** \\brief Print the state of this object */
434void
435${{self.c_ident}}::print(ostream& out) const
436{
437 out << "[${{self.c_ident}}: ";
438''')
439
440 # For each field
441 code.indent()
442 for dm in self.data_members.values():
443 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
444
445 if self.isMessage:
446 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";')
447 code.dedent()
448
449 # Trailer
450 code('''
451 out << "]";
452}''')
453
454 # print the code for the functions in the type
455 for item in self.functions:
456 code(self.functions[item].generateCode())
457
458 code.write(path, "%s.cc" % self.c_ident)
459
460 def printEnumHH(self, path):
461 code = self.symtab.codeFormatter()
462 code('''
463/** \\file ${{self.c_ident}}.hh
464 *
465 * Auto generated C++ code started by $__file__:$__line__
466 */
467
468#ifndef __${{self.c_ident}}_HH__
469#define __${{self.c_ident}}_HH__
470
471#include <iostream>
472#include <string>
473
474''')
475 if self.isStateDecl:
476 code('#include "mem/protocol/AccessPermission.hh"')
477
478 if self.isMachineType:
479 code('#include "base/misc.hh"')
480 code('#include "mem/protocol/GenericMachineType.hh"')
481 code('#include "mem/ruby/common/Address.hh"')
482 code('struct MachineID;')
483
484 code('''
485
486// Class definition
487/** \\enum ${{self.c_ident}}
488 * \\brief ${{self.desc}}
489 */
490enum ${{self.c_ident}} {
491 ${{self.c_ident}}_FIRST,
492''')
493
494 code.indent()
495 # For each field
496 for i,(ident,enum) in enumerate(self.enums.iteritems()):
497 desc = enum.get("desc", "No description avaliable")
498 if i == 0:
499 init = ' = %s_FIRST' % self.c_ident
500 else:
501 init = ''
502 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
503 code.dedent()
504 code('''
505 ${{self.c_ident}}_NUM
506};
507
508// Code to convert from a string to the enumeration
509${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
510
511// Code to convert state to a string
512std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
513
514// Code to increment an enumeration type
515${{self.c_ident}} &operator++(${{self.c_ident}} &e);
516''')
517
518 # MachineType hack used to set the base component id for each Machine
519 if self.isMachineType:
520 code('''
521int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
522MachineType ${{self.c_ident}}_from_base_level(int);
523int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
524int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
525''')
526
527 for enum in self.enums.itervalues():
528 if enum.ident == "DMA":
529 code('''
530MachineID map_Address_to_DMA(const Address &addr);
531''')
532 code('''
533
534MachineID get${{enum.ident}}MachineID(NodeID RubyNode);
535''')
536
537 code('''
538inline GenericMachineType
539ConvertMachToGenericMach(MachineType machType)
540{
541''')
542 for enum in self.enums.itervalues():
543 code('''
544 if (machType == MachineType_${{enum.ident}})
545 return GenericMachineType_${{enum.ident}};
546''')
547 code('''
548 panic("cannot convert to a GenericMachineType");
549}
550''')
551
552 if self.isStateDecl:
553 code('''
554
555// Code to convert the current state to an access permission
556AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
557
558''')
559
560 # Trailer
561 code('''
562std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
563
564#endif // __${{self.c_ident}}_HH__
565''')
566
567 code.write(path, "%s.hh" % self.c_ident)
568
569 def printEnumCC(self, path):
570 code = self.symtab.codeFormatter()
571 code('''
572/** \\file ${{self.c_ident}}.hh
573 *
574 * Auto generated C++ code started by $__file__:$__line__
575 */
576
577#include <cassert>
578#include <iostream>
579#include <string>
580
581#include "base/misc.hh"
582#include "mem/protocol/${{self.c_ident}}.hh"
583
584using namespace std;
585
586''')
587
588 if self.isStateDecl:
589 code('''
590// Code to convert the current state to an access permission
591AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
592{
593 switch(obj) {
594''')
595 # For each case
596 code.indent()
597 for statePerm in self.statePermPairs:
598 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
599 code(' return AccessPermission_${{statePerm[1]}};')
600 code.dedent()
601 code ('''
602 default:
603 panic("Unknown state access permission converstion for ${{self.c_ident}}");
604 }
605}
606
607''')
608
609 if self.isMachineType:
610 for enum in self.enums.itervalues():
611 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
612 code('#include "mem/ruby/system/MachineID.hh"')
613
614 code('''
615// Code for output operator
616ostream&
617operator<<(ostream& out, const ${{self.c_ident}}& obj)
618{
619 out << ${{self.c_ident}}_to_string(obj);
620 out << flush;
621 return out;
622}
623
624// Code to convert state to a string
625string
626${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
627{
628 switch(obj) {
629''')
630
631 # For each field
632 code.indent()
633 for enum in self.enums.itervalues():
634 code(' case ${{self.c_ident}}_${{enum.ident}}:')
635 code(' return "${{enum.ident}}";')
636 code.dedent()
637
638 # Trailer
639 code('''
640 default:
641 panic("Invalid range for type ${{self.c_ident}}");
642 }
643}
644
645// Code to convert from a string to the enumeration
646${{self.c_ident}}
647string_to_${{self.c_ident}}(const string& str)
648{
649''')
650
651 # For each field
652 start = ""
653 code.indent()
654 for enum in self.enums.itervalues():
655 code('${start}if (str == "${{enum.ident}}") {')
656 code(' return ${{self.c_ident}}_${{enum.ident}};')
657 start = "} else "
658 code.dedent()
659
660 code('''
661 } else {
662 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
663 }
664}
665
666// Code to increment an enumeration type
667${{self.c_ident}}&
668operator++(${{self.c_ident}}& e)
669{
670 assert(e < ${{self.c_ident}}_NUM);
671 return e = ${{self.c_ident}}(e+1);
672}
673''')
674
675 # MachineType hack used to set the base level and number of
676 # components for each Machine
677 if self.isMachineType:
678 code('''
679/** \\brief returns the base vector index for each machine type to be
680 * used by NetDest
681 *
682 * \\return the base vector index for each machine type to be used by NetDest
683 * \\see NetDest.hh
684 */
685int
686${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
687{
688 switch(obj) {
689''')
690
691 # For each field
692 code.indent()
693 for i,enum in enumerate(self.enums.itervalues()):
694 code(' case ${{self.c_ident}}_${{enum.ident}}:')
695 code(' return $i;')
696 code.dedent()
697
698 # total num
699 code('''
700 case ${{self.c_ident}}_NUM:
701 return ${{len(self.enums)}};
702
703 default:
704 panic("Invalid range for type ${{self.c_ident}}");
705 }
706}
707
708/** \\brief returns the machine type for each base vector index used by NetDest
709 *
710 * \\return the MachineType
711 */
712MachineType
713${{self.c_ident}}_from_base_level(int type)
714{
715 switch(type) {
716''')
717
718 # For each field
719 code.indent()
720 for i,enum in enumerate(self.enums.itervalues()):
721 code(' case $i:')
722 code(' return ${{self.c_ident}}_${{enum.ident}};')
723 code.dedent()
724
725 # Trailer
726 code('''
727 default:
728 panic("Invalid range for type ${{self.c_ident}}");
729 }
730}
731
732/** \\brief The return value indicates the number of components created
733 * before a particular machine\'s components
734 *
735 * \\return the base number of components for each machine
736 */
737int
738${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
739{
740 int base = 0;
741 switch(obj) {
742''')
743
744 # For each field
745 code.indent()
746 code(' case ${{self.c_ident}}_NUM:')
747 for enum in reversed(self.enums.values()):
748 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
749 code(' case ${{self.c_ident}}_${{enum.ident}}:')
750 code(' break;')
751 code.dedent()
752
753 code('''
754 default:
755 panic("Invalid range for type ${{self.c_ident}}");
756 }
757
758 return base;
759}
760
761/** \\brief returns the total number of components for each machine
762 * \\return the total number of components for each machine
763 */
764int
765${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
766{
767 switch(obj) {
768''')
769
770 # For each field
771 for enum in self.enums.itervalues():
772 code('''
773 case ${{self.c_ident}}_${{enum.ident}}:
774 return ${{enum.ident}}_Controller::getNumControllers();
775''')
776
777 # total num
778 code('''
779 case ${{self.c_ident}}_NUM:
780 default:
781 panic("Invalid range for type ${{self.c_ident}}");
782 }
783}
784''')
785
786 for enum in self.enums.itervalues():
787 if enum.ident == "DMA":
788 code('''
789MachineID
790map_Address_to_DMA(const Address &addr)
791{
792 MachineID dma = {MachineType_DMA, 0};
793 return dma;
794}
795''')
796
797 code('''
798
799MachineID
800get${{enum.ident}}MachineID(NodeID RubyNode)
801{
802 MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
803 return mach;
804}
805''')
806
807 # Write the file
808 code.write(path, "%s.cc" % self.c_ident)
809
810__all__ = [ "Type" ]
295
296 code('${{self.c_ident}}($params)')
297
298 # Call superclass constructor
299 if "interface" in self:
300 if self.isMessage:
301 code(' : ${{self["interface"]}}(curTime)')
302 else:
303 code(' : ${{self["interface"]}}()')
304
305 code('{')
306 code.indent()
307 for dm in self.data_members.values():
308 code('m_${{dm.ident}} = local_${{dm.ident}};')
309 if "nextLineCallHack" in dm:
310 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
311
312 code.dedent()
313 code('}')
314
315 # create a clone member
316 code('''
317${{self.c_ident}}*
318clone() const
319{
320 return new ${{self.c_ident}}(*this);
321}
322''')
323
324 if not self.isGlobal:
325 # const Get methods for each field
326 code('// Const accessors methods for each field')
327 for dm in self.data_members.values():
328 code('''
329/** \\brief Const accessor method for ${{dm.ident}} field.
330 * \\return ${{dm.ident}} field
331 */
332const ${{dm.type.c_ident}}&
333get${{dm.ident}}() const
334{
335 return m_${{dm.ident}};
336}
337''')
338
339 # Non-const Get methods for each field
340 code('// Non const Accessors methods for each field')
341 for dm in self.data_members.values():
342 code('''
343/** \\brief Non-const accessor method for ${{dm.ident}} field.
344 * \\return ${{dm.ident}} field
345 */
346${{dm.type.c_ident}}&
347get${{dm.ident}}()
348{
349 return m_${{dm.ident}};
350}
351''')
352
353 #Set methods for each field
354 code('// Mutator methods for each field')
355 for dm in self.data_members.values():
356 code('''
357/** \\brief Mutator method for ${{dm.ident}} field */
358void
359set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
360{
361 m_${{dm.ident}} = local_${{dm.ident}};
362}
363''')
364
365 code('void print(std::ostream& out) const;')
366 code.dedent()
367 code(' //private:')
368 code.indent()
369
370 # Data members for each field
371 for dm in self.data_members.values():
372 if "abstract" not in dm:
373 const = ""
374 init = ""
375
376 # global structure
377 if self.isGlobal:
378 const = "static const "
379
380 # init value
381 if dm.init_code:
382 # only global structure can have init value here
383 assert self.isGlobal
384 init = " = %s" % (dm.init_code)
385
386 if "desc" in dm:
387 code('/** ${{dm["desc"]}} */')
388
389 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
390
391 # Prototypes for functions defined for the Type
392 for item in self.functions:
393 proto = self.functions[item].prototype
394 if proto:
395 code('$proto')
396
397 code.dedent()
398 code('};')
399
400 code('''
401inline std::ostream&
402operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
403{
404 obj.print(out);
405 out << std::flush;
406 return out;
407}
408
409#endif // __${{self.c_ident}}_HH__
410''')
411
412 code.write(path, "%s.hh" % self.c_ident)
413
414 def printTypeCC(self, path):
415 code = self.symtab.codeFormatter()
416
417 code('''
418/** \\file ${{self.c_ident}}.cc
419 *
420 * Auto generated C++ code started by $__file__:$__line__
421 */
422
423#include <iostream>
424
425#include "mem/protocol/${{self.c_ident}}.hh"
426#include "mem/ruby/common/Global.hh"
427#include "mem/ruby/system/System.hh"
428
429using namespace std;
430''')
431
432 code('''
433/** \\brief Print the state of this object */
434void
435${{self.c_ident}}::print(ostream& out) const
436{
437 out << "[${{self.c_ident}}: ";
438''')
439
440 # For each field
441 code.indent()
442 for dm in self.data_members.values():
443 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
444
445 if self.isMessage:
446 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";')
447 code.dedent()
448
449 # Trailer
450 code('''
451 out << "]";
452}''')
453
454 # print the code for the functions in the type
455 for item in self.functions:
456 code(self.functions[item].generateCode())
457
458 code.write(path, "%s.cc" % self.c_ident)
459
460 def printEnumHH(self, path):
461 code = self.symtab.codeFormatter()
462 code('''
463/** \\file ${{self.c_ident}}.hh
464 *
465 * Auto generated C++ code started by $__file__:$__line__
466 */
467
468#ifndef __${{self.c_ident}}_HH__
469#define __${{self.c_ident}}_HH__
470
471#include <iostream>
472#include <string>
473
474''')
475 if self.isStateDecl:
476 code('#include "mem/protocol/AccessPermission.hh"')
477
478 if self.isMachineType:
479 code('#include "base/misc.hh"')
480 code('#include "mem/protocol/GenericMachineType.hh"')
481 code('#include "mem/ruby/common/Address.hh"')
482 code('struct MachineID;')
483
484 code('''
485
486// Class definition
487/** \\enum ${{self.c_ident}}
488 * \\brief ${{self.desc}}
489 */
490enum ${{self.c_ident}} {
491 ${{self.c_ident}}_FIRST,
492''')
493
494 code.indent()
495 # For each field
496 for i,(ident,enum) in enumerate(self.enums.iteritems()):
497 desc = enum.get("desc", "No description avaliable")
498 if i == 0:
499 init = ' = %s_FIRST' % self.c_ident
500 else:
501 init = ''
502 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
503 code.dedent()
504 code('''
505 ${{self.c_ident}}_NUM
506};
507
508// Code to convert from a string to the enumeration
509${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
510
511// Code to convert state to a string
512std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
513
514// Code to increment an enumeration type
515${{self.c_ident}} &operator++(${{self.c_ident}} &e);
516''')
517
518 # MachineType hack used to set the base component id for each Machine
519 if self.isMachineType:
520 code('''
521int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
522MachineType ${{self.c_ident}}_from_base_level(int);
523int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
524int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
525''')
526
527 for enum in self.enums.itervalues():
528 if enum.ident == "DMA":
529 code('''
530MachineID map_Address_to_DMA(const Address &addr);
531''')
532 code('''
533
534MachineID get${{enum.ident}}MachineID(NodeID RubyNode);
535''')
536
537 code('''
538inline GenericMachineType
539ConvertMachToGenericMach(MachineType machType)
540{
541''')
542 for enum in self.enums.itervalues():
543 code('''
544 if (machType == MachineType_${{enum.ident}})
545 return GenericMachineType_${{enum.ident}};
546''')
547 code('''
548 panic("cannot convert to a GenericMachineType");
549}
550''')
551
552 if self.isStateDecl:
553 code('''
554
555// Code to convert the current state to an access permission
556AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
557
558''')
559
560 # Trailer
561 code('''
562std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
563
564#endif // __${{self.c_ident}}_HH__
565''')
566
567 code.write(path, "%s.hh" % self.c_ident)
568
569 def printEnumCC(self, path):
570 code = self.symtab.codeFormatter()
571 code('''
572/** \\file ${{self.c_ident}}.hh
573 *
574 * Auto generated C++ code started by $__file__:$__line__
575 */
576
577#include <cassert>
578#include <iostream>
579#include <string>
580
581#include "base/misc.hh"
582#include "mem/protocol/${{self.c_ident}}.hh"
583
584using namespace std;
585
586''')
587
588 if self.isStateDecl:
589 code('''
590// Code to convert the current state to an access permission
591AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
592{
593 switch(obj) {
594''')
595 # For each case
596 code.indent()
597 for statePerm in self.statePermPairs:
598 code(' case ${{self.c_ident}}_${{statePerm[0]}}:')
599 code(' return AccessPermission_${{statePerm[1]}};')
600 code.dedent()
601 code ('''
602 default:
603 panic("Unknown state access permission converstion for ${{self.c_ident}}");
604 }
605}
606
607''')
608
609 if self.isMachineType:
610 for enum in self.enums.itervalues():
611 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
612 code('#include "mem/ruby/system/MachineID.hh"')
613
614 code('''
615// Code for output operator
616ostream&
617operator<<(ostream& out, const ${{self.c_ident}}& obj)
618{
619 out << ${{self.c_ident}}_to_string(obj);
620 out << flush;
621 return out;
622}
623
624// Code to convert state to a string
625string
626${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
627{
628 switch(obj) {
629''')
630
631 # For each field
632 code.indent()
633 for enum in self.enums.itervalues():
634 code(' case ${{self.c_ident}}_${{enum.ident}}:')
635 code(' return "${{enum.ident}}";')
636 code.dedent()
637
638 # Trailer
639 code('''
640 default:
641 panic("Invalid range for type ${{self.c_ident}}");
642 }
643}
644
645// Code to convert from a string to the enumeration
646${{self.c_ident}}
647string_to_${{self.c_ident}}(const string& str)
648{
649''')
650
651 # For each field
652 start = ""
653 code.indent()
654 for enum in self.enums.itervalues():
655 code('${start}if (str == "${{enum.ident}}") {')
656 code(' return ${{self.c_ident}}_${{enum.ident}};')
657 start = "} else "
658 code.dedent()
659
660 code('''
661 } else {
662 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
663 }
664}
665
666// Code to increment an enumeration type
667${{self.c_ident}}&
668operator++(${{self.c_ident}}& e)
669{
670 assert(e < ${{self.c_ident}}_NUM);
671 return e = ${{self.c_ident}}(e+1);
672}
673''')
674
675 # MachineType hack used to set the base level and number of
676 # components for each Machine
677 if self.isMachineType:
678 code('''
679/** \\brief returns the base vector index for each machine type to be
680 * used by NetDest
681 *
682 * \\return the base vector index for each machine type to be used by NetDest
683 * \\see NetDest.hh
684 */
685int
686${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
687{
688 switch(obj) {
689''')
690
691 # For each field
692 code.indent()
693 for i,enum in enumerate(self.enums.itervalues()):
694 code(' case ${{self.c_ident}}_${{enum.ident}}:')
695 code(' return $i;')
696 code.dedent()
697
698 # total num
699 code('''
700 case ${{self.c_ident}}_NUM:
701 return ${{len(self.enums)}};
702
703 default:
704 panic("Invalid range for type ${{self.c_ident}}");
705 }
706}
707
708/** \\brief returns the machine type for each base vector index used by NetDest
709 *
710 * \\return the MachineType
711 */
712MachineType
713${{self.c_ident}}_from_base_level(int type)
714{
715 switch(type) {
716''')
717
718 # For each field
719 code.indent()
720 for i,enum in enumerate(self.enums.itervalues()):
721 code(' case $i:')
722 code(' return ${{self.c_ident}}_${{enum.ident}};')
723 code.dedent()
724
725 # Trailer
726 code('''
727 default:
728 panic("Invalid range for type ${{self.c_ident}}");
729 }
730}
731
732/** \\brief The return value indicates the number of components created
733 * before a particular machine\'s components
734 *
735 * \\return the base number of components for each machine
736 */
737int
738${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
739{
740 int base = 0;
741 switch(obj) {
742''')
743
744 # For each field
745 code.indent()
746 code(' case ${{self.c_ident}}_NUM:')
747 for enum in reversed(self.enums.values()):
748 code(' base += ${{enum.ident}}_Controller::getNumControllers();')
749 code(' case ${{self.c_ident}}_${{enum.ident}}:')
750 code(' break;')
751 code.dedent()
752
753 code('''
754 default:
755 panic("Invalid range for type ${{self.c_ident}}");
756 }
757
758 return base;
759}
760
761/** \\brief returns the total number of components for each machine
762 * \\return the total number of components for each machine
763 */
764int
765${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
766{
767 switch(obj) {
768''')
769
770 # For each field
771 for enum in self.enums.itervalues():
772 code('''
773 case ${{self.c_ident}}_${{enum.ident}}:
774 return ${{enum.ident}}_Controller::getNumControllers();
775''')
776
777 # total num
778 code('''
779 case ${{self.c_ident}}_NUM:
780 default:
781 panic("Invalid range for type ${{self.c_ident}}");
782 }
783}
784''')
785
786 for enum in self.enums.itervalues():
787 if enum.ident == "DMA":
788 code('''
789MachineID
790map_Address_to_DMA(const Address &addr)
791{
792 MachineID dma = {MachineType_DMA, 0};
793 return dma;
794}
795''')
796
797 code('''
798
799MachineID
800get${{enum.ident}}MachineID(NodeID RubyNode)
801{
802 MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
803 return mach;
804}
805''')
806
807 # Write the file
808 code.write(path, "%s.cc" % self.c_ident)
809
810__all__ = [ "Type" ]