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