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