Type.py (12065:e3e51756dfef) Type.py (12334:e0ab29a34764)
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>')
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>')
463 code('#include "base/misc.hh"')
463 code('#include "base/logging.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''')
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
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''')
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"
564#include "base/logging.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" ]
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" ]